我正在尝试创建一个程序来模拟使用Java和JavaFX解决Rubik的Cube。该场景有一个文本框,可以显示计算机以正确表示法进行的每次移动。文本框旁边有一个展开的多维数据集,应该显示多维数据集的当前状态。
问题是GUI只是更新以显示移动列表,以及所有进程最后的多维数据集的状态。我查看了文档,本网站上的其他问题,其他网站上的其他问题,我找不到能解决这个问题的任何问题。我尝试使用PauseTransition,我尝试稍微使用Run Later。这两者似乎都是过于复杂的方法来实现简单的结果。
public class Main extends Application {
@Override
public void start(Stage Stage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("RubiksFXML.fxml"));
Scene scene = new Scene(root, 675, 450);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
Stage.setScene(scene);
Stage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
@FXML
private Button SolveButton;
@FXML
private ImageView s100, s101, s102, s110, s111, s112, s120, s121, s122;
@FXML
private ImageView s200, s201, s202, s210, s211, s212, s220, s221, s222;
@FXML
private ImageView s300, s301, s302, s310, s311, s312, s320, s321, s322;
@FXML
private ImageView s400, s401, s402, s410, s411, s412, s420, s421, s422;
@FXML
private ImageView s500, s501, s502, s510, s511, s512, s520, s521, s522;
@FXML
private ImageView s600, s601, s602, s610, s611, s612, s620, s621, s622;
@FXML
private TextArea MoveRecord;
private char side1[][] = { { 'y', 'y', 'y' }, { 'y', 'y', 'y' }, { 'y', 'y', 'y' } };
private char side2[][] = { { 'o', 'o', 'o' }, { 'o', 'o', 'o' }, { 'o', 'o', 'o' } };
private char side3[][] = { { 'b', 'b', 'b' }, { 'b', 'b', 'b' }, { 'b', 'b', 'b' } };
private char side4[][] = { { 'r', 'r', 'r' }, { 'r', 'r', 'r' }, { 'r', 'r', 'r' } };
private char side5[][] = { { 'w', 'w', 'w' }, { 'w', 'w', 'w' }, { 'w', 'w', 'w' } };
private char side6[][] = { { 'g', 'g', 'g' }, { 'g', 'g', 'g' }, { 'g', 'g', 'g' } };
private char cen = side3[1][1];
private String MoveList = "";
public static void main(String[] args) {
launch(args);
}
@FXML
protected void SolveClicked(ActionEvent event) {
L();
R();
F();
B();
//Refresh does not happen until this point.
//I want it to happen every time the cube is moved
//Hence the OutputCube() function
}
此代码是"转向"左侧是顺时针方向,每个还有11个功能,转动"可能性,以及"顺时针()"哪个"转#34;实际的面孔
private void L() {
OutputCube();
MoveRecord.appendText("L");
char temp;
Clockwise(2);
temp = side5[0][0];
side5[0][0] = side3[0][0];
side3[0][0] = side1[0][0];
side1[0][0] = side6[0][0];
side6[0][0] = temp;
temp = side5[2][0];
side5[2][0] = side3[2][0];
side3[2][0] = side1[2][0];
side1[2][0] = side6[2][0];
side6[2][0] = temp;
temp = side5[1][0];
side5[1][0] = side3[1][0];
side3[1][0] = side1[1][0];
side1[1][0] = side6[1][0];
side6[1][0] = temp;
}
以下功能未完成,只有在片段为黄色时才更新立方体的第一面。此过程实际上执行了5次以检查每种颜色,然后所有六种颜色(使用for循环)再执行五次以更新每一侧。完整的代码会产生所需的结果,但是在每次移动完成之前都不会更新ImageView,尽管在每次移动开始时调用了这个函数。
@FXML
private void OutputCube() {
int imageview = 0;
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
switch (side1[row][col]) {
case 'y':
switch (imageview) {
case 0:
s100.setImage(new Image("yellow.png"));
break;
case 1:
s101.setImage(new Image("yellow.png"));
break;
case 2:
s102.setImage(new Image("yellow.png"));
break;
case 3:
s110.setImage(new Image("yellow.png"));
break;
case 4:
s111.setImage(new Image("yellow.png"));
break;
case 5:
s112.setImage(new Image("yellow.png"));
break;
case 6:
s120.setImage(new Image("yellow.png"));
break;
case 7:
s121.setImage(new Image("yellow.png"));
break;
case 8:
s122.setImage(new Image("yellow.png"));
break;
}
break;
}
imageview++;
}
}
}
答案 0 :(得分:0)
直到最后才看到效果,因为您正在执行FX应用程序线程上的所有内容。这是负责呈现UI的相同线程,因此如果在该线程上执行某些操作(例如您的SolveClicked
[sic:请使用正确的naming conventions]方法),则UI不能是渲染,直到动作完成。
如果你以正确的方式思考这个问题,那么你真正想要做的就是创造一个动画。 (您不仅希望显示解决方案;还希望向用户显示多个“动画帧”,每个“动画帧”代表解决方案中的一个步骤。)因此,您应该使用animation API。最简单的方法可能是Timeline
:
@FXML
protected void solveClicked(ActionEvent event) {
Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(500), e -> L()),
new KeyFrame(Duration.millis(1000), e -> R()),
new KeyFrame(Duration.millis(1500), e -> F()),
new KeyFrame(Duration.millis(2000), e -> B()));
timeline.play();
}
如果你需要一种更“自动化”的方式来生成时间线,你可以做(有趣)的事情:
@FXML
protected void solveClicked(ActionEvent event) {
Runnable[] steps = new Runnable[] {this::L, this::R, this::F, this::B};
createTimeline(steps, 500).play();
}
private Timeline createTimeline(Runnable[] steps, int delay) {
Duration frameTime = Duration.millis(delay);
Duration increment = Duration.millis(delay);
Timeline timeline = new Timeline() ;
for (Runnable step : steps) {
timeline.getKeyFrames().add(new KeyFrame(frameTime, e -> step.run()));
frameTime = frameTime.add(increment);
}
return timeline ;
}
更复杂的方法可能是通过动画表示脸部的每次移动(显示实际旋转),然后将它们全部合并为SequentialTransition
。