我被要求在JavaFX中编写转换程序,但我需要允许用户根据转换方向设置不同的选项。
为了交换转换方向,我需要显示两个不同的(唯一的)控件集,仅用于与当前方向相关的选项。
在一个方向上,我需要在另一个方向上显示两个TextField,一对RadioButtons。我可以在同一时间显示两者,并在需要时启用/禁用,但我首先尝试的是一种不那么混乱的方法。
我正在寻找一种与我在C ++中使用的Qt StackedWidget具有类似布局切换功能的解决方案,因此我可以根据转换方向替换RadioButtons的TextFields,反之亦然。
重要的是要注意,此窗口有许多其他两个方向共有的选项,因此只需要根据转换方向进行更改的一小部分。因此,如果我可以从同一个控制器中轻松访问交换的控件,我会更喜欢它。
我不想要标签或页码,因为用户控制其他地方的方向,因此TabPane和Pagination都会出局,除非可以禁用这些不需要的功能。
我听说在另一个Java框架中有一个名为CardLayout的东西(如果我听到的话,它就是awt)可以完成我想要的工作,JavaFX 8的等价是什么?或者是否有另一种我应该使用的解决方案?
我正在使用SceneBuilder,所以我可以在其中实现,但如果需要,我可以使用纯代码。
答案 0 :(得分:1)
您可以根据需要使用任何0
子类(例如Pane
)并致电StackPane
或pane.getChildren().setAll(textFieldDisplay);
。不同的显示可以是任何类型的pane.getChildren().setAll(radioButtonDisplay);
,但由于它们拥有其他控件,因此它们通常也是Node
的某些子类。在下面的示例中,我使用Pane
作为一个,GridPane
作为另一个。VBox
。在实际应用程序中,您可以在自己的FXML文件中定义每个文件并单独加载它们等。
完整示例(使用FXML):
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController"
alignment="CENTER">
<padding>
<Insets top="20" left="20" right="20" bottom="20" />
</padding>
<CheckBox text="Show Text Fields" fx:id="showTextFields" VBox.vgrow="NEVER">
<VBox.margin>
<Insets top="10" left="10" right="10" bottom="10"/>
</VBox.margin>
</CheckBox>
<StackPane fx:id="display" VBox.vgrow="ALWAYS" />
<Button text="OK" onAction="#submit" VBox.vgrow="NEVER" />
</VBox>
MainController.java:
package application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.StackPane;
public class MainController {
@FXML
private CheckBox showTextFields ;
@FXML
private StackPane display ;
private Node radioDisplay ;
private Node textFieldDisplay ;
private RadioButtonController radioButtonController ;
private TextFieldController textFieldController ;
public void initialize() throws Exception {
FXMLLoader radioDisplayLoader = new FXMLLoader(getClass().getResource("RadioDisplay.fxml"));
radioDisplay = radioDisplayLoader.load();
radioButtonController = radioDisplayLoader.getController();
FXMLLoader textFieldDisplayLoader = new FXMLLoader(getClass().getResource("TextFieldDisplay.fxml"));
textFieldDisplay = textFieldDisplayLoader.load();
textFieldController = textFieldDisplayLoader.getController();
showTextFields.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
if (isSelected) {
display.getChildren().setAll(textFieldDisplay);
} else {
display.getChildren().setAll(radioDisplay);
}
});
display.getChildren().add(radioDisplay);
}
@FXML
private void submit() {
if (showTextFields.isSelected()) {
System.out.println("Value 1 is "+ textFieldController.getText1());
System.out.println("Value 2 is "+ textFieldController.getText2());
} else {
System.out.println("Chosen value is "+radioButtonController.getSelectedItem());
}
}
}
RadioDisplay.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.RadioButton?>
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.RadioButtonController"
alignment="TOP_CENTER" spacing="10">
<padding>
<Insets top="10" left="10" right="10" bottom="10"/>
</padding>
<RadioButton text="Choice 1" selected="true" fx:id="choice1"/>
<RadioButton text="Choice 2" fx:id="choice2"/>
</VBox>
RadioButtonController.java:
package application;
import javafx.fxml.FXML;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
public class RadioButtonController {
@FXML
private RadioButton choice1 ;
@FXML
private RadioButton choice2 ;
public void initialize() {
ToggleGroup toggleGroup = new ToggleGroup();
choice1.setToggleGroup(toggleGroup);
choice2.setToggleGroup(toggleGroup);
}
public String getSelectedItem() {
if (choice1.isSelected()) {
return "Choice 1";
} else if (choice2.isSelected()) {
return "Choice 2";
} else return "" ;
}
}
TextFieldDisplay.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<GridPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.TextFieldController"
hgap="10" vgap="10">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" halignment="RIGHT"/>
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<Label text="Value 1:" GridPane.columnIndex="0" GridPane.rowIndex="0"/>
<Label text="Value 2:" GridPane.columnIndex="0" GridPane.rowIndex="1"/>
<TextField fx:id="textField1" GridPane.columnIndex="1" GridPane.rowIndex="0"/>
<TextField fx:id="textField2" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
</GridPane>
TextFieldController.java:
package application;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
public class TextFieldController {
@FXML
private TextField textField1 ;
@FXML
private TextField textField2 ;
public String getText1() {
return textField1.getText() ;
}
public String getText2() {
return textField2.getText();
}
}
Main.java:
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
VBox root = (VBox)FXMLLoader.load(getClass().getResource("Main.fxml"));
Scene scene = new Scene(root,400,400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
所有FXML文件与.java文件位于同一个包(application
)中。
<强>更新强>
如果你不喜欢&#34; modularize&#34;在这种程度上,您可以将所有内容放在一个带有单个控制器的FXML中。在这种情况下,Main.fxml看起来像
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController"
alignment="CENTER">
<padding>
<Insets top="20" left="20" right="20" bottom="20" />
</padding>
<CheckBox text="Show Text Fields" fx:id="showTextFields" VBox.vgrow="NEVER">
<VBox.margin>
<Insets top="10" left="10" right="10" bottom="10"/>
</VBox.margin>
</CheckBox>
<StackPane fx:id="display" VBox.vgrow="ALWAYS">
<VBox fx:id="radioDisplay" alignment="TOP_CENTER" spacing="10">
<padding>
<Insets top="10" left="10" right="10" bottom="10" />
</padding>
<RadioButton text="Choice 1" selected="true" fx:id="choice1" />
<RadioButton text="Choice 2" fx:id="choice2" />
</VBox>
<fx:define>
<GridPane fx:id="textFieldDisplay" hgap="10" vgap="10">
<columnConstraints>
<ColumnConstraints hgrow="NEVER" halignment="RIGHT" />
<ColumnConstraints hgrow="SOMETIMES" />
</columnConstraints>
<Label text="Value 1:" GridPane.columnIndex="0"
GridPane.rowIndex="0" />
<Label text="Value 2:" GridPane.columnIndex="0"
GridPane.rowIndex="1" />
<TextField fx:id="textField1" GridPane.columnIndex="1"
GridPane.rowIndex="0" />
<TextField fx:id="textField2" GridPane.columnIndex="1"
GridPane.rowIndex="1" />
</GridPane>
</fx:define>
</StackPane>
<Button text="OK" onAction="#submit" VBox.vgrow="NEVER" />
</VBox>
并且相应的控制器是
package application;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.StackPane;
public class MainController {
@FXML
private CheckBox showTextFields ;
@FXML
private StackPane display ;
@FXML
private Node radioDisplay ;
@FXML
private Node textFieldDisplay ;
@FXML
private TextField textField1 ;
@FXML
private TextField textField2 ;
@FXML
private RadioButton choice1 ;
@FXML
private RadioButton choice2 ;
public void initialize() throws Exception {
showTextFields.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
if (isSelected) {
display.getChildren().setAll(textFieldDisplay);
} else {
display.getChildren().setAll(radioDisplay);
}
});
ToggleGroup toggleGroup = new ToggleGroup();
choice1.setToggleGroup(toggleGroup);
choice2.setToggleGroup(toggleGroup);
}
@FXML
private void submit() {
if (showTextFields.isSelected()) {
System.out.println("Value 1 is "+ textField1.getText());
System.out.println("Value 2 is "+ textField2.getText());
} else {
String chosenValue ;
if (choice1.isSelected()) {
chosenValue = "Choice 1";
} else if (choice2.isSelected()) {
chosenValue = "Choice 2";
} else {
chosenValue
= "None";
}
System.out.println("Chosen value is "+chosenValue);
}
}
}
(在这种情况下,删除另外两个FXML文件及其控制器)。