如何使用JavaFX正确实现上一个或下一个按钮事件

如何使用JavaFX正确实现上一个或下一个按钮事件,java,javafx,Java,Javafx,在这里使用JavaFX编写我的第一个程序。该程序显示一个对象(个人)的数据,我想实现一个“previous”按钮,该按钮应使用静态ArrayList“arrayListOfPeople”中的前一个对象刷新窗格 作为一名noob,我希望我可以简单地执行currentPersonPosition-1和loadWindow,如下所示: Button btnBottom = new Button(Integer.toString(currentPersonPosition-1)); final

在这里使用JavaFX编写我的第一个程序。该程序显示一个对象(个人)的数据,我想实现一个“previous”按钮,该按钮应使用静态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);
        }
    };
Button btnBottom=新按钮(Integer.toString(currentPersonPosition-1));
final EventHandler EventHandler=new EventHandler(){
@凌驾
公共无效句柄(MouseEvent e){
加载窗口(currentPersonPosition、边框窗格、其他阶段);
}
};
但是,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();
}
public类主扩展应用程序{
场景=空;
静态ArrayList arrayListOfPeople=new ArrayList();
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公共作废开始(最终阶段初级阶段){
int currentPersonPosition=arrayListOfPeople.size()-1;
final BorderPane BorderPane=新的BorderPane();
场景=新场景(边框窗格,640480);
arrayListOfPeople.add(“Name1”);
arrayListOfPeople.add(“Name2”);
arrayListOfPeople.add(“Name3”);
加载窗口(currentPersonPosition、borderPane、primaryStage);
}
公共void加载窗口(int currentPersonPosition,final BorderPane BorderPane,final Stage另一个Stage){
如果(currentPersonPosition<0)currentPersonPosition=arrayListOfPeople.size()-1;
//底部
按钮btnBottom=新按钮(整数.toString(currentPersonPosition-1));
final EventHandler EventHandler=new EventHandler(){
@凌驾
公共无效句柄(MouseEvent e){
String[]testString=e.getTarget().toString().split(“,”);
System.out.println(testString[0]);
if(testString[0]。包含(“\”){
int-positionOfFirstTextQuote=testString[0]。indexOf(“\”);
int positionOfLastTextQuote=testString[0]。lastIndexOf(“\”);
String currentClipPositionString=testString[0]。子字符串(positionOfFirstTextQuote+1,positionOfLastTextQuote);
int currentPersonPosition=Integer.parseInt(currentClipPositionString);
加载窗口(currentPersonPosition、边框窗格、其他阶段);
}
}
};
btnBottom.addEventHandler(MouseEvent.MOUSE_单击,eventHandler);
borderPane.setBottom(btnBottom);
setTitle(arrayListOfPeople.get(currentPersonPosition));
另一阶段:场景;
另一个阶段。show();
}

}

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

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

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);
        }
    };
final var currentPersonPosition=新对象(){
int值;
};
现在,您可以使用
currentPersonPosition.value
引用变量。这样做的缺点是,您将无法将对象作为参数传递,并且仍然可以访问
value
字段

另一个选项是使用单元素数组:

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

现在,您可以使用
currentPersonPosition[0]引用变量

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

Main

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 + '}';
    }    
}

请问..@kleopatra done您在哪里学会了公共静态void main(String[]args){arrayListOfPeople.add(“Name1”);arrayListOfPeople.add(“Name2”);arrayListOfPeople.add(“Name3”);launch(args);}from?@Sedrick我只是想快速想出一个“可重复性最小的示例。实际程序将json文件中的数据加载到Person对象中,ArrayListPersole是ArrayList谢谢,我使用了“单元素数组”选项,这比我的解决方法好得多。@如果答案解决了您的问题,请随意接受t他回答是为了表明问题已经解决。我肯定会记得,在将来使用重写方法时,这种“单元素数组”方法,否则我无法访问某些变量,因此对此表示感谢!但我现在知道,我可以使用Button.setOnAction而不是EventHandler&重写句柄方法,所以我没有首先是这个问题。谢谢你的回复!使用Button.setOnAction而不是像我那样使用EventHandler&handle()方法解决了主要问题(我无法访问ArrayList变量)。现在了解AtomicInteger也很好。有一些重复的代码(stage.setTitle、lblName.setText和lblAge.setText在start方法中总共是3倍),我会更改它,但您的答复节省了我几个小时,再次感谢!