Обнаружение щелчка кнопки пользовательского дизайна JavaFx в используемом приложении - PullRequest
0 голосов
/ 11 июня 2018

Создан пользовательский дизайн с использованием FXML с двумя файлами CustomToggleSwitch.fxml и CustomToggleSwitch.java.

CustomToggleSwitch.fxml имеет следующий код

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.shape.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<fx:root type="Pane" xmlns="http://javafx.com/javafx/8"   xmlns:fx="http://javafx.com/fxml/1">
 <children>
    <Button mnemonicParsing="false" onAction="#click" text="Button" />
 </children>
</fx:root>

CustomToggleSwitch.java имеет код

package com.custom;

import java.io.IOException;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.Pane;

public class CustomToggleSwitch extends Pane{
   int tick;

   public CustomToggleSwitch() {

      FXMLLoader loader=new FXMLLoader(getClass().getResource("CustomToggleSwitch.fxml"));
      loader.setRoot(this);
      loader.setController(this);

       try {
          loader.load();            
       } catch (IOException e) {
          e.printStackTrace();
     }
  }

  @FXML 
  public void click(ActionEvent actionEvent){
     System.out.println(tick++);
  }
}

Создал из них файл jar и использовал этот файл jar внутри проекта приложения.Приложение имеет test.fxml:

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

<?import com.custom.*?>
<?import com.custom.CustomToggleSwitch?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-   Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0"   xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
  <children>
    <CustomToggleSwitch layoutX="29.0" layoutY="48.0" />
  </children>
</AnchorPane>

Класс контроллера (TestController.java) имеет следующие значения:

public class TestController implements Initializable{

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

    }

    @FXML 
    public void click(){
        System.out.println("Test");
    }
}

Кнопка успешно отображается в графическом интерфейсе пользователя, и нажатие кнопки также обнаруживается. Кнопка показывает0,1,2,3 .. и т. Д. На выходной консоли.Но тест не печатается на экране.

Как я могу обнаружить нажатие кнопки в классе контроллера приложения? Может ли кто-нибудь помочь мне решить эту проблему.

Большое спасибодля всех.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

добавить свойство слушателя с помощью getter и setter в вашем компонентном контроллере.

Пример Jai корректен, но не согласуется с другими компонентами javafx.Для правильной реализации целесообразно использовать свойства, которыми можно манипулировать как в FXML, так и в ручном режиме.

Это контроллер компонента пользователя, к которому добавлено свойство onMyAction.Это свойство используется для уведомления о событиях.

public class CustomToggleSwitch extends Pane {

    private ObjectProperty<EventHandler<ActionEvent>> onMyAction = new SimpleObjectProperty<EventHandler<ActionEvent>>();

    public CustomToggleSwitch() {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("/sample/CustomToggleSwitch.fxml"));
        loader.setRoot(this);
        loader.setController(this);

        try {
            loader.load();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    private void initialize() {

    }

    @FXML
    private void click(ActionEvent event) {
        if(onMyAction.get() != null) {
            onMyAction.get().handle(event);
        }
    }

    public EventHandler<ActionEvent> getOnMyAction() {
        return onMyAction.get();
    }

    public ObjectProperty<EventHandler<ActionEvent>> onMyActionProperty() {
        return onMyAction;
    }

    public void setOnMyAction(EventHandler<ActionEvent> onMyAction) {
        this.onMyAction.set(onMyAction);
    }
}

С таким структурированным компонентом FXML может добавить свойство onMyAction, например

<AnchorPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" >
    <CustomToggleSwitch onMyAction="#testHandler"/>
</AnchorPane>

public class Controller {

    @FXML
    private void testHandler(ActionEvent event) {

    }

}

или вручную

<AnchorPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" >
    <CustomToggleSwitch fx:id="customToggleSwitch"/>
</AnchorPane>

public class Controller {

    @FXML
    private CustomToggleSwitch customToggleSwitch;

    @FXML
    private void initialize() {
        customToggleSwitch.setOnMyAction(event -> {

        });
    }

}

Обновление

Вам не нужно использовать свойство.Чтобы использовать его из fxml, достаточно сделать его доступным и доступным.(Я не сталкивался со случаем, когда я бы добавил листернер в свойство обработчика событий.)

Это преобразование без использования свойства

public class CustomToggleSwitch extends Pane {

    private EventHandler<ActionEvent> myEventHandler;

    public CustomToggleSwitch() {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("/sample/CustomToggleSwitch.fxml"));
        loader.setRoot(this);
        loader.setController(this);

        try {
            loader.load();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    private void initialize() {

    }

    @FXML
    private void click(ActionEvent event) {
        if(myEventHandler != null) {
            myEventHandler.handle(event);
        }
    }

    public EventHandler<ActionEvent> getOnMyAction() {
        return myEventHandler;
    }

    public void setOnMyAction(EventHandler<ActionEvent> onMyAction) {
        myEventHandler = onMyAction;
    }
}
0 голосов
/ 11 июня 2018

Это происходит потому, что onAction="#click" объявлен в CustomToggleSwitch.fxml, поэтому FXMLLoader будет искать click() в CustomToggleSwitch.java.

Добавление click() в TestController классничего не делать, потому что у вас нет ни одного узла с onAction="#click" в test.fxml.

Один из способов взаимодействия Button в CustomToggleSwitch с классом TestController - это передать событие из.

public class CustomToggleSwitch extends Pane {
    // Same stuff

    private List<Runnable> onClickRunnables = new ArrayList<>();

    public final void addButtonOnClickRunnable(Runnable runnable) {
        Objects.requireNonNull(runnable);
        onClickRunnables.add(runnable);
    }

    @FXML 
    private void click(ActionEvent actionEvent){
        System.out.println(tick++);
        if (!onClickRunnables.isEmpty()) {
            onClickRunnables.forEach(r -> r.run());
        }
    }
}


public class TestController implements Initializable {
    // Give CustomToggleSwitch control an fx:id in FXML
    @FXML private CustomToggleSwitch customSwitch;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        customSwitch.addButtonOnClickRunnable(this::click);
    }
}

Другой способ - выставить Button в CustomToggleSwitch out.Лично я бы посоветовал против этого, потому что лучше скрыть реализацию «контроля».

...