【问题标题】:"Independent" GUI window launching“独立”GUI 窗口启动
【发布时间】:2011-03-13 09:36:35
【问题描述】:

我对 GUI 编程相当陌生,我正在尝试在 D 中编写一个绘图库,以与一些其他基于控制台的科学应用程序一起使用。我使用 DFL 作为我的 GUI 库。

假设我的绘图表单有一个名为showPlot() 的方法,它应该在屏幕上显示绘图。我希望能够让我的应用程序中的任何线程抛出一个绘图窗口并阻塞直到绘图关闭或继续工作,而showPlot() 的调用者不必知道任何其他线程在绘图方面正在做什么,或者过去创建了哪些情节并且可能仍在屏幕上。 (showPlot() 的内部当然可能有这方面的知识。)

我仍在试图了解 GUI 库通常如何在幕后工作。似乎您应该只有一个 GUI 线程和一个主窗体。除了特定于语言/库的设计模式之外,我希望能得到与语言/库无关的设计模式级别的答案。

编辑:要强调的是,这个应用程序除了在执行过程中在有趣的点抛出的情节之外没有任何 GUI。它基本上是一个控制台应用程序加上一些情节。因此,没有明确定义的“主”形式。

【问题讨论】:

    标签: user-interface language-agnostic design-patterns d


    【解决方案1】:

    GUI 框架通常有自己的事件循环,并调用应用程序代码作为对外部事件(按钮单击、计时器、重绘等)的回调。 “典型”控制台应用程序和 GUI 应用程序之间的主要区别在于,您放弃了对 GUI 框架何时调用函数的控制权。

    当应用程序代码包含一些长时间运行的进程时,通常使用线程,这些进程不能被中断成更小的块(大型计算、复制文件、控制世界……)。然后使用一个线程来保持 GUI 响应,而工作在单独的线程中完成。主要问题是保持两个线程正确同步,因为大多数 GUI 工具包无法处理来自多个线程的调用。当您只有很小的工作部件,并且不会长时间(

    我还强烈建议将 GUI 代码和应用程​​序逻辑分开。将 GUI 代码和应用程​​序代码混合在一起是一场维护噩梦。

    【讨论】:

    • 我认为你没有抓住重点。关键是这不是一个“典型的”GUI 应用程序。它主要是一个控制台科学计算应用程序,但在执行的有趣部分中碰巧抛出了一些情节。在这种情况下,除了这些图之外没有 GUI。
    【解决方案2】:

    您将能够做什么可能取决于 DFL 的工作方式。通常,在 GUI 应用程序中,有一个事件线程来处理应用程序中的所有事件——无论是重绘事件、按钮单击事件、鼠标单击事件还是其他任何事件。该线程调用已注册的事件处理程序来处理事件(通常是被单击的小部件或诸如此类的小部件)。您遇到的问题是,如果您尝试在这些事件处理程序中执行过多操作,则会锁定事件线程,因此其他事件(包括重绘事件)不会得到及时处理。一些 GUI 工具包甚至特别限制了您可以在事件处理程序中执行的操作。有些人还将某些类型的操作限制在该特定线程中(比如做任何事情——尤其是对象创建——使用实际的 GUI 代码,比如工具包必须具有的各种小部件或窗口类)。

    通常,处理这种情况的方法是让事件线程在事件处理程序中触发单独的线程并让其他线程实际处理事件,或者您在事件处理程序中设置一些状态,一个单独的,已经运行的线程会收到状态变化的警报(可能使用观察者模式),并根据该状态适当地处理事情。在这两种情况下,事件处理程序本身所做的通常都相当有限。

    GUI 的工作方式通常非常基于事件。该程序处理来自用户和系统的事件,并且在没有发出信号的情况下不会做很多事情。通常,GUI 应用程序在被事件告知之前不会执行任何操作(尽管在很多情况下,后台线程正在执行与事件分开的某种工作)。您正在尝试做的事情听起来并不是特别基于事件,所以这会使事情变得有点复杂。

    我的猜测是,每次你想抛出一个新的情节时,你都需要让你的应用程序创建一个新窗口。该窗口可能是主窗口的子窗口,因为您显然不需要它,所以它会被隐藏,并且大概 DFL 要求您拥有某种主窗口。很有可能每个想要创建窗口的线程都必须告诉主 GUI 窗口来执行此操作,但这实际上取决于 DFL。 DFL 也有可能允许任何线程创建新的 GUI 元素(例如新窗口)。

    无论如何,它几乎肯定是实际处理窗口的主事件线程。想要创建窗口并填充它的线程可能必须创建窗口(直接或间接),然后通过更新一组共享变量来更新窗口的状态,以便事件线程可以适当地重新绘制窗口.原始线程实际重绘窗口可能会做的最多的事情是在更新保存绘制窗口所需数据的共享变量的状态后向窗口发送重绘事件。它不会处理绘画本身。

    至于线程阻塞,它可能不得不忙着等待,直到事件线程接收到窗口关闭事件,并且一些共享变量被更新,或者你可以让它进入睡眠状态直到事件线程唤醒在收到窗口关闭事件后它会启动。在您不希望它阻塞的情况下,它只是不会在意等待被告知关闭窗口的事件,并且会继续前进。

    无论如何,希望这些信息足以让您朝着正确的方向前进。通常事件驱动一切,一切都挂在 GUI 上,可以这么说。但在您的情况下,您的应用程序使用的 GUI 更像是标准输出。所以,你最好先开发一些小的、相当愚蠢的 GUI 应用程序,这些应用程序是实际的、正常的、基于事件的 GUI 应用程序(比如井字游戏或其他东西),以便更好地处理如何GUI 的东西在试图让它像你一样以不那么标准的方式工作之前就可以工作了。

    【讨论】:

    • 标准输出类比是一个很好的类比——这几乎正是我希望 GUI 系统在这种情况下的理想行为方式。
    猜你喜欢
    • 1970-01-01
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    相关资源
    最近更新 更多