JavaFX действия над элементами одного окна из другого окна

288
07 апреля 2019, 17:50

Помогите решить проблему. Имеются два fxml файла и их контроллеры:

sample.fxml, его контроллер ControllerMain (главное окно программы)
find_win.fxml, его контроллер ControllerFind (модальное окно поиска текста)

В модальном окне find_win.fxml имеется TextField, в который вводится искомый текст, и кнопка "Найти", при нажатии на которую ControllerFind должен обработать нажатие и вызвать метод поиска и выделения искомого текста в элементе TextArea окна sample.fxml.

<fx:include source="sample.fxml" fx:id="textAreaOne"/>

и унаследование ControllerMain контроллером ControllerFind не помогают добиться решения - в первом случае включается вся разметка окна в модальное окно полностью, во втором случае при операцией над TextArea возвращается java.lang.reflect.InvocationTargetException

Как правильно реализовать действия над элементами одного окна из другого окна?

Answer 1

Спасибо комментатору Maxim за его краткий, но емкий комментарий, который указал направление в сторону верного решения. Т.к. ответ не был дан, отвечаю сам. Отрывок кода sample.fxml:

<TextArea fx:id="textAreaOne" prefHeight="0.0" prefWidth="783.0" </TextArea>
<MenuBar nodeOrientation="LEFT_TO_RIGHT" prefHeight="25.0" prefWidth="613.0" GridPane.halignment="CENTER" GridPane.valignment="TOP">
<menus>
<Menu mnemonicParsing="false" text="Правка">
  <items>
        MenuItem fx:id="findMenuItem" mnemonicParsing="false" onAction="#findAction" text="Найти">
           <accelerator>
              <KeyCodeCombination alt="UP" code="F" control="DOWN" meta="UP" shift="UP" shortcut="UP" />
           </accelerator>
        </MenuItem>
  </items>
</Menu>
</MenuBar>

Отрывок кода ControllerMain разметки sample.fxml:

package sample;
public class ControllerMain {
    //ссылки на контроллеры
    private ControllerFind children;  // Ссылка на контроллер окна поиска текста
    //главное окно
    @FXML
    public TextArea textAreaOne;
    @FXML
    public MenuItem findMenuItem;
    public void findAction(ActionEvent actionEvent) {
        try {
            Stage stageFind = new Stage();
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource("FXML/find_win.fxml"));
            Parent root = loader.load();
            stageFind.setTitle("Найти");
            stageFind.setMinHeight(200);
            stageFind.setMinWidth(150);
            stageFind.setResizable(false);
            stageFind.setScene(new Scene(root));
            stageFind.getIcons().add(new Image("image/search.png"));
            stageFind.initModality(Modality.NONE);
            stageFind.show();
            children = loader.getController(); //получаем контроллер окна find_win.fxml
            children.setParent(this);   //устанавливаем предка – этот контроллер
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Ключевой момент кроется в методе findAction, а именно:

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("FXML/find_win.fxml"));
Parent root = loader.load();
children = loader.getController(); //получаем контроллер окна find_win.fxml
children.setParent(this);   //устанавливаем предка – этот контроллер

После этого в контроллере разметки find_win.fxml нужно определить метод setParent(ControllerMain controller):

package sample.Controllers;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import sample.Classes.DialogManager;
import sample.ControllerMain;
public class ControllerFind {
    //окно "Найти"
    @FXML public TextField searchTextField;
    @FXML public Label findTextLabel;
    @FXML public Button okTextFindButton;
    @FXML public Button cancelTextFindButton;
    private String text;
    private ControllerMain controller;
    public void setParent (ControllerMain controller){
        this.controller = controller;
    }
    public ControllerFind getThis(){
        return this;
    }
    public void initialize(){
        System.out.println("psvm");
    }
    public void textFindOkButtonAction(ActionEvent actionEvent) {
        text = (searchTextField.getText());
        if (text.equals("")) {
            DialogManager.showInfoDialog("Ошибка!", "Введите текст для поиска!");
        } else {
            if (controller.textAreaOne.getText() != null && !controller.textAreaOne.getText().isEmpty()) {
                int index = controller.textAreaOne.getText().indexOf(text);
                if (index == -1) {
                    DialogManager.showInfoDialog("Результат", "Искомый текст отсутствует");
                } else {
                    controller.textAreaOne.selectRange(index, index + text.length());
                }
            } else {
                DialogManager.showInfoDialog("Ошибка", "Отсутствует исходный текст");
            }
        }
    }
    public void textFindCancelButtonAction(ActionEvent actionEvent) {
        Node source = (Node) actionEvent.getSource();
        Stage stage = (Stage) source.getScene().getWindow();
        stage.close();
    }
}

и, конечно же, объявить

private ControllerMain controller;

Все, после этого можно работать с элементами контроллера MainController из ControllerFind Код разметки find_win.fxml:

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="150.0" maxWidth="400.0" minHeight="100.0" minWidth="400.0" prefHeight="130.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controllers.ControllerFind">
   <children>
      <Label fx:id="findTextLabel" text="Введите текст для поиска:">
         <VBox.margin>
            <Insets bottom="10.0" left="40.0" right="20.0" top="20.0" />
         </VBox.margin>
         <font>
            <Font size="14.0" />
         </font>
      </Label>
      <TextField fx:id="searchTextField">
         <VBox.margin>
            <Insets left="40.0" right="40.0" />
         </VBox.margin>
      </TextField>
      <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
         <children>
            <Button fx:id="okTextFindButton" defaultButton="true" mnemonicParsing="false" onAction="#textFindOkButtonAction" prefHeight="25.0" prefWidth="100.0" text="OK" textAlignment="CENTER">
               <HBox.margin>
                  <Insets left="20.0" right="20.0" />
               </HBox.margin>
            </Button>
            <Button fx:id="cancelTextFindButton" cancelButton="true" mnemonicParsing="false" onAction="#textFindCancelButtonAction" prefHeight="25.0" prefWidth="100.0" text="Отмена" textAlignment="CENTER">
               <HBox.margin>
                  <Insets left="20.0" right="20.0" />
               </HBox.margin>
            </Button>
         </children>
      </HBox>
   </children>
</VBox>
READ ALSO
Можно ли установить приоритет свайпа RecyclerView на SwipeRefreshLayout? [закрыт]

Можно ли установить приоритет свайпа RecyclerView на SwipeRefreshLayout? [закрыт]

Если свайпнуть сверху вниз посередине экрана, то включится метод onRefresh(), вместо прокрутки RecyclerViewМожно ли установить приоритет свайпа RecyclerView...

161
Java не импортирует библиотеку JavaFX

Java не импортирует библиотеку JavaFX

После автоматического создания в Intellij IDEA проекта JavaFX приложения, при запуске компилятор Java выводит следующее сообщение:

194
Как удалить дубликаты строк из другого файла?

Как удалить дубликаты строк из другого файла?

Есть два тестовых файлаКак удалить дубликаты строк из первого файла, которые содержатся в другом файле? Файлы на 500 000 строк и больше

201