刷新JavaFX GUI [英] Refreshing a JavaFX GUI

查看:53
本文介绍了刷新JavaFX GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个程序,以使用Java和JavaFX模拟Rubik's Cube的求解.该场景具有一个文本框,该文本框将以正确的方式显示计算机所做的每一个动作.文本框旁边有一个展开的多维数据集,其中显示多维数据集的当前状态.

I am attempting to create a program to simulate a solve of a Rubik's Cube using Java and JavaFX. The scene has a text box that will show every move the computer makes in proper notation. Next to the text box there is an unfolded cube which should show the current state of the cube.

问题在于,GUI仅在更新时显示移动列表,并且在所有进程的最后显示多维数据集的状态.我已经浏览了文档,该站点上的其他问题,其他站点上的其他问题,但找不到任何能够解决此问题的方法.我尝试使用PauseTransition,然后尝试使用稍后运行.这两种方法似乎都过于复杂,无法获得简单的结果.

The problem is that the GUI is only updating to show the list of moves, and the state of the cube at the very end of all processes. I have looked through the documentation, other questions on this site, other questions on other sites, and I have not been able to find anything that would solve this problem. I tried using PauseTransition, and I tried using Run Later a little bit. Both of these seemed like overly complicated ways to achieve a simple result.

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个功能,以及"Clockwise()"转"实际脸的代码

This code is the code to "turn" the left face clockwise, there are 11 more functions for each "turning" possibility, as well as "Clockwise()" which "turns" the actual face

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循环)执行五次以更新每一侧.完整的代码可以产生理想的结果,但是,尽管在每次移动开始时都调用了此函数,但直到进行了每次移动之后,它都不会更新ImageViews.

The following function is not complete this only updates the first side of the cube if the piece is yellow. This procedure is actually performed 5 more times to check each color, then all six colors (with the for loops), are performed five more times to update each side. The complete code produces the desired result, but does not update the ImageViews until every move has been made despite the calling of this function at the beginning of each move.

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

    }
}

推荐答案

直到结束,您才看到效果,因为您正在FX Application Thread上执行所有操作.这是负责呈现UI的同一线程,因此,如果执行某些操作(例如您的SolveClicked [sic:请使用正确的

You don't see the effect until the end because you are executing everything on the FX Application Thread. This is the same thread that is responsible for rendering the UI, so if some action (such as your SolveClicked [sic: please use proper naming conventions] method) is performed on that thread, the UI cannot be rendered until the action is complete.

如果您以正确的方式考虑问题,那么您真正想做的就是创建动画. (您不仅要显示解决方案,还想向用户显示多个动画帧",每个动画帧代表解决方案中的一个步骤.)因此,您应该使用 Timeline :

If you think about this the right way, what you are really trying to do is create an animation. (You don't just want to show the solution; you want to show multiple "animation frames" to the user, each of which represents a step in the solution.) So you should use the animation API. The simplest way might be a 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();
}

如果您需要一种更为自动化"的方式来生成时间轴,则可以进行以下操作(有趣):

If you need a more "automated" way of generating the timeline, you can do (fun) things like:

@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 ;
}

一种更复杂的方法可能是通过动画(显示实际旋转)来表示面孔的每一个动作,然后将它们全部组合成

A more sophisticated approach might be to represent each move of a face by an animation (showing the actual rotation), and then combine them all into a SequentialTransition.

这篇关于刷新JavaFX GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆