【问题标题】:Synchronizing "Frontend" and "Backend" in Java (and SWT)在 Java(和 SWT)中同步“前端”和“后端”
【发布时间】:2014-07-19 13:11:36
【问题描述】:

编辑:所以代码实际上工作正常 - 所有对象都按应有的方式修改。在方法仍在运行时,似乎只有表面出现自我更新问题...


我正在开发一个项目 atm,它基本上是关于解决推箱子谜题。现在,我们已经实现了 GUI 和算法的东西来解决这个谜,但连接似乎很棘手。 例如,在 GUI 中我选择“解决”并且算法解决了谜题(在控制台中可见),但 GUI 不会更改为 InGame 视图(在调用 solve() 之前初始化。如果我这样做 / /switchToRoboControl() 它将立即显示 InGame!)。在solve()完成后会切换到InGame,这很不方便,因为它应该显示图标在地图上移动并解决谜题。

所以我的实际问题是:我如何正确地同步前端和后端,以便如果后端移动并通知前端,前端实际上会显示发生了什么。

另外,如果有人对此有任何想法,为什么 InGame 会在solve() 完成后出现,即使它之前已初始化并且即使isVisible() 返回true?

如果有帮助,我可以发布代码,但有数千行,所以我想也许可以解释问题并获得可以帮助我解决这个问题的提示就足够了......

谢谢!



    public class SokobanGUIManager {
    public SokobanGUIManager() {
            this.display = new Display();

            //initialsiere Shell
            this.shell = new Shell(this.display);
            shell.setText("Sokobots - The absolute best Sokoban-Solver you've ever seen!");
            shell.setSize(735, 460);

            //initialisiere Stack-Layout
            this.layout = new StackLayout();
            shell.setLayout(layout);
            shell.layout();

            //öffne Main-Menü;
            goToMainMenu();

            //Starte Fenster
            this.shell.open();

            //Lebensschleife
            while (!this.shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                display.sleep();
                }
            }
        }
    }

    public class InGameGUI extends Composite {
       ...
       public void initRoboControl() {
            this.roboControl = new RoboControlGUI(this, manager, map, map.twoRobos(), this, this.roboStream); //RoboControlGUI is a child-Composite of InGameGUI
            this.roboControl.setLayoutData(new RowData(300, 400));
            this.layout();
            this.guiCoordinator.setRoboControl(this.roboControl);
            this.guiCoordinator.switchToRoboControl();
        }
        ...
    }

    public class GUICoordinator {
        ...
        protected void switchToRoboControl() {
            if(this.roboControl != null) {
                this.roboControl.setVisible(true);
                System.out.println("RoboControl is visible");
                this.roboCoordinator.switchToRoboControl();

            } else {
                System.out.println("Epic fail");
            }
        }
        ...
    }

    public class RoboCoordinator {
        public void switchToRoboControl() { //TODO
            this.gui.addToStreamEnd("switched to automatic control");
            this.gui.deleteFirstLine();
            this.gui.addToStreamEnd("the robots are calculating a solution. please wait");
            try{ Thread.sleep(5000); } catch(Exception e) {}

            this.map.setSolution(new Solution("1u:1l:1r:1d"));
            this.gui.deleteFirstLine();
            this.gui.deleteFirstLine();

            this.gui.addToStreamEnd("robot 1 in direction u");
            this.gui.addToStreamEnd("robot 1 in direction l");
            this.gui.addToStreamEnd("robot 1 in direction r");
            this.gui.addToStreamEnd("robot 1 in direction d");

            try{ Thread.sleep(2000); } catch (Exception e) {}

            this.map.moveRobo(1, 'u');
            this.gui.updateMoves();
            this.gui.updateSurface();
            this.gui.deleteFirstLine();
            System.out.println(this.map.toString());

            System.out.println("Erster Zug fertig!");

            try{ Thread.sleep(2000); } catch (Exception e) {}

            this.map.moveRobo(1, 'l');
            this.gui.updateMoves();
            this.gui.updateSurface();
            this.gui.deleteFirstLine();
            System.out.println(this.map.toString());

            System.out.println("Zweiter Zug fertig!");

            try{ Thread.sleep(2000); } catch (Exception e) {}

            this.map.moveRobo(1, 'r');
            this.gui.updateMoves();
            this.gui.updateSurface();
            this.gui.deleteFirstLine();
            System.out.println(this.map.toString());

            try{ Thread.sleep(2000); } catch (Exception e) {}

            this.map.moveRobo(1, 'd');
            this.gui.updateMoves();
            this.gui.updateSurface();
            this.gui.deleteFirstLine();
            System.out.println(this.map.toString());

        }
    }

(最后一部分是集成测试的模拟,稍后将被真实的方法调用所取代,例如“getSolution()”等......这就是解决方案在代码中实现的原因。)

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建最小、完整和可验证的示例。 stackoverflow.com/help/mcve
  • 对不起!我不知道我必须精确到什么程度。我添加了与我的问题直接相关的代码。感谢您的反馈。
  • 您的代码与描述不符?解决()在哪里?
  • 抱歉,当我还没有代码时,solve() 就在那里。我试图简化它。 solve() 与 switchToRoboControl() 基本相同

标签: java swt frontend backend


【解决方案1】:

好吧,据我所知,您的问题是计算逻辑与 GUI 在同一线程中运行。 这会导致计算期间不进行更新。 您需要将计算放在后台线程中。此外,您的 Thread.sleep() 将导致 GUI 什么也不做。

所以,把你的计算,例如在 Runnable 中。

Runnable runnable = new Runnable(Display display) {
... some methods ...
    @Override run() {
        ... your logic ...
        display.asyncExec(new Runnable() {
            run() {
            // update your gui here
            });
      ... some more logic ...
};

Display.asyncExec 会将您的更改转发到 gui 并立即返回到调用方法。 UI 会在显示线程有时间时更新。

【讨论】:

  • 这听起来合乎逻辑,但是当我按照建议将计算放在单独的线程中并刷新 gui 时,它将不再显示起始页面,而是显示混乱的 inGame。计算完成后 InGame 看起来会很好...
猜你喜欢
  • 1970-01-01
  • 2018-03-30
  • 2012-02-21
  • 1970-01-01
  • 2018-02-24
  • 2020-08-17
  • 2012-07-16
  • 1970-01-01
  • 2023-01-24
相关资源
最近更新 更多