Java Fx, 编辑特定标签的文本区域

Java Fx, Edit the textarea of a specific tab

好吧,我的问题很简单。 我正在使用 Java Fx 构建一个应用程序,并且我有一个 TabPane。 当我打开一个新选项卡时,该选项卡通过 fxml 文件获取其内容。

tab.setContent((Node)FXMLLoader.load(this.getClass().getResource("/main/textEditor.fxml")))

很好,效果很好,它总是在所有选项卡上加载相同的文件,因此,所有选项卡上的所有文本区域都具有相同的 ID。 问题是,使用java,我只能获取第一个Tab 的textarea 的信息。

我如何专门编辑一个选项卡的文本区域?


我想做的事的一个例子:

主要

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Screen;
import javafx.stage.Stage;


public class Main extends Application{


     public static void main(String[] args) {
         Application.launch(Main.class, args);
     }

     @Override   
     public void start(Stage stage) throws Exception {  
         Parent root = FXMLLoader.load(getClass().getResource("/tabPane/test.fxml"));


         Screen screen = Screen.getPrimary();
         Rectangle2D bounds = screen.getVisualBounds();

         stage.setScene(new Scene(root));



         stage.show();
     }
}

test.fxml

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

<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.AnchorPane?>

<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tabPane.controller">
   <children>
      <MenuBar VBox.vgrow="NEVER">
         <menus>
            <Menu mnemonicParsing="false" onAction="#test" text="File">
               <items>
                  <MenuItem fx:id="insert" mnemonicParsing="false" onAction="#test" text="Insert" />
               </items>
            </Menu>
         </menus>
      </MenuBar>
      <AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
         <children>
            <Label alignment="CENTER" layoutX="155.0" layoutY="177.0" style="&#10;" text="Drag components from Library here…" textAlignment="CENTER" textFill="#9f9f9f" wrapText="false">
               <font>
                  <Font size="18.0" />
               </font>
            </Label>
            <TabPane fx:id="tabPane" prefHeight="375.0" prefWidth="640.0" tabClosingPolicy="UNAVAILABLE">
               <tabs>
                  <Tab text="Untitled Tab 1">
                     <content>
                        <TextArea fx:id="textarea" prefHeight="200.0" prefWidth="200.0" text="a" />
                     </content>
                  </Tab>
                  <Tab text="Untitled Tab 2">
                     <content>
                        <TextArea fx:id="textarea1" prefHeight="200.0" prefWidth="200.0" text="a" />
                     </content>
                  </Tab>
               </tabs>
            </TabPane>
         </children>
      </AnchorPane>
   </children>
   <stylesheets>
      <URL value="@../../../../BasicApplicatio11n_css/BasicApplication.css" />

controller.java

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TextArea;

public class controller implements Initializable{

    @FXML
    private TextArea textarea;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {


    }
    public void test(ActionEvent event){

        textarea.appendText("Text");

    }

}

这个例子有两个选项卡,当按下按钮时,我想在当前选择的选项卡上添加文本。

有几种不同的方法可以做到这一点。一种方法是让选项卡内容的控制器从文本区域公开 textProperty。然后在您的 "main controller" 中创建一个 StringProperty 字段。当您创建一个新选项卡时,只需观察其 selected 属性 并更新字符串 属性 字段以指向当前控制器中的那个。然后您可以轻松地将文本加载到 "current" 窗格中。

这是一个简单的例子:

编辑控制器:

import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;

public class EditorController {

    @FXML
    private TextArea textArea ;


    public StringProperty textProperty() {
        return textArea.textProperty() ;
    }
}

与 textEditor.fxml:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.TextArea?>

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="EditorController">
    <center>
        <TextArea fx:id="textArea"/>
    </center>
</BorderPane>

然后 MainController 可能看起来像:

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.FileChooser;

public class MainController {

    @FXML
    private TabPane tabPane ;

    private StringProperty currentText ;

    public void initialize() throws IOException {
        // load an initial tab:
        newTab();
    }

    @FXML
    private void newTab() throws IOException {
        Tab tab = new Tab("Untitled text");
        FXMLLoader loader = new FXMLLoader(getClass().getResource("textEditor.fxml"));

        tab.setContent(loader.load());

        EditorController controller = loader.getController() ;

        tab.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
            if (isNowSelected) {
                currentText = controller.textProperty();
            }
        });

        tabPane.getTabs().add(tab);
        tabPane.getSelectionModel().select(tab);
    }

    @FXML
    private void load() {
        FileChooser chooser = new FileChooser();
        File file = chooser.showOpenDialog(tabPane.getScene().getWindow());
        if (file != null) {
            Path path = file.toPath();
            try {
                currentText.set(String.join("\n", Files.readAllLines(path)));
            } catch (IOException e) {
                Alert alert = new Alert(AlertType.ERROR);
                alert.setContentText("Unable to load file "+path);
                alert.setTitle("Load error");
                alert.showAndWait();
            }
            tabPane.getSelectionModel().getSelectedItem().setText(path.getFileName().toString());
        }
    }
}

与 main.fxml:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?>

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="MainController">
    <center>
        <TabPane fx:id="tabPane"/>
    </center>
    <bottom>
        <HBox alignment="CENTER" spacing="5">
            <padding>
                <Insets top="5" right="5" left="5" bottom="5" />
            </padding>
            <Button text="Load..." onAction="#load" />
            <Button text="New" onAction="#newTab"/>
        </HBox>
    </bottom>
</BorderPane>

为了完整性,一个简单的应用程序class:

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
        Scene scene = new Scene(root, 800, 800);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

还有其他方法,例如您可以在选项卡选择更改等时更改按钮的 onAction 属性