繁体   English   中英

使用 eclipse 中的 swt 库关闭 Java 中的框架并打开另一个框架

[英]Closing a frame in Java and opening another one, with the swt library from eclipse

我目前正在 Java 中制作一个阅读应用程序,这是我的主菜单:

主菜单

我想要的是,当我在选择一本书后按下底部按钮时,打开另一本书 window,我现在所做的是一个 function,它将打开另一个 window,同时关闭一个memory:我首先关闭当前的 window 在从中检索必要的信息(书的索引)之后,如下所示:

btnOuvrirLeLivre.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            int index = list.getSelectionIndex();
            LiseuseController controller = new LiseuseController(null, null);
            parent.dispose();
            controller.viewBookController(index);       
        }
    });

(我在我的项目中使用 MVC 方法), parent 只是用于打开框架的复合。

public void viewBookController(int index) {
    Display displayBook = new Display();
    Shell shellBook = new Shell(displayBook);
    shellBook.setLayout(new GridLayout(1, false));
    index += 250;
    LiseuseView lecture = new LiseuseView(shellBook, SWT.NONE, index);
    shellBook.pack();
    shellBook.open();
    while(!shellBook.isDisposed()) {
        if(!displayBook.readAndDispatch())
            displayBook.sleep();
    }
    displayBook.dispose();
}

索引只是我数据库中的书号,一切都应该没问题,但是在按下按钮打开书后执行此操作时出现此错误:

Exception in thread "main" org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:4875)
at org.eclipse.swt.SWT.error(SWT.java:4790)
at org.eclipse.swt.SWT.error(SWT.java:4761)
at org.eclipse.swt.widgets.Display.checkDisplay(Display.java:824)
at org.eclipse.swt.widgets.Display.create(Display.java:887)
at org.eclipse.swt.graphics.Device.<init>(Device.java:126)
at org.eclipse.swt.widgets.Display.<init>(Display.java:563)
at org.eclipse.swt.widgets.Display.<init>(Display.java:554)
at Controller.LiseuseController.viewBookController(LiseuseController.java:133)
at View.LiseuseHome$4.widgetSelected(LiseuseHome.java:81)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:252)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:89)
at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4209)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1037)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4026)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3626)
at Controller.LiseuseController.viewController(LiseuseController.java:126)
at Main.Main.main(Main.java:59)

(LiseuseController.java:133) 包含“显示 displayBook = new Display();”

并且 (LiseuseController.java:126) 包含

if(!display.readAndDispatch())
            display.sleep();

这是来自另一个 function 用于打开第一个 window。

我真的不明白是什么导致了这个错误,我不能只把一个放在“可见”而另一个放在“不可见”,就像我使用 Jframe 因为 2 个 window 在 2 个不同上。

您对如何解决此问题有任何想法吗?

来自 org.eclipse.swt.widgets.Display 的org.eclipse.swt.widgets.Display 文档

使用 SWT 构建的应用程序几乎总是只需要一个显示器。 特别是,SWT 支持的某些平台不允许多个活动显示。 换句话说,如果一个已经存在但没有发送 dispose() 消息的平台不支持创建一个新的显示。

因此,您应该调整您的应用程序以仅使用Display的一个实例。 由于 class LiceuseController已经管理打开初始 window 和补充窗口,它似乎适合管理用于两种用途的Display实例。

此实例应在应用程序启动时创建,由LiceuseController class 维护,并最终在应用程序关闭时处理。


另一个问题是, LiceuseController中的所有方法都没有真正返回。 从堆栈跟踪中可以看出,当您创建新的 window 时,来自LiseuseController.viewControllerDisplay.readAndDispatch仍然处于活动状态。 我猜您还想在补充 window 关闭时重新打开原始 window。 但是,以这种方式打开和关闭 windows 会无限增加调用堆栈,直到最终出现StackOverflowException

相反, LiceuseController应该能够在不受外界干扰的情况下创建 windows。 Therefore, instead of actively calling a method in the controller class to open another window, the listener should only tell the controller what window it should open next when the current window was closed.

一个例子可能看起来像

public enum WindowType {
    MAIN, BOOK, NONE
}

public class LiceuseController {

    Display display;
    WindowType nextToOpen = WindowType.MAIN;

    public LiceuseController() {
        display = new Display();
    }

    public void setNextToOpen(WindowType value) {
        nextToOpen = value;
    }

    public void run() {
        for (boolean run = true; run;) {
            switch(nextToOpen) {
            case MAIN:
                viewController();
                break;
            case BOOK:
                viewBookController();
                break;
            case NONE:
                run = false;
                break;
            default:
                throw new RuntimeException("unexpected enum constant");
            }
        }
        /*
         * Depending on how you want to manage the instance of this class,
         * you could also extract this into a separate method.
         */
        display.dispose();
    }

    private void viewController() {
        // open main window using 'display'
    }

    private void viewBookController() {
        // open book window using 'display'
    }

}

这样监听者只需要调用LiceuseController.setNextToOpen ,然后关闭当前的window。 这将导致viewBookController viewController ,之后循环将重新进入并打开请求的 window。 要关闭应用程序,请使用WindowType.NONE调用setNextToOpen

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM