如何使用JavaFX正确实现Previous或Next按钮事件



在这里使用JavaFX编写我的第一个程序。该程序显示对象(Person(的数据,我想实现一个"上一个"按钮,该按钮应使用静态ArrayList"arrayListOfPeople"中的上一个对象刷新窗格。

作为一个noob,我希望我可以简单地做currentPersonPosition-1和loadWindow,如下所示:

Button btnBottom = new Button(Integer.toString(currentPersonPosition-1));
final EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
loadWindow(currentPersonPosition, borderPane, anotherStage);
}
};

但是,handle((方法不能使用currentPersonPosition变量,因为内部方法似乎只能使用最终实例变量。。。那你该如何妥善处理呢?

我写了一些肯定不是正确的方法:我已经将按钮文本设置为currentPersonPosition-1,然后阅读&解析handle方法中的值。在花了很多时间想出这个愚蠢的变通办法之后,我想知道它是如何正确完成的。

下面的最小可生产示例打开一个窗口,在窗口标题栏中显示Name1/Name2/Name3,并在左下角包含一个小按钮,用作"上一个"按钮。

提前感谢!

public class Main extends Application {
Scene scene = null;
static ArrayList<String> arrayListOfPeople = new ArrayList<>();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(final Stage primaryStage) {
int currentPersonPosition = arrayListOfPeople.size() - 1;
final BorderPane borderPane = new BorderPane();
scene = new Scene(borderPane, 640, 480);
arrayListOfPeople.add("Name1");
arrayListOfPeople.add("Name2");
arrayListOfPeople.add("Name3");
loadWindow(currentPersonPosition, borderPane, primaryStage);
}
public void loadWindow(int currentPersonPosition, final BorderPane borderPane, final Stage anotherStage) {
if (currentPersonPosition < 0) currentPersonPosition = arrayListOfPeople.size()-1;
// BOTTOM
Button btnBottom = new Button(Integer.toString(currentPersonPosition-1));
final EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
String[] testString = e.getTarget().toString().split(",");
System.out.println(testString[0]);
if (testString[0].contains(""")) {
int positionOfFirstTextQuote = testString[0].indexOf(""");
int positionOfLastTextQuote = testString[0].lastIndexOf(""");
String currentClipPositionString = testString[0].substring(positionOfFirstTextQuote + 1, positionOfLastTextQuote);
int currentPersonPosition = Integer.parseInt(currentClipPositionString);
loadWindow(currentPersonPosition, borderPane, anotherStage);
}
}
};
btnBottom.addEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);
borderPane.setBottom(btnBottom);
anotherStage.setTitle(arrayListOfPeople.get(currentPersonPosition));
anotherStage.setScene(scene);
anotherStage.show();
}

}

有各种方法可以解决这个问题,但它们的工作方式都是相同的;您需要将值封装在Object中。

如果您使用的是Java 10或更高版本,则可以将匿名内部类与局部变量类型推断一起使用。像这样声明变量:

final var currentPersonPosition = new Object() {
int value;
};

现在,您可以使用currentPersonPosition.value引用该变量。这样做的缺点是,您将无法将Object作为参数传递,并且仍然可以访问value字段。

另一种选择是使用单一元素数组:

final int[] currentPersonPosition = new int[1];

现在可以使用currentPersonPosition[0]引用该变量。

解决这个问题的关键是使用计数器变量来跟上当前位置。不应允许该计数器变量大于列表大小-1或小于0。如果您是初学者,我建议您使用匿名内部类创建按钮处理程序,如以下示例所示。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

/**
* JavaFX App
* @Author Sedrick (SedJ601)
*/
public class App extends Application {
List<Person> listOfPeople = new ArrayList();
AtomicInteger currentPosition = new AtomicInteger();
Label lblName;
Label lblAge;

@Override
public void start(Stage stage) {
listOfPeople.add(new Person("John Doe", 22));
listOfPeople.add(new Person("Jane Doe", 21));
listOfPeople.add(new Person("Kim Doe", 5));
listOfPeople.add(new Person("John Doe Jr", 3));

//Load the first Person
stage.setTitle(listOfPeople.get(currentPosition.get()).getName());
Label lblNameTag = new Label("Name: ");
lblName = new Label(listOfPeople.get(currentPosition.get()).getName());
Label lblAgeTag = new Label("Age: ");
lblAge = new Label(Integer.toString(listOfPeople.get(currentPosition.get()).getAge()));    

//Use a GridPane to display the name and age.
GridPane gridPane = new GridPane();
gridPane.setMaxSize(Control.USE_PREF_SIZE, Control.USE_PREF_SIZE);
gridPane.add(lblNameTag, 0, 0);
gridPane.add(lblName, 1, 0);
gridPane.add(lblAgeTag, 0, 1);
gridPane.add(lblAge, 1, 1);

//Create Previous and Next Buttons with their handlers
Button btnPrevious = new Button("<");
btnPrevious.setOnAction((t) -> {
System.out.println(currentPosition.get());
if(currentPosition.get() > 0)
{                
currentPosition.decrementAndGet();
stage.setTitle(listOfPeople.get(currentPosition.get()).getName());
lblName.setText(listOfPeople.get(currentPosition.get()).getName());
lblAge.setText(Integer.toString(listOfPeople.get(currentPosition.get()).getAge())); 
}
});
Button btnNext = new Button(">");
btnNext.setOnAction((t) -> {
System.out.println(currentPosition.get());
if(currentPosition.get() < listOfPeople.size() - 1)
{                
currentPosition.incrementAndGet();
stage.setTitle(listOfPeople.get(currentPosition.get()).getName());
lblName.setText(listOfPeople.get(currentPosition.get()).getName());
lblAge.setText(Integer.toString(listOfPeople.get(currentPosition.get()).getAge())); 
}
});
HBox hBox = new HBox(btnPrevious, btnNext);
hBox.setAlignment(Pos.CENTER);

BorderPane root = new BorderPane();
root.setCenter(gridPane);
root.setBottom(hBox);

var scene = new Scene(root, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}

人员

/**
*
* @author sedrick (SedJ601)
*/
class Person 
{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" + "name=" + name + ", age=" + age + '}';
}    
}

最新更新