为什么不可见的 TableView 会覆盖标签?
Why is an invisible TableView covering up a label?
我有一个奇怪的 GUI 问题。我正在使用 JavaFX 制作应用程序。该应用程序有不同的页面,每个页面都有一个标题、标签和 tableView。让我们关注欢迎页面。如果我只添加一个 tableView 到我的 vbox,一切看起来都很正常。
vbox.getChildren().addAll(title, subtitle, reqTable);
但是当我添加所有三个 tableView 时,标题下方的标签被截断了。桌子甚至还不可见!
vbox.getChildren().addAll(title, subtitle, reqTable, tempTable, ontTable);
知道为什么会这样吗?这是我的完整代码。谢谢!
package FLOOR;
// --- Imports
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
// --- Main Class
public class Example extends Application {
// --- All Pages
final Page[] pages = new Page[] {
new Page("Welcome!",
"Use the File menu to... \n"),
};
// --- All Tables
TableView<ObservableList<StringProperty>> reqTable = new TableView<>();
TableView<ObservableList<StringProperty>> tempTable = new TableView<>();
TableView<ObservableList<StringProperty>> ontTable = new TableView<>();
// --- Current Page
final Label title = new Label();
final Label subtitle = new Label();
// --- Main
public static void main(String[] args) {
launch(args);
}
// --- Start
@Override
public void start(Stage stage) {
// --- Stage & Scene
stage.setTitle("APP");
Scene scene = new Scene(new VBox(), 900, 500);
MenuBar menuBar = new MenuBar();
// --- VBox
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.setPadding(new Insets(5, 20, 0, 20));
vbox.getChildren().addAll(title, subtitle, reqTable, tempTable, ontTable);
//vbox.getChildren().addAll(title, subtitle, reqTable);
reqTable.setVisible(false);
tempTable.setVisible(false);
ontTable.setVisible(false);
reqTable.setMinHeight(300);
tempTable.setMinHeight(300);
ontTable.setMinHeight(300);
reqTable.translateYProperty().set(100);
tempTable.translateYProperty().set(-100);
ontTable.translateYProperty().set(-300);
// --- Welcome Page
title.setFont(new Font("Arial", 24));
title.translateYProperty().set(10);
title.setText(pages[0].title);
subtitle.setText(pages[0].subtitle);
subtitle.setMinHeight(10);
// --- Menus
// --- File Menu
// --- Import Submenu
Menu menuFile = new Menu("File");
Menu importMenu = new Menu("Import");
MenuItem opt1 = new MenuItem("opt_1");
MenuItem opt2 = new MenuItem("opt_2");
MenuItem opt3 = new MenuItem("opt_3");
importMenu.getItems().addAll(opt1, opt2, opt3);
MenuItem export = new MenuItem("Export");
MenuItem exit = new MenuItem("Exit");
menuFile.getItems().addAll(importMenu, export, new SeparatorMenuItem(), exit);
menuBar.getMenus().addAll(menuFile);
// --- Show
((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);
stage.setScene(scene);
stage.show();
}
// Page Class
private class Page {
public String title;
public String subtitle;
public Page(String title, String subtitle) {
this.title = title;
this.subtitle = subtitle;
}
}
}
请这样修改代码,然后检查。
删除这一行:subtitle.setMinHeight(10);或设置:subtitle.setMinHeight(50);
subtitle.setMinHeight(50);
这个答案是在 Keyur 写他的时候写的。 Keyur 的回答是正确的,但鉴于我已经写了所有这些,我还是 post :-)
看不见的table没有遮住字幕标签
您将字幕的最小高度设置为10:
subtitle.setMinHeight(10);
当没有足够的空间以首选大小显示布局区域中的所有内容时,布局窗格将开始缩小其中项目的大小,直到达到最小大小的所有内容。这就是这里发生的情况,VBox 布局管理器正在将字幕的大小减小到您设置的最小大小。
如果您删除最小高度设置,则字幕标签将不会被截断。
您可以将最小高度设置为首选高度:
subtitle.setMinHeight(Control.USE_PREF_SIZE);
这有时很有用,但在这种情况下是不必要的(这里根本不需要设置最小高度,因为 VBox 布局管理器的默认行为会为其分配足够的 space 给标签完全垂直显示)。
不可见的项目仍然占据布局 space,即使您看不到它们。想象一下,如果你的房间有一扇看不见的玻璃门,而你试图离开房间,你会撞到头。会痛的。我已经做到了。好痛。
如果你也不希望不可见节点占用布局space那么你需要将其设置为非托管,参见:
- JavaFX - setVisible doesn't "hide" the element
其他布局建议
大部分与您的问题没有直接关系,请忽略。只是一些背景信息。
您已经在使用布局窗格来布置项目(VBox)。您不应为放置在布局窗格中的项目设置翻译值。翻译值(translateX 和 translateY)实际上应该只是用于临时移动事物,例如 OS X 框样式的弹跳动画。相反,布局应该通过 layoutX 和 layoutY 值进行管理。当您使用布局管理器时,布局管理器负责设置 layoutX 和 layoutY 值,因此您不必设置任何转换值或布局值。
相反,您在布局管理器上为其管理的节点设置布局约束。例如,对于 VBox,要通过边距偏移某些项目,您可以使用 VBox.setMargin(node)
而不是更改翻译值。设置转换值的一个问题是布局管理器会忽略它们,因此尽管您可能会移动一个节点,布局管理器不会自动正确设置其他托管节点的布局,并且您可能会遇到奇怪的重叠问题(尽管那不是'您在这里遇到的问题的根源)。
Gluon SceneBuilder 是学习更多关于 JavaFX 布局的好工具(即使您不想使用 FXML)。
学习布局的一个很好的例子是Layout sans tears. Unfortunately the example is a bit old and uses deprecated builder code, but the basic concepts are still valid and the ideas are easy enough to transfer into more modern code. Oracle also have a layout tutorial,但不幸的是,它远非全面,事实上,woeful这个词浮现在脑海中......
Scenic View 是一个很好的工具,可用于了解应用程序的布局(以及解决可能出现的问题,就像您在此处遇到的那样)。
为防止您的内容变得小于其首选大小,您可以将其放在 ScrollPane 中,并在内容溢出可用区域(如网页)时让用户滚动。
我有一个奇怪的 GUI 问题。我正在使用 JavaFX 制作应用程序。该应用程序有不同的页面,每个页面都有一个标题、标签和 tableView。让我们关注欢迎页面。如果我只添加一个 tableView 到我的 vbox,一切看起来都很正常。
vbox.getChildren().addAll(title, subtitle, reqTable);
但是当我添加所有三个 tableView 时,标题下方的标签被截断了。桌子甚至还不可见!
vbox.getChildren().addAll(title, subtitle, reqTable, tempTable, ontTable);
知道为什么会这样吗?这是我的完整代码。谢谢!
package FLOOR;
// --- Imports
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
// --- Main Class
public class Example extends Application {
// --- All Pages
final Page[] pages = new Page[] {
new Page("Welcome!",
"Use the File menu to... \n"),
};
// --- All Tables
TableView<ObservableList<StringProperty>> reqTable = new TableView<>();
TableView<ObservableList<StringProperty>> tempTable = new TableView<>();
TableView<ObservableList<StringProperty>> ontTable = new TableView<>();
// --- Current Page
final Label title = new Label();
final Label subtitle = new Label();
// --- Main
public static void main(String[] args) {
launch(args);
}
// --- Start
@Override
public void start(Stage stage) {
// --- Stage & Scene
stage.setTitle("APP");
Scene scene = new Scene(new VBox(), 900, 500);
MenuBar menuBar = new MenuBar();
// --- VBox
final VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
vbox.setSpacing(10);
vbox.setPadding(new Insets(5, 20, 0, 20));
vbox.getChildren().addAll(title, subtitle, reqTable, tempTable, ontTable);
//vbox.getChildren().addAll(title, subtitle, reqTable);
reqTable.setVisible(false);
tempTable.setVisible(false);
ontTable.setVisible(false);
reqTable.setMinHeight(300);
tempTable.setMinHeight(300);
ontTable.setMinHeight(300);
reqTable.translateYProperty().set(100);
tempTable.translateYProperty().set(-100);
ontTable.translateYProperty().set(-300);
// --- Welcome Page
title.setFont(new Font("Arial", 24));
title.translateYProperty().set(10);
title.setText(pages[0].title);
subtitle.setText(pages[0].subtitle);
subtitle.setMinHeight(10);
// --- Menus
// --- File Menu
// --- Import Submenu
Menu menuFile = new Menu("File");
Menu importMenu = new Menu("Import");
MenuItem opt1 = new MenuItem("opt_1");
MenuItem opt2 = new MenuItem("opt_2");
MenuItem opt3 = new MenuItem("opt_3");
importMenu.getItems().addAll(opt1, opt2, opt3);
MenuItem export = new MenuItem("Export");
MenuItem exit = new MenuItem("Exit");
menuFile.getItems().addAll(importMenu, export, new SeparatorMenuItem(), exit);
menuBar.getMenus().addAll(menuFile);
// --- Show
((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);
stage.setScene(scene);
stage.show();
}
// Page Class
private class Page {
public String title;
public String subtitle;
public Page(String title, String subtitle) {
this.title = title;
this.subtitle = subtitle;
}
}
}
请这样修改代码,然后检查。
删除这一行:subtitle.setMinHeight(10);或设置:subtitle.setMinHeight(50);
subtitle.setMinHeight(50);
这个答案是在 Keyur 写他的时候写的。 Keyur 的回答是正确的,但鉴于我已经写了所有这些,我还是 post :-)
看不见的table没有遮住字幕标签
您将字幕的最小高度设置为10:
subtitle.setMinHeight(10);
当没有足够的空间以首选大小显示布局区域中的所有内容时,布局窗格将开始缩小其中项目的大小,直到达到最小大小的所有内容。这就是这里发生的情况,VBox 布局管理器正在将字幕的大小减小到您设置的最小大小。
如果您删除最小高度设置,则字幕标签将不会被截断。
您可以将最小高度设置为首选高度:
subtitle.setMinHeight(Control.USE_PREF_SIZE);
这有时很有用,但在这种情况下是不必要的(这里根本不需要设置最小高度,因为 VBox 布局管理器的默认行为会为其分配足够的 space 给标签完全垂直显示)。
不可见的项目仍然占据布局 space,即使您看不到它们。想象一下,如果你的房间有一扇看不见的玻璃门,而你试图离开房间,你会撞到头。会痛的。我已经做到了。好痛。
如果你也不希望不可见节点占用布局space那么你需要将其设置为非托管,参见:
- JavaFX - setVisible doesn't "hide" the element
其他布局建议
大部分与您的问题没有直接关系,请忽略。只是一些背景信息。
您已经在使用布局窗格来布置项目(VBox)。您不应为放置在布局窗格中的项目设置翻译值。翻译值(translateX 和 translateY)实际上应该只是用于临时移动事物,例如 OS X 框样式的弹跳动画。相反,布局应该通过 layoutX 和 layoutY 值进行管理。当您使用布局管理器时,布局管理器负责设置 layoutX 和 layoutY 值,因此您不必设置任何转换值或布局值。
相反,您在布局管理器上为其管理的节点设置布局约束。例如,对于 VBox,要通过边距偏移某些项目,您可以使用 VBox.setMargin(node)
而不是更改翻译值。设置转换值的一个问题是布局管理器会忽略它们,因此尽管您可能会移动一个节点,布局管理器不会自动正确设置其他托管节点的布局,并且您可能会遇到奇怪的重叠问题(尽管那不是'您在这里遇到的问题的根源)。
Gluon SceneBuilder 是学习更多关于 JavaFX 布局的好工具(即使您不想使用 FXML)。
学习布局的一个很好的例子是Layout sans tears. Unfortunately the example is a bit old and uses deprecated builder code, but the basic concepts are still valid and the ideas are easy enough to transfer into more modern code. Oracle also have a layout tutorial,但不幸的是,它远非全面,事实上,woeful这个词浮现在脑海中......
Scenic View 是一个很好的工具,可用于了解应用程序的布局(以及解决可能出现的问题,就像您在此处遇到的那样)。
为防止您的内容变得小于其首选大小,您可以将其放在 ScrollPane 中,并在内容溢出可用区域(如网页)时让用户滚动。