JavaFX 8 - Qt StackedWidget的布局交换或类似/等效功能?

时间:2015-07-07 11:52:57

标签: java qt layout awt javafx-8

我被要求在JavaFX中编写转换程序,但我需要允许用户根据转换方向设置不同的选项。

为了交换转换方向,我需要显示两个不同的(唯一的)控件集,仅用于与当前方向相关的选项。

在一个方向上,我需要在另一个方向上显示两个TextField,一对RadioButtons。我可以在同一时间显示两者,并在需要时启用/禁用,但我首先尝试的是一种不那么混乱的方法。

我正在寻找一种与我在C ++中使用的Qt StackedWidget具有类似布局切换功能的解决方案,因此我可以根据转换方向替换RadioButtons的TextFields,反之亦然。

重要的是要注意,此窗口有许多其他两个方向共有的选项,因此只需要根据转换方向进行更改的一小部分。因此,如果我可以从同一个控制器中轻松访问交换的控件,我会更喜欢它。

我不想要标签或页码,因为用户控制其他地方的方向,因此TabPane和Pagination都会出局,除非可以禁用这些不需要的功能。

我听说在另一个Java框架中有一个名为CardLayout的东西(如果我听到的话,它就是awt)可以完成我想要的工作,JavaFX 8的等价是什么?或者是否有另一种我应该使用的解决方案?

我正在使用SceneBuilder,所以我可以在其中实现,但如果需要,我可以使用纯代码。

1 个答案:

答案 0 :(得分:1)

您可以根据需要使用任何0子类(例如Pane)并致电StackPanepane.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文件及其控制器)。