在Java(和SWT)中同步“前端”和“后端”

时间:2014-07-19 13:11:37

标签: java swt frontend backend

编辑:所以代码实际上工作正常 - 所有对象都应该按原样修改。当方法仍然在运行时,只有表面似乎有问题更新...


我正在开展一个项目atm,主要是解决一个推箱子谜语。现在,我们已经实现了GUI和算法的东西来解决这个谜题,但是连接似乎很棘手。 例如,在GUI中我选择“解决”并且算法解决了谜语(在控制台中可见),但GUI不会改变为InGame视图(在调用resolve()之前初始化)。如果我这样做/ / 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()”等等......这就是解决方案在代码中实现的原因。)

1 个答案:

答案 0 :(得分: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将被更新。