所以我跟着this blog(特别是part 2)来创建自定义控件并将其导入到Scene Builder中。
这就是它的样子:
这是fxml文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="30.0" prefWidth="150.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox alignment="CENTER" layoutX="-65.0" layoutY="-56.0" spacing="5.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Button fx:id="previousButton" minWidth="25.0" mnemonicParsing="false" prefWidth="25.0" text="<" />
<Label fx:id="label" alignment="CENTER" contentDisplay="CENTER" prefWidth="500.0" text="Label" />
<Button fx:id="nextButton" minWidth="25.0" mnemonicParsing="false" prefWidth="25.0" text=">" />
</children>
</HBox>
</children>
</fx:root>
这是类文件:
package swipeselector;
import java.io.IOException;
import java.util.ArrayList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
/**
*
* @author patrickb
*/
public class SwipeSelector extends AnchorPane {
@FXML
private Button previousButton;
@FXML
private Label label;
@FXML
private Button nextButton;
ArrayList<String> items;
int selectedIndex;
private boolean repetitive;
public SwipeSelector() {
FXMLLoader fxmlLoader = new FXMLLoader(
getClass().getResource("swipeSelectorFXML.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
items = new ArrayList<>();
selectedIndex = 0;
previousButton.setOnAction((ActionEvent event) -> {
setPrevious();
});
nextButton.setOnAction((ActionEvent event) -> {
setNext();
});
}
public void setItems(ArrayList<String> items) {
this.items = items;
selectFirst();
}
public void setPrevious() {
updateItem(selectedIndex - 1);
}
public void setNext() {
updateItem(selectedIndex + 1);
}
public void selectFirst() {
updateItem(0);
}
private void selectLast() {
updateItem(items.size() - 1);
}
private void updateItem() {
if (items.isEmpty()) {
label.setText("");
} else {
if (selectedIndex < 0) {
if (repetitive) {
selectedIndex = items.size() - 1;
} else {
selectedIndex = 0;
}
}
if (selectedIndex >= items.size()) {
if (repetitive) {
selectedIndex = 0;
} else {
selectedIndex = items.size() - 1;
}
}
label.setText(items.get(selectedIndex));
}
}
private void updateItem(int selectedIndex) {
this.selectedIndex = selectedIndex;
updateItem();
}
public void setRepetitive(boolean cyclesThrough) {
this.repetitive = cyclesThrough;
}
}
一切正常,但是:当我点击下一个或上一个按钮时,我希望在原始项目中发生一些事情。我通常会通过向对象添加setOnAction(new EventHandler ...
方法来完成此操作。但是这个方法不存在,所以我不知何故需要将它添加到我的自定义控件中。 每次单击两个按钮中的一个时,如何让我的自定义控件调用ActionEvent,以及如何为我的对象创建一个setOnAction方法?
答案 0 :(得分:1)
您需要创建自定义事件。不幸的是,关于这一点的信息很少。您可以查看ButtonBase的源代码以获取示例。
您需要定义onAction属性:
ObjectProperty<EventHandler<ActionEvent>> onAction
我为此实现了一个实用程序类:SimpleEventHandlerProperty
您可以在此处使用SimpleEventHandlerProperty找到完整的示例:LeftTestPane.java
您可以从Maven Central获取图书馆:
<dependency>
<groupId>org.drombler.commons</groupId>
<artifactId>drombler-commons-fx-core</artifactId>
<version>0.6</version>
</dependency>
答案 1 :(得分:1)
我找到了让它发挥作用的方法。以下代码被添加到类文件中(它基本上是从ButtonBase复制的。
public final ObjectProperty<EventHandler<ActionEvent>> onActionProperty() { return onAction; }
public final void setOnAction(EventHandler<ActionEvent> value) { onActionProperty().set(value); }
public final EventHandler<ActionEvent> getOnAction() { return onActionProperty().get(); }
private ObjectProperty<EventHandler<ActionEvent>> onAction = new ObjectPropertyBase<EventHandler<ActionEvent>>() {
@Override protected void invalidated() {
setEventHandler(ActionEvent.ACTION, get());
}
@Override
public Object getBean() {
return SwipeSelector.this;
}
@Override
public String getName() {
return "onAction";
}
};
此外,每当您希望触发Action Event的某些事情发生时,调用方法fireEvent(new ActionEvent());
将为您执行此操作。此方法返回到Node类,它继承到此类,因为它扩展了AnchorPane(从Node继承了fireEvent
方法)。
所以在我的情况下,我用这两个按钮替换了我的两个onAction方法:
previousButton.setOnAction((ActionEvent event) -> {
setPrevious();
fireEvent(event);
});
nextButton.setOnAction((ActionEvent event) -> {
setNext();
fireEvent(event);
});
现在,每当按下两个按钮中的一个时,就会触发一个ActionEvent(我刚刚为此目的传递了按钮事件),我可以通过添加
在我的项目中捕获它swipeSelector.setOnAction((ActionEvent event) -> {
System.out.println("Event fired!!!");
//DO SOMETHING
});
像往常一样。