JavaFx:处理大量按钮的最佳实践是什么
我正在使用JavaFx编写一个项目,它是一个3D Tic Tac Toe,我有一个3D 4*4*4页面,我用scene builder 2.0设计了这个页面,并放置了许多按钮作为控件,所以当你点击一个按钮时,它的文本会变成“R”,当计算机选择它的移动时,它会变成“B”,总之,这是我的控制器类的一个示例:JavaFx:处理大量按钮的最佳实践是什么,java,javafx,Java,Javafx,我正在使用JavaFx编写一个项目,它是一个3D Tic Tac Toe,我有一个3D 4*4*4页面,我用scene builder 2.0设计了这个页面,并放置了许多按钮作为控件,所以当你点击一个按钮时,它的文本会变成“R”,当计算机选择它的移动时,它会变成“B”,总之,这是我的控制器类的一个示例: public class Controller { @FXML private Button b131; @FXML private Button b111; @FXML private B
public class Controller {
@FXML
private Button b131;
@FXML
private Button b111;
@FXML
private Button b133;
@FXML
private Button b232;
@FXML
private Button b331;
@FXML
private Button b132;
@FXML
private Button b231;
@FXML
private Button b314;
@FXML
private Button b113;
@FXML
private Button b234;
@FXML
private Button b212;
@FXML
private Button b333;
@FXML
private Button b311;
...
@FXML
public void Initialize() {
assert b131 != null : "fx:id=\"b131\" was not injected: check your FXML file 'Scene.fxml'.";
assert b111 != null : "fx:id=\"b111\" was not injected: check your FXML file 'Scene.fxml'.";
assert b133 != null : "fx:id=\"b133\" was not injected: check your FXML file 'Scene.fxml'.";
assert b232 != null : "fx:id=\"b232\" was not injected: check your FXML file 'Scene.fxml'.";
assert b331 != null : "fx:id=\"b331\" was not injected: check your FXML file 'Scene.fxml'.";
assert b132 != null : "fx:id=\"b132\" was not injected: check your FXML file 'Scene.fxml'.";
assert b231 != null : "fx:id=\"b231\" was not injected: check your FXML file 'Scene.fxml'.";
assert b314 != null : "fx:id=\"b314\" was not injected: check your FXML file 'Scene.fxml'.";
assert b113 != null : "fx:id=\"b113\" was not injected: check your FXML file 'Scene.fxml'.";
assert b234 != null : "fx:id=\"b234\" was not injected: check your FXML file 'Scene.fxml'.";
assert b212 != null : "fx:id=\"b212\" was not injected: check your FXML file 'Scene.fxml'.";
assert b333 != null : "fx:id=\"b333\" was not injected: check your FXML file 'Scene.fxml'.";
assert b311 != null : "fx:id=\"b311\" was not injected: check your FXML file 'Scene.fxml'.";
assert b112 != null : "fx:id=\"b112\" was not injected: check your FXML file 'Scene.fxml'.";
assert b134 != null : "fx:id=\"b134\" was not injected: check your FXML file 'Scene.fxml'.";
assert b233 != null : "fx:id=\"b233\" was not injected: check your FXML file 'Scene.fxml'.";
assert b211 != null : "fx:id=\"b211\" was not injected: check your FXML file 'Scene.fxml'.";
assert b332 != null : "fx:id=\"b332\" was not injected: check your FXML file 'Scene.fxml'.";
assert b214 != null : "fx:id=\"b214\" was not injected: check your FXML file 'Scene.fxml'.";
assert b313 != null : "fx:id=\"b313\" was not injected: check your FXML file 'Scene.fxml'.";
assert b114 != null : "fx:id=\"b114\" was not injected: check your FXML file 'Scene.fxml'.";
assert b213 != null : "fx:id=\"b213\" was not injected: check your FXML file 'Scene.fxml'.";
assert b334 != null : "fx:id=\"b334\" was not injected: check your FXML file 'Scene.fxml'.";
assert b312 != null : "fx:id=\"b312\" was not injected: check your FXML file 'Scene.fxml'.";
assert b142 != null : "fx:id=\"b142\" was not injected: check your FXML file 'Scene.fxml'.";
assert b241 != null : "fx:id=\"b241\" was not injected: check your FXML file 'Scene.fxml'.";
assert b141 != null : "fx:id=\"b141\" was not injected: check your FXML file 'Scene.fxml'.";
assert b122 != null : "fx:id=\"b122\" was not injected: check your FXML file 'Scene.fxml'.";
assert b144 != null : "fx:id=\"b144\" was not injected: check your FXML file 'Scene.fxml'.";
assert b243 != null : "fx:id=\"b243\" was not injected: check your FXML file 'Scene.fxml'.";
assert b221 != null : "fx:id=\"b221\" was not injected: check your FXML file 'Scene.fxml'.";
assert b342 != null : "fx:id=\"b342\" was not injected: check your FXML file 'Scene.fxml'.";
assert b121 != null : "fx:id=\"b121\" was not injected: check your FXML file 'Scene.fxml'.";
assert b143 != null : "fx:id=\"b143\" was not injected: check your FXML file 'Scene.fxml'.";
...
我已经设置了我的按钮fx:id在这个逻辑中,'b'代表按钮,第一个整数代表它的页面,第二个和第三个整数代表该按钮的行和列,现在我的问题是事件处理,我已经编写了一个函数,它可以这样做,并通过scene builder的代码部分连接到我的按钮,它可以工作:
public void ButtonHandler(){
b111.setOnAction(new EventHandler<javafx.event.ActionEvent>() {
@Override
public void handle(javafx.event.ActionEvent event) {
b111.setText("R");
}
});
...
public void ButtonHandler(){
b111.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(javafx.event.ActionEvent){
b111.setText(“R”);
}
});
...
但我希望按钮名称是一种动态的,但我不知道如何有效地做到这一点。
任何帮助都将不胜感激。我想我通常建议不要在FXML中创建类似的按钮,而是在控制器代码的循环中创建它们。因此,您的FXML文件可以定义布局:
然后,控制器可以使用明显的for
循环简洁地定义按钮:
package tictactoe3d;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
public class GameController {
@FXML
private GridPane page0 ;
@FXML
private GridPane page1 ;
@FXML
private GridPane page2 ;
@FXML
private GridPane page3 ;
public void initialize() {
GridPane[] pages = {page0, page1, page2, page3};
for (int page = 0; page < 4; page++) {
for (int row = 0; row < 4; row ++) {
for (int col = 0; col < 4; col++) {
Button button = new Button("O");
pages[page].add(button, col, row);
String message = "Button pressed on page "+page+" row "+row+" column "+col;
button.setOnAction(e -> {
button.setText("R");
// replace with real data update:
System.out.println(message);
});
}
}
}
}
}
您甚至可以更进一步,定义一个带有四个按钮的“行”FXML,并使页面包含它的四个副本(而不是16个按钮)但是,这将阻止您使用
GridPane
;您必须使用包含HBox
es的VBox
,这可能会使您很难将所有内容都保存在网格中。我想我通常建议不要在FXML中创建类似的按钮,而是在控制器代码中的循环中创建它们。因此,您的FXML文件可以定义布局:
然后,控制器可以使用明显的for
循环简洁地定义按钮:
package tictactoe3d;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
public class GameController {
@FXML
private GridPane page0 ;
@FXML
private GridPane page1 ;
@FXML
private GridPane page2 ;
@FXML
private GridPane page3 ;
public void initialize() {
GridPane[] pages = {page0, page1, page2, page3};
for (int page = 0; page < 4; page++) {
for (int row = 0; row < 4; row ++) {
for (int col = 0; col < 4; col++) {
Button button = new Button("O");
pages[page].add(button, col, row);
String message = "Button pressed on page "+page+" row "+row+" column "+col;
button.setOnAction(e -> {
button.setText("R");
// replace with real data update:
System.out.println(message);
});
}
}
}
}
}
您甚至可以更进一步,定义一个带有四个按钮的“行”FXML,并使页面包含它的四个副本(而不是16个按钮)。这将阻止您使用
GridPane
;您必须使用包含HBox
es的VBox
,这可能会使您很难将所有内容都保存在网格中。也许最好不要在FXML中创建这些按钮。在FXML中创建用于保存按钮的窗格和其他控件,然后创建并添加按钮在Java代码中。这样你可以使用循环和数组等。@fabian链接答案的可能重复非常好:使用64个按钮可能会延长你的理智。创建一个窗格,按所需次数迭代循环,然后创建一次按钮。我会减少LOC,这也是最佳做法。也许最好不要这样做o在FXML中创建这些按钮。在FXML中创建用于保存按钮的窗格和其他控件,然后在Java代码中创建和添加按钮。这样,您可以使用循环和数组等。@fabian链接答案的可能重复非常好:使用64个按钮可能会让您的理智有所放松。创建一个窗格并迭代循环r所需的次数并创建一次按钮。我将减少LOC,这也是最佳做法。对于for
循环中声明的这些按钮,我如何访问它们并处理我提到的另一个事件,即放置“B”在不丢失当前按钮的情况下被对手使用?我尝试在for循环外部声明按钮,并在内部声明新按钮,以便通过整个方法访问,但随后我丢失了该按钮的坐标,函数无法将按钮的文本设置为所需字符串,你知道吗?我没有真正理解您所要求的;当您在循环中创建按钮时,您可能只需要注册您需要的其他处理程序。但是,如果您以后确实需要访问所有按钮,只需创建一个数组,即Button[][][]allButtons=newbutton[4][4][4];
并将您创建的按钮放入数组中:allButtons[page][row][col 2]=button;
。那么我可以在最内部循环之外处理我的任何按钮,或者将单击的按钮发送到另一个联机方法吗?要在循环之外引用它们(可能在循环的最后一次迭代中创建的按钮除外),需要将它们存储在数组中。我不理解最后一部分…你是说button.setOnAction(e->somethod(button));
可能,这(显然)是可能的。如果您想要方法中按钮在网格中的位置,那么您也应该传递它,即button.setOnAction(e->somethod(button,page,row,col))
。对于for
循环中声明的这些按钮,我如何能够访问它们并处理我提到的另一个事件,即放置“B”在不丢失当前按钮的情况下被对手使用?我尝试在for循环外部声明按钮,并在内部声明新按钮,以便通过整个方法访问,但随后我丢失了该按钮的坐标,函数无法将按钮的文本设置为所需字符串,你知道吗?我没有真正理解您所要求的;当您在循环中创建按钮时,您可能只需要注册您需要的其他处理程序。但是,如果您以后确实需要访问所有按钮,只需创建一个数组,即Button[][][]allButtons=newbutton[4][4][4];
并将您创建的按钮放入数组中:allButtons[page][row][col 2]=按钮;
。我能处理任何
package tictactoe3d;
import javafx.fxml.FXML;
public class GameController {
@FXML
private PageController page0Controller ;
@FXML
private PageController page1Controller ;
@FXML
private PageController page2Controller ;
@FXML
private PageController page3Controller ;
public void initialize() {
page0Controller.setPage(0);
page1Controller.setPage(1);
page2Controller.setPage(2);
page3Controller.setPage(3);
}
}