Qt 加载消息应保持在父小部件的顶部并居中

Posted

技术标签:

【中文标题】Qt 加载消息应保持在父小部件的顶部并居中【英文标题】:Qt Loading message should stay on top of and centered to parent widget 【发布时间】:2013-08-22 13:28:09 【问题描述】:

如何创建一个 QWidget(QDialog?),它停留在父 Widgt 之上,而不是像 Qt::WindowsStaysOnTopHint 这样的其他应用程序?我想显示一些“正在加载”的消息。

编辑:澄清

移动主窗口时,消息应保持在小部件的中心位置。 我是否需要连接主窗口中的移动信号才能手动将小部件保持在正确的位置?

我不想阻止整个应用程序本身(没有 dialog.exec()),我只想说用户应该等待并阻止用户输入(可能不是所有小部件,而是父小部件)

【问题讨论】:

所以你希望其他窗口(你的程序)不接受输入? 你试过QProgressDialog吗? @saeed 是的,但我不想阻止整个应用程序本身(没有 exec()),只是想说用户应该等待并阻止用户输入(也许不是所有小部件,但父小部件)。 【参考方案1】:

如果您仔细阅读QDialog::setModal() 的文档,那么您应该会找到合适的解决方案。 只需使用 QDialog 并将 paret 设置为您的窗口并将其 windowModality 设置为 Qt::WindowModal。

文档说:

Qt::WindowModal - 窗口对单个窗口层次结构是模态的,并且 阻止对其父窗口、所有祖父窗口和所有 其父窗口和祖父窗口的兄弟姐妹。

【讨论】:

setmodal() 将阻止整个 ui 访问,而不仅仅是父项 我写过关于阅读 QDialog::setModal 的文档并捕获不使用它的相关内容!解决方法很简单:setParent, setWindowModality(Qt::WindowModal), show()。【参考方案2】:

这是我的解决方案:

我不使用 setModal 之类的东西。只需显示()和隐藏()对话框,它应该保持在它的父级之上。我添加了推送和弹出(如堆栈),因为不同的线程可能对显示/隐藏对话框感兴趣......所以应该保证只有最后一次调用隐藏对话框。欢迎其他解决方案...这只是快速而肮脏的。

class WaitDialog : public QDialog

    Q_OBJECT

    public:
        WaitDialog(const QString& message, QWidget *parent = 0);

public slots:
    void show();
    void hide();
    void push();
    void pop();

signals:
        void visibilityChanged(bool enable);

private:
    int stack;
        QLabel* msgLabel;
;

WaitDialog::WaitDialog(const QString &message, QWidget *parent)
: QDialog(parent, Qt::FramelessWindowHint),
      msgLabel(new QLabel(message, this)),
      stack(0)

    QVBoxLayout* mainLayout = new QVBoxLayout;
    mainLayout->setContentsMargins(30, 30, 30, 30);
    mainLayout->addWidget(msgLabel);
    setLayout(mainLayout);


void WaitDialog::show()

    QDialog::show();

        emit visibilityChanged(true);


void WaitDialog::hide()

    QDialog::hide();
    emit visibilityChanged(false);


void WaitDialog::push()

    stack++;
    show();

    emit visibilityChanged(true);


void WaitDialog::pop()

    if (stack > 0)
        --stack;
    if (stack == 0)
    
        hide();
    

所以我所做的只是

connect(someObject, SIGNAL(someProcessingFinished()), waitDialog, SLOT(pop()));

在开始处理时自动隐藏对话框并手动调用 waitDialog->push()(或将其与 someProcessingStarted() 方法连接)。

对话框本身就是这样实例化的:

WaitDialog* waitDialog = new WaitDialog(tr("正在加载数据...请稍候。"), this);

并在第二个参数中获取其父级(在示例中为 this)。

对我来说,让主窗口弹出一条消息,只要停止 ui 交互,但保持应用程序运行而不是等待对话框返回。未使用模态标志等。我只是将感兴趣的小部件连接到 WaitDialog 发出的 visibilityChanged() 信号。

connect(waitDialog, SIGNAL(visibilityChanged(bool)), someControl, SLOT(doSomething(bool)));

...例如,以下代码会在 WaitDialog 更改可见性时禁用/启用控件...

void SomeControl::doSomething(bool enabled)

    setEnabled(!enabled);

Look my question and answer here to get know how to keep it centered.

【讨论】:

以上是关于Qt 加载消息应保持在父小部件的顶部并居中的主要内容,如果未能解决你的问题,请参考以下文章

如何在父小部件的右侧绘画?

如何布局 GridView.count 以便小部件从 Flutter 中的父小部件顶部开始构建?

将自定义 QEvent 传播到 Qt/PyQt 中的父小部件

Flutter - 无法从父小部件更改子状态

Qt:: 如何消除 qmainwindow 中小部件和工具栏之间的间隙

试图在线程中保持 qt 小部件的焦点