Замена графических интерфейсов на основе logi c в JavaFX на FXML - PullRequest
0 голосов
/ 14 июля 2020

Я использую следующий код для создания GridPane из TextField s в JavaFX:

GridPane grid = new GridPane();
for (int i = 0; i < 9; i++) 
    for (int j = 0; j < 9; j++) {
        grid.add(createTextField(), j, i);
    }
}

createTextField() - это созданный мной метод, который возвращает TextField с определенными свойствами. set.

Я хотел бы начать использовать файлы F XML для создания своих графических интерфейсов в JavaFX, но я не совсем понимаю, как заменить Java logi c файлом XML. Как мне воссоздать приведенный выше код с помощью F XML? Есть ли в F XML циклы for?

Ответы [ 2 ]

4 голосов
/ 14 июля 2020

Формат F XML не обеспечивает способ l oop.

Файл F XML должен описывать только stati c (т. Е. Не динамический c), неповторяющиеся части вашего пользовательского интерфейса. Сделать UI полностью динамичным c с помощью только файла F XML невозможно, а объявление, например, 81 различных TextField s быстро становится неуправляемым. Вместо этого эти части пользовательского интерфейса должны обрабатываться контроллером, который позволяет вам подключить код Java к файлу F XML. В вашем случае поля, вероятно, следует добавить в метод initialize контроллера. Например:

F XML:

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>

<GridPane fx:id="grid" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
          hgap="3" vgap="3" alignment="CENTER" fx:controller="com.example.Controller">
  <padding>
    <Insets topLeftBottomRight="5"/>
  </padding>
</GridPane>

Контроллер:

package com.example;

import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;

public class Controller {

  @FXML private GridPane grid;
  private TextField[][] fields;

  @FXML
  private void initialize() {
    grid.addEventFilter(KeyEvent.KEY_PRESSED, this::handleArrowNavigation);

    fields = new TextField[9][9];
    for (int i = 0; i < fields.length; i++) {
      for (int j = 0; j < fields[0].length; j++) {
        fields[i][j] = createTextField();
        grid.add(fields[i][j], j, i);
      }
    }
  }

  private TextField createTextField() {
    // ...
  }

  private void handleArrowNavigation(KeyEvent event) {
    // ...
  }
}

Поскольку это, похоже, связано с вашим предыдущим вопросом Я также показал, как добавить фильтр событий, поскольку в файле FMXL нет возможности сделать это (можно установить только onXXX свойства обработчика событий).

В этом примере это может не стоить того использовать F XML, поскольку вы фактически используете F XML только для объявления GridPane. Но это, очевидно, зависит от того, как спроектировано остальное ваше приложение.

3 голосов
/ 14 июля 2020

Как указано в комментариях и другом ответе, нет возможности использовать c циклы в F XML, и такие функции должны быть написаны в Java, а не в F XML.

Обратите внимание, что один из шаблонов - создать собственный класс для обработки частей, которые вам нужно написать в коде. Обычно я не люблю подклассы классов макета исключительно с целью добавления к ним элементов управления, хотя в этом случае это, по крайней мере, добавляет некоторые функциональные возможности, а также прекрасно играет с F XML.

TextFieldGrid. java :

package org.jamesd.examples.textfieldgrid;

import javafx.beans.NamedArg;
import javafx.beans.property.StringProperty;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;

public class TextFieldGrid extends GridPane {

    private final StringProperty[][] text ;
    
    
    public TextFieldGrid(
            @NamedArg("numberOfColumns") int numberOfColumns,
            @NamedArg("numberOfRows") int numberOfRows 
    ) {
        
        text = new StringProperty[numberOfColumns][numberOfRows];
        for (int i = 0 ; i < numberOfRows ; i++) {
            for (int j = 0 ; j < numberOfColumns ; j++) {
                TextField textField = new TextField();
                add(textField, j, i);
                text[j][i] = textField.textProperty();
            }
        }
    }
    
    public StringProperty textProperty(int column, int row) {
        return text[column][row];
    }
    
    public final String getText(int column, int row) {
        return textProperty(column, row).get();
    }
    
    public final void setText(int column, int row, String text) {
        textProperty(column, row).set(text);
    }
    
    public int getNumberOfColumns() {
        return text.length;
    }
    
    public int getNumberOfRows() {
        return text[0].length;
    }
}

Что вы можете использовать, например, в файле F XML:

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

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>

<?import org.jamesd.examples.textfieldgrid.TextFieldGrid?>

<BorderPane xmlns="http://javafx.com/javafx/8.0.171"
    xmlns:fx="http://javafx.com/fxml/1"
    fx:controller="org.jamesd.examples.textfieldgrid.Controller">
    <top>
        <Label text="Enter 81 values below:" />
    </top>

    <center>
        <TextFieldGrid fx:id="textFieldGrid" numberOfColumns="9" numberOfRows="9" />
    </center>

    <bottom>
        <Button text="Check values" onAction="#checkValues" />
    </bottom>

</BorderPane>

и ссылаться на функциональность обычным способом в контроллере:

package org.jamesd.examples.textfieldgrid;

import javafx.fxml.FXML;

public class Controller {

    @FXML
    private TextFieldGrid textFieldGrid ;
    
    @FXML
    private void checkValues() {
        for (int i = 0 ; i < textFieldGrid.getNumberOfColumns(); i++) {
            for (int j = 0; j < textFieldGrid.getNumberOfRows(); j++) {
                System.out.printf("[%d, %d]: %s%n", i, j, textFieldGrid.getText(i, j));
            }
        }
    }

}

Для полноты, класс приложения:

package org.jamesd.examples.textfieldgrid;

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

import java.io.IOException;

public class App extends Application {


    @Override
    public void start(Stage stage) throws IOException {
        Scene scene = new Scene(FXMLLoader.load(getClass().getResource("TextFieldGrid.fxml")));
        stage.setScene(scene);
        stage.show();
    }


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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...