JavaFX切换BorderPane的中心:按钮只能使用一次 [英] JavaFX Switching BorderPane's Center: Buttons only work once

查看:104
本文介绍了JavaFX切换BorderPane的中心:按钮只能使用一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当时有点与JavaFX混淆.基本上,运行代码时,我只能单击一次应用程序侧栏上的按钮,然后它将中心窗格替换为我要显示的窗格.不过,在那之后,似乎ActionEvent不会触发...我尝试在处理后重新附加它们,但是它不起作用,而且我也不知道怎么了.

I'm a tad confused with JavaFX at the minute. Basically, when I run my code, I can only click on a button on the side bar of the application once, then it will swap the center pane for the one that I want displayed. After that though, it appears that the ActionEvent does not trigger... I've tried reattaching them after handling but it doesn't work, and I have no idea whats wrong.

我花了2天的时间来解决这个问题,我敢肯定这是如此烦人的简单.

I've spent 2 days trying to crack this, and I'm sure it's something so annoyingly simple.

控制器:

@FXML private Button fooButton, barButton;
@FXML private Pane fooPane, barPane;
@FXML private BorderPane mainWindow;
@FXML private TabPane tabPane;
@FXML private VBox buttonBar;
@FXML private AnchorPane centerAP;
private HashMap<Button, Pane> buttonsPaneHMap = new HashMap<>(); //storing the data in a HashMap to create a link between buttons and their panes.

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    putNodesInHashmap();
    assertControlsExist();
    mainWindow.setCenter(welcomePane);
    setOnActions(buttonsPaneHMap);  
}

public final void handleButton(ActionEvent event) throws IOException {
    Node newCenter = new AnchorPane();

    if (event.getSource() ==  fooButton){
        newCenter = FXMLLoader.load(getClass().getResource("/FXML/fooPane.fxml"));
    }   
    if (event.getSource() ==  barButton){
        newCenter = FXMLLoader.load(getClass().getResource("/FXML/barPane.fxml"));
    }               

    try{
        this.mainWindow.setCenter(newCenter); 
     }
     catch (NullPointerException e){
         e.printStackTrace();
     }   
 }

public final void setOnActions(HashMap<Button, Pane> hMap){
    for (Button button : hMap.keySet()){
        ((ButtonBase) button).setOnAction(arg0 -> {
            try {
                handleButton(arg0);
            } 
            catch (Exception e) {
                e.printStackTrace();
            }
        });
    }       
}
public final void putNodesInHashMap(){
     buttonsPaneHMap.put(fooButton, fooPane);
     buttonsPaneHMap.put(barButton, barPane);

}

FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import java.net.URL?>
<?import javafx.scene.Cursor?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<BorderPane fx:id="mainWindow" prefHeight="461.0" prefWidth="760.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="guiControllers.MainController">
   <top>
      <Pane id="body" prefHeight="96.0" prefWidth="658.0" style="-fx-background-color: #243242; -fx-border-color: #0E141B; -fx-border-radius: 3;" stylesheets="@application.css" BorderPane.alignment="CENTER">
         <children>
            <Label layoutX="103.0" layoutY="25.0" prefHeight="48.0" prefWidth="394.0" text="Title Here" textFill="WHITE">
               <font>
                  <Font name="Calibri Bold" size="41.0" />
               </font>
            </Label>
            <ImageView fitHeight="55.0" fitWidth="61.0" layoutX="25.0" layoutY="20.0" pickOnBounds="true" preserveRatio="true">
               <image>
                  <Image url="@../Res/mhlogo.png" />
               </image>
            </ImageView>
         </children>
      </Pane>
   </top>
   <left>
      <VBox id="buttonBar" fx:id="buttonBar" alignment="TOP_CENTER" prefHeight="365.0" prefWidth="168.0" style="-fx-background-color: #2E4055; -fx-border-radius: 3; -fx-border-color: #0E141B;" BorderPane.alignment="CENTER">
         <children>
            <Pane prefHeight="31.0" prefWidth="98.0">
               <children>
                  <Pane layoutX="-1.0" layoutY="-2.0" prefHeight="33.0" prefWidth="169.0" style="-fx-background-color: #565656; -fx-border-color: #000000; -fx-border-radius: 20; -fx-background-radius: 20;">
                     <children>
                        <ImageView fitHeight="19.0" fitWidth="18.0" layoutX="7.0" layoutY="7.0" pickOnBounds="true" preserveRatio="true">
                           <image>
                              <Image url="@../Res/magnifying-glass.png" />
                           </image>
                        </ImageView>
                        <TextField layoutX="29.0" layoutY="2.0" prefHeight="0.0" prefWidth="134.0" style="-fx-border-radius: 1; -fx-border-color: #111111; -fx-border-width: 2; -fx-background-color: #FFFFFF; -fx-background-radius: 20; -fx-border-radius: 20;" styleClass="stop-color-leaking" stylesheets="@../cSS/application.css" />
                     </children>
                  </Pane>
               </children>
            </Pane>
            <Button id="fooButton" fx:id="fooButton" mnemonicParsing="false" onAction="#handleButton" prefHeight="31.0" prefWidth="171.0" style="-fx-background-color: #CDCDCD; -fx-border-color: #0E141B; -fx-border-radius: 3;" text="foo" />
            <Button id="barButton" fx:id="barButton" mnemonicParsing="false" onAction="#handleButton" prefHeight="31.0" prefWidth="202.0" style="-fx-background-color: #CDCDCD; -fx-border-color: #0E141B; -fx-border-radius: 3;" text="bar" />

               <children>
                  <ImageView id="settingsButton" fitHeight="38.0" fitWidth="48.0" layoutX="64.0" layoutY="130.0" pickOnBounds="true" preserveRatio="true">
                     <image>
                        <Image url="@../Res/settings.png" />
                     </image>
                  </ImageView>
               </children>
            </AnchorPane>
         </children>
      </VBox>
   </left>
   <right>
      <TabPane id="tabPane" fx:id="tabPane" focusTraversable="false" prefHeight="365.0" prefWidth="166.0" rotateGraphic="true" style="-fx-background-color: # #414760;" styleClass="tab-header-background" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
        <tabs>
          <Tab fx:id="notesTab" text="Notes">
            <content>
              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="336.0" prefWidth="216.0" style="-fx-border-color: #414760; -fx-background-radius: 3;" styleClass="tab-header-background" stylesheets="@../application/CSS/application.css" />
            </content>
          </Tab>
          <Tab fx:id="diagramTab" closable="false" text="Diagram" />
        </tabs>
         <cursor>
            <Cursor fx:constant="DEFAULT" />
         </cursor>
         <stylesheets>
            <URL value="@application.css" />
            <URL value="@../application/CSS/application.css" />
         </stylesheets>
      </TabPane>
   </right>
   <center>
      <AnchorPane fx:id="centerAP" style="-fx-background-color: #414760;" BorderPane.alignment="CENTER">
         <children>
            <VBox fx:id="welcomePane" prefHeight="304.0" prefWidth="391.0" style="-fx-background-color: #414760;">
               <children>
                  <Pane fx:id="welcomePane" prefHeight="313.0" prefWidth="428.0" style="-fx-background-color: #414760;">
                     <children>
                        <ImageView fitHeight="183.0" fitWidth="296.0" layoutX="14.0" layoutY="65.0" pickOnBounds="true" preserveRatio="true">
                           <image>
                              <Image url="@../Res/welcomepane.png" />
                           </image>
                        </ImageView>
                        <Label layoutX="141.0" layoutY="14.0" text="Welcome" textFill="WHITE">
                           <font>
                              <Font name="Calibri Bold" size="33.0" />
                           </font>
                        </Label>
                        <Label layoutX="82.0" layoutY="53.0" prefHeight="68.0" prefWidth="346.0" text="To start, please select an" textFill="WHITE" textOverrun="CLIP">
                           <font>
                              <Font name="Calibri" size="24.0" />
                           </font>
                        </Label>
                        <Label layoutX="82.0" layoutY="80.0" prefHeight="68.0" prefWidth="346.0" text="option from the left." textFill="WHITE" textOverrun="CLIP">
                           <font>
                              <Font name="Calibri" size="24.0" />
                           </font>
                        </Label>
                     </children>
                  </Pane>
               </children>
            </VBox>
         </children>
      </AnchorPane>
   </center>
</BorderPane>

据我所知,所有对象都是从FXML正确注入的,但是一旦中心面板切换,侧面按钮将不再起作用(尽管我可以单击任何初始按钮,它将加载.

As far as I can tell all objects are injected correctly from the FXML, but once the center panel has switched, the side buttons no longer function (Though I can click any initially and it will load.

脚注:上面的代码已被稍微缩减并进行了更改以提高可读性.

Footnote: The code above is slightly cut down and changed for readability.

推荐答案

我从Android的剧本中得到了一个想法. 如果您知道如何到达节点的父节点,并且知道节点的fx:id,则可以使用这种方法.

I took an idea from Android's playbook. If you know how to get to the node's parent and you know the node's fx:id, you can use this approach.

完整代码根据按下哪个按钮将不同的窗格加载到场景的中心.下面的代码是一个示例,显示了如何加载一个窗格.如果知道节点的父节点,节点的fx:id和节点的类型,则可以使用此想法获得任何节点.

The full code loads different panes into the center of a Scene depending on which button is press. The code below is a sample that show how one pane is loaded. You can get any node using this idea if you know the node's parent, the node's fx:id and the node's type for casting.

控制器代码

Controller code

private void showSetupAccountScreen()
{
    try 
    {
        spCenterDisplay.getChildren().remove(0);//remove old display            
        BorderPane root = FXMLLoader.load(getClass().getResource("SubSetupAccount.fxml"));
        spCenterDisplay.getChildren().add(root);//add new display
        GridPane tempDisplay = (GridPane)root.getChildren().get(1);//get Parent of the nodes I will be using in this controller
        loadQWERTYKeyboard();            

        TextField tfFirstName = (TextField)findNodeByID("tfFirstName", tempDisplay.getChildren());
        TextField tfLastName = (TextField)findNodeByID("tfLastName", tempDisplay.getChildren());
        TextField tfStreetAddress = (TextField)findNodeByID("tfStreetAddress", tempDisplay.getChildren());
        TextField tfCity = (TextField)findNodeByID("tfCity", tempDisplay.getChildren());
        TextField tfState = (TextField)findNodeByID("tfState", tempDisplay.getChildren());
        TextField tfZip = (TextField)findNodeByID("tfZip", tempDisplay.getChildren());
        TextField tfInitialDepositChecking = (TextField)findNodeByID("tfInitialDepositChecking", tempDisplay.getChildren());
        TextField tfInitialDepositSavings  = (TextField)findNodeByID("tfInitialDepositSavings", tempDisplay.getChildren());
        ChoiceBox cbChecking  = (ChoiceBox)findNodeByID("cbChecking", tempDisplay.getChildren());
        cbChecking.getItems().addAll("No", "Yes");
        cbChecking.setValue("No");
        ChoiceBox cbSavings  = (ChoiceBox)findNodeByID("cbSavings", tempDisplay.getChildren());
        cbSavings.getItems().addAll("No", "Yes");
        cbSavings.setValue("No");            

        if(true)//come back and check to make sure all info is in textfields
        {
            btnLeftOne.setOnAction((event) -> {

                boolean createChecking = cbChecking.getValue().equals("Yes");
                boolean createSavings = cbSavings.getValue().equals("Yes");

                dbh.createNewAccount(tfFirstName.getText(), tfLastName.getText(), tfStreetAddress.getText(), tfCity.getText(), 
                                     tfState.getText(), tfZip.getText(), createChecking, Double.parseDouble(tfInitialDepositChecking.getText()),
                                     createSavings, Double.parseDouble(tfInitialDepositSavings.getText()));
            });
        }
        else
        {
            //create Alert 
        }

        btnRightOne.setOnAction((event) -> {
            cancelAccountCreation();
        });

        btnLeftTwo.setOnAction(null);
        btnLeftThree.setOnAction(null);
        btnLeftFour.setOnAction(null);
        btnRightTwo.setOnAction(null);
        btnRightThree.setOnAction(null);
        btnRightFour.setOnAction(null);
    }
    catch (IOException ex) 
    {
        Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private void loadQWERTYKeyboard()
{
    try 
    {
        AnchorPane keyboardRoot = FXMLLoader.load(getClass().getResource("KeyboardQWERTY.fxml"));
        System.out.println(keyboardRoot.getId());
        spBottomDisplay.getChildren().add(keyboardRoot);

        GridPane tempKeyboard = (GridPane)keyboardRoot.getChildren().get(0);

        tempKeyboard.getChildren().stream().filter((tempNode)
                -> (tempNode instanceof Button)).map((
                        tempNode) -> (Button) tempNode).forEachOrdered((tempButton) -> {
                            buttons.put(tempButton.getText().toLowerCase(), tempButton);
                        });

        apMain.setOnKeyPressed((event) -> {
            Button tempButton = buttons.get(event.getText());
            if (tempButton != null) {
                tempButton.arm();
                tempButton.setStyle("-fx-background-color: blue");
            }
            else if (event.getCode().equals(KeyCode.ENTER)) {
                tempButton = buttons.get("enter");
                tempButton.arm();
                tempButton.setStyle("-fx-background-color: blue");
            }
            else if (event.getCode().equals(KeyCode.BACK_SPACE)) {
                tempButton = buttons.get("backspace");
                tempButton.arm();
                tempButton.setStyle("-fx-background-color: blue");
            }
            else if (event.getCode().equals(KeyCode.SPACE)) {
                tempButton = buttons.get("space");
                tempButton.arm();
                tempButton.setStyle("-fx-background-color: blue");
            }
        });

        apMain.setOnKeyReleased((event) -> {
            System.out.println();
            Button tempButton = buttons.get(event.getText());
            System.out.println("Released key text: " + event.getText());
            System.out.println("Released key code: " + event.getCode());

            if (tempButton != null) {
                tempButton.disarm();
                tempButton.setStyle("");
            }
            else if (event.getCode().equals(KeyCode.ENTER)) {
                tempButton = buttons.get("enter");
                tempButton.disarm();
                tempButton.setStyle("");
            }
            else if (event.getCode().equals(KeyCode.BACK_SPACE)) {
                tempButton = buttons.get("backspace");
                tempButton.disarm();
                tempButton.setStyle("");
            }
            else if (event.getCode().equals(KeyCode.SPACE)) {
                tempButton = buttons.get("space");
                tempButton.disarm();
                tempButton.setStyle("");
            }
        });
    }
    catch (IOException ex) 
    {
        Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

private Node findNodeByID(String id, ObservableList<Node> observableList)
{
    for(Node node : observableList)
    {
        if(node.getId().equals(id))
        {
            System.out.println("node found!");
            return node;
        }
        else
        {
            System.out.println("node not found yet!");
        }
    }

    return null;
}

在这段代码中,我使用两种不同的方法.在loadQWERTYKeyboard方法中是一种方法.在findNodeByID中是第二种方法.完整代码可在此处找到.工作正常,但项目尚未完成.

In this snippet of code I use two different approaches. In the loadQWERTYKeyboard methods is one approach. In the findNodeByID is the second approach. The full code is found here. Working but project not complete.

这篇关于JavaFX切换BorderPane的中心:按钮只能使用一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆