【问题标题】:JavaFX Switching BorderPane's Center: Buttons only work onceJavaFX 切换 BorderPane 的中心:按钮只能工作一次
【发布时间】:2017-09-09 23:39:24
【问题描述】:

我现在对 JavaFX 有点困惑。基本上,当我运行我的代码时,我只能单击应用程序侧栏上的一个按钮一次,然后它将中心窗格交换为我想要显示的那个。不过在那之后,ActionEvent 似乎没有触发......我已经尝试在处理后重新附加它们,但它不起作用,我不知道出了什么问题。

我花了 2 天的时间试图破解这个问题,我敢肯定这是非常简单的事情。

控制器:

@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 正确注入的,但是一旦中心面板切换,侧面按钮就不再起作用(尽管我最初可以单击任何对象,它会加载。

脚注:为了便于阅读,上面的代码略有删减和更改。

【问题讨论】:

  • 没有看到此控制器的fxml(我假设我们正在查看控制器的一部分),这有点难以分辨。您以这种奇怪的方式分配动作处理程序是否有原因?更习惯的做法是为每个按钮的操作处理程序设置一个方法,该方法要么在 initialize() 方法中分配,要么通过 fxml 映射。
  • 我想知道为什么这首先会起作用,因为您似乎从未填满地图......
  • 您似乎正在尝试在未正式独立于控制器的按钮上设置处理程序。我有类似的情况,我可以发布一下,让您了解我是如何处理的。
  • 对不起,我的错,我忘了包含 FXML。我现在编辑它。感谢您的回复。每个按钮都有单一方法的原因是什么?那岂不是意味着更少的干代码?
  • 您仍然可以拥有其他方法(并从处理程序方法中调用它们),因此完全没有理由重复您自己。通过使用多种方法,您可以摆脱那个丑陋的 if 语句(随着按钮数量的增加,它会变得非常丑陋)。

标签: java javafx fxml


【解决方案1】:

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

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

控制器代码

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;
}

在这段代码的 sn-p 中,我使用了两种不同的方法。在 loadQWERTYKeyboard 方法中是一种方法。在 findNodeByID 中是第二种方法。完整代码可在here 找到。工作但项目未完成。

【讨论】:

    【解决方案2】:

    此答案与您发布的代码类似。该答案使用了与原始答案中讨论的相同的两个想法。

    主要

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    /**
     *
     * @author blj0011
     */
    public class JavaFXApplication75 extends Application
    {
    
        @Override
        public void start(Stage stage) throws Exception
        {
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args)
        {
            launch(args);
        }
    
    }
    

    FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.layout.AnchorPane?>
    
    <AnchorPane id="AnchorPane" prefHeight="449.0" prefWidth="564.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication75.FXMLDocumentController">
        <children>
            <Button fx:id="btnMainBar" layoutX="76.0" layoutY="391.0" onAction="#handleButtonAction" text="Load Bar" />
            <Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
          <Button fx:id="btnMainFoo" layoutX="419.0" layoutY="391.0" mnemonicParsing="false" onAction="#handleButtonAction" text="Load Foo" />
          <AnchorPane fx:id="apMain" layoutX="161.0" layoutY="88.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="100.0" AnchorPane.leftAnchor="50.0" AnchorPane.rightAnchor="50.0" AnchorPane.topAnchor="25.0" />
        </children>
    </AnchorPane>
    

    控制器

    import java.io.IOException;
    import java.net.URL;
    import java.util.ResourceBundle;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javafx.collections.ObservableList;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.fxml.Initializable;
    import javafx.scene.Node;
    import javafx.scene.control.Button;
    import javafx.scene.control.Label;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.AnchorPane;
    import javafx.scene.layout.Pane;
    
    /**
     *
     * @author blj0011
     */
    public class FXMLDocumentController implements Initializable
    {    
        @FXML AnchorPane apMain;//This pane will be used to display the other two panes depending on which button is pressed.
    
        //Foo Pane children nodes
        Button btnFooOne, btnFooTwo;
        TextField tfFooOne, tfFooTwo;
        Label lblFoo;
    
        //Bar Pane children nodes
        Button btnBar;
        TextField tfBar;
        Label lblBar;
    
        @FXML
        private void handleButtonAction(ActionEvent event)
        {
            if(((Button)event.getSource()).getId().equals("btnMainBar"))
            {
                loadBarPane();
            }
            else if(((Button)event.getSource()).getId().equals("btnMainFoo"))
            {
                loadFooPane();
            }
        }
    
        @Override
        public void initialize(URL url, ResourceBundle rb)
        {
            // TODO
        }   
    
        //This approach uses the findNodeByID method.
        private void loadFooPane()
        {
            try 
            {
                if(apMain.getChildren().size() > 0)
                {
                    apMain.getChildren().remove(0);//if a node is loaded into apMain, remove the node.
                }
    
                Pane root = FXMLLoader.load(getClass().getResource("Foo.fxml"));
                apMain.getChildren().add(root);//Add Foo Pane to apMain
    
                //Get Foo Pane's children nodes
                tfFooOne = (TextField)findNodeByID("tfFooOne", root.getChildren());
                tfFooTwo = (TextField)findNodeByID("tfFooTwo", root.getChildren());
                btnFooOne = (Button)findNodeByID("btnFooOne", root.getChildren());
                btnFooTwo = (Button)findNodeByID("btnFooTwo", root.getChildren());
                lblFoo = (Label)findNodeByID("lblFoo", root.getChildren());
    
                //Set Listeners
    
                tfFooOne.textProperty().addListener((obserValue, oldValue, newValue) -> {
                    lblFoo.setText("new value: " + newValue);
                });
    
                tfFooTwo.textProperty().addListener((obserValue, oldValue, newValue) -> {
                    lblFoo.setText("new value: " + newValue);
                });
    
                btnFooOne.setOnAction((event) -> {lblFoo.setText("You pressed btnFooOne");});
                btnFooTwo.setOnAction((event) -> {lblFoo.setText("You pressed btnFooTwo");});
    
            }
            catch (IOException ex) 
            {
                Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        private void loadBarPane()
        {
            try
            {
                //This way is more complicate if you have more than one of the same type of node
                if(apMain.getChildren().size() > 0)
                {
                    apMain.getChildren().remove(0);//if a node is loaded into apMain, remove the node.
                }
                Pane root = FXMLLoader.load(getClass().getResource("Bar.fxml"));
                apMain.getChildren().add(root);//Add Foo Pane to apMain
    
                //Get Bar Pane's children nodes
                for(Node node : root.getChildren())
                {
                    if(node instanceof Button)
                    {
                        btnBar = (Button)node;
                    }
                    else if(node instanceof TextField)
                    {
                        tfBar = (TextField)node;
                    }
                    else if(node instanceof Label)
                    {
                        lblBar = (Label)node;
                    }
                }
    
                //Set listeners
                tfBar.textProperty().addListener((obserValue, oldValue, newValue) -> {
                    lblBar.setText("new value: " + newValue);
                });
    
                btnBar.setOnAction((event) -> {lblBar.setText("You pressed btnFooOne");});
            }
            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;
        }
    
    
    }
    

    Foo FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.Pane?>
    
    <Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="324.0" prefWidth="464.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
       <children>
          <Button fx:id="btnFooOne" layoutX="84.0" layoutY="209.0" mnemonicParsing="false" text="Button" />
          <Button fx:id="btnFooTwo" layoutX="329.0" layoutY="209.0" mnemonicParsing="false" text="Button" />
          <TextField fx:id="tfFooOne" layoutX="36.0" layoutY="162.0" />
          <TextField fx:id="tfFooTwo" layoutX="281.0" layoutY="162.0" />
          <Label fx:id="lblFoo" layoutX="165.0" layoutY="39.0" text="You just loaded Foo Pane" />
       </children>
    </Pane>
    

    条形 FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.Label?>
    <?import javafx.scene.control.TextField?>
    <?import javafx.scene.layout.Pane?>
    
    <Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="324.0" prefWidth="464.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
       <children>
          <Button fx:id="btnBar" layoutX="206.0" layoutY="186.0" mnemonicParsing="false" text="Button" />
          <TextField fx:id="tfBar" layoutX="158.0" layoutY="130.0" />
          <Label fx:id="lblBar" layoutX="160.0" layoutY="65.0" text="You just loaded Bar Pane" />
       </children>
    </Pane>
    

    【讨论】:

    • 感谢您的解决方案,两者都有助于学习如何构建 JavaFX。您能否对此评论进行更多扩展? //This way is more complicate if you have more than one of the same type of node
    • 我想我可能在你阅读的时候编辑了最后一行对不起,我过早地按下了回车键。不过问题来了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多