当前位置: 首页 > 面试题库 >

刷新JavaFX GUI

袁秦迟
2023-03-14
问题内容

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

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

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()”可“旋转”实际的脸

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

    }
}

问题答案:

直到最后您都看不到效果,因为您正在FX Application
Thread上执行所有操作。这是负责呈现UI的同一线程,因此,如果对该线程执行了某些操作(例如SolveClicked[sic:请使用正确的命名约定
]方法),则在操作完成之前无法呈现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



 类似资料:
  • 问题内容: 如果将新文档索引到Elasticsearch索引,则可在索引操作后1秒钟左右搜索新文档。但是,可以通过调用或对索引进行操作来强制使该文档可立即搜索。这两个操作之间有什么区别- 结果似乎对他们来说是相同的,可以立即搜索文档。 这些操作中的每一项到底是什么? ES文档似乎并未深入解决此问题。 问题答案: 您得到的答案是正确的,但我认为值得详细说明。 刷新有效地调用了Lucene索引读取器上

  • 2.12 刷新 2.12.1 描述 此接口用于增加内容刷新任务 2.12.2 请求地址 地址: https://api.bokecs.com/cont/add_refresh 2.12.3 请求方式 POST 2.12.4 请求参数 1) 请求入参 Urls 待刷新的链接 2)请求出参 { "code": "", "message": "" } code:接口响应代码。200表示成功。 mess

  • 问题内容: 我有一个文件,其中我在页面顶部显示外部页面(使用iframe),其他部分是写在文件中的html代码的输出。 HTML代码如下所示: 现在,我想以编程方式刷新页面而不刷新。 我的问题是我可以不刷新页面就刷新页面吗? 答案/提示将不胜感激。 问题答案: 该嵌在主HMTL页面(或在JSP)。因此,如果刷新页面,则肯定会再次加载iframe。 为了避免这种情况,我可以考虑以下两种选择: 使用A

  • 问题内容: 我有使用JPA的Web应用程序。这个实体经理保持一堆实体,突然间我从另一侧更新了数据库。我使用 MySQL, 并使用 PhpMyAdmin 并更改一些行。 如何告诉实体管理器重新同步,例如忘记缓存中的所有实体? 我知道有方法,但是有可能怎么做或导致什么结果? 可以肯定,这是昂贵的操作,但必须执行。 问题答案: 有所不同,因为它 修改了您的对象 。该行将是,因此,如果您在实体管理器外部获

  • 有没有办法使用下面的代码来刷新已经存在的div id,而不是刷新时间? 假设我要用我想刷新的id替换时间id,我会在. innerHTML=??? 这是我需要每秒刷新的div。 [addItemsHTML]不知何故从一个软件中提取数据,告诉你什么是到期的,什么不是,但是脚本并没有每秒钟拉一次时间,浏览器刷新时只是改变了到期状态列上的时间。 现在我用这个来刷新整个页面,我只需要刷新绘图目录。

  • 掌握刷新方法 iScroll需要知道包装器和滚动器确切的尺寸,在iScroll初始化的时候进行计算,如果元素大小发生了变化,需要告诉iScroll DOM发生了变化。 下面将提供调用refresh方法的正确时机。 每次触摸DOM,浏览器渲染器重绘页面。一旦发生了重画我们可以安全地读新的DOM属性。重新绘制阶段不是瞬时发生的只是范围结束时触发。这就是为什么我们需要给渲染器刷新iScroll之前一点时

  • 描述 (Description) 它是一个特殊的组件,用于通过拉取它来刷新(重新加载)页面内容。 以下代码显示了如何刷新页面内容 - <div class = "page"> <!-- Page content should have additional "pull-to-refresh-content" class --> <div class = "page-content pu

  • 问题内容: 我希望我知道此列表中每个项目的确切功能,工作原理,后果以及何时使用正确的时间。 刷新 驱逐 复制 冲洗 我什至不知道每个人的工作,但是我不确定,所以我要求您的帮助,因为我真的很想了解它。 我知道这是一个非常笼统的问题,但是我认为了解这一切真的很有用。 谢谢。 问题答案: 在 Hibernate文档提供了很好的例证。另外,此博客文章还将为您提供一些见识。我将从下面添加一些行。 使用该方法