GUI设计 - 显示没有弹出窗口的消息

时间:2014-07-03 13:52:23

标签: python qt user-interface

在没有弹出对话框的情况下,您使用哪些技术在GUI中显示消息?

对于用户来说,弹出对话框通常非常糟糕 - 它们会妨碍您,并且您通常不会对导致错误感兴趣。另一种方法是忽略错误而不做任何事情

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

因此,您希望显示信息性消息,但不要求用户必须单击烦人的弹出框。

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

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

  

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

设计正确,情况并非如此。我的许多课程都有这样的日志信号: -

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

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

另外,我有一个带有匹配日志槽的Logging类。您可以将其设为singleton,或者只使用static方法。

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

对于日志本身,Log类可以选择设置消息栏上的文本,写入文件,显示通知(OSX)或任何其他所需的方法。

虽然我的方法使用C ++,但我希望你可以在Python中做同样或类似的事情。

答案 1 :(得分:1)

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

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

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

另一种选择是"不再显示"自定义messageBox中的复选框。

答案 2 :(得分:0)

首先,消息和它的显示小部件是两个不同的东西。将它们组合在一起是一个严重的设计错误。

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

由于QObject以及qApp是全局实例指针而QCoreApplicationQObject这一事实,传递水槽非常容易。因此你可以:

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

  2. 使接收器成为全局应用程序对象的唯一子项。

  3. 见下面的例子。请注意,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 ++保证在这里。