【问题标题】:GUI design - display messages without popupsGUI 设计 - 显示没有弹出窗口的消息
【发布时间】:2014-08-24 16:31:21
【问题描述】:

您使用什么技术在没有弹出对话框的 GUI 中显示消息?

弹出式对话框对用户来说通常是非常可怕的——它们会妨碍您,而且您通常不会对自己造成的错误感兴趣。另一种方法是忽略错误,什么也不做

但是,可能偶尔会有用户想知道他们何时导致错误...

因此,您希望显示信息丰富的消息,但无需用户点击烦人的弹出框。

一种选择可能是使用主窗口的状态栏,但是为了让任何小部件使用它,您需要传递对这个该死的状态栏的引用(我在这里考虑的是 python/qt)...它很快就会变得混乱并消除小部件的“可重复性”(假设您创建了另一个应用程序,没有状态栏,并且您想在其中重用小部件......)......

有什么想法吗?

【问题讨论】:

    标签: python qt user-interface


    【解决方案1】:

    一个选项可能是使用主窗口的状态栏,但为了让任何小部件使用它,您需要传递对这个该死的状态栏的引用

    设计正确,事实并非如此。我的许多课程都有这样的 Log 信号:-

    void Log(const QString& message, enum LogPriority priority);
    

    优先级是一个枚举,用于定义信息的级别,无论是调试消息、警告、错误、严重错误等。

    此外,我还有一个带有匹配 Log 槽的 Logging 类。您可以将其设为singleton,或者简单地使用static 方法。

    类将它们的信号直接连接到日志记录类,或者连接到父级的信号。这确保了类在发送日志消息时不关心发生了什么。您还可以通过删除其连接来禁用类的日志记录。

    至于日志记录本身,Log 类可以选择设置消息栏上的文本、写入文件、显示通知 (OSX) 或您想要的任何其他方法。

    虽然我的方法使用 C++,但我希望您可以在 Python 中执行相同或类似的操作。

    【讨论】:

    • 我们的回答基本相同.. :)
    【解决方案2】:

    我在我的 QT/C++ 应用程序中所做的是主窗口中名为“消息板”的 QDockedWidget,其中包含警告/错误/信息消息列表。无论如何,它都可以被用户删除。为了不传递对这个 QDockedWidget 的所有小部件的引用,我使用(也用于许多其他目的......)一个 SharedData 类,它具有全局可见性,构建为应用程序的单例。因此,每个小部件都可以作为对其的全局引用,并且可以设置错误或警告或其他内容:

    Gshared->setError("oops!", ErrorType::Critical);
    

    在这里的 setError 函数中,我发出一个信号,该信号被 QDockedWidget 中的插槽(用于显示错误)、记录器管理器(在日志文件中写入有关错误的更多详细信息)等...

    另一个选项是自定义消息框中的“不再显示”复选框。

    【讨论】:

      【解决方案3】:

      首先,消息和它的显示小部件是两个独立的东西。将它们拼凑在一起是一个严重的设计错误。

      一个典型的解决方案会有某种记录器/消息接收器,它是一个语义单例,但不一定使用单例模式实现。接收器可以是QObject,以便您可以轻松地将消息源连接到接收器。然后可以将接收器附加到一个或多个显示小部件。

      由于QObject 以及qApp 是全局实例指针,QCoreApplicationQObject,传递接收器非常容易。因此,您可以:

      1. 通过动态属性系统传递指针,或

      2. 将接收器设为全局应用程序对象的唯一子代。

      请参见下面的示例。注意Widget只需要知道MessageSink类的声明。它不需要显式传递任何实例。通常的单例模式也不是按原样使用的。

      class MessageSink : public QObject {
        Q_OBJECT
      public:
        MessageSink(QObject * parent = 0) : QObject(parent) {}
        Q_SIGNAL void message(const QString &);
        static MessageSink * instance() { return qApp->findChild<MessageSink*>(); }
      }    
      
      class Widget : public QWidget {
        QVBoxLayout m_layout;
        QLabel m_l1, m_l2;
      public:
        Widget(QWidget * parent = 0) : QWidget(parent), m_layout(this) {
          m_layout.addWidget(&m_l1);
          m_layout.addWidget(&m_l2);
          m_l1.connect(MessageSink::instance(), SIGNAL(message(QString)), SLOT(setText(QString)));
          m_l2.connect(MessageSink::instance(), SIGNAL(message(QString)), SLOT(setText(QString)));
        }
      }
      
      int main(int argc, char ** argv) {
        QApplication app(argc, argv);
        MessageSink sink(&app);
        Widget w;
        w.show();
        emit sink.message("Hello!");
        return app.exec();
      }
      

      注意:本地QObject 具有父级不是错误。你只需要确保it gets destructed before the parent。 C++ 在这里保证。

      【讨论】:

        猜你喜欢
        • 2015-11-25
        • 2013-07-14
        • 2015-05-14
        • 2018-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多