如何让Qt小部件看不见,而不改变其他Qt小部件的位置?

我有一个充满QPushButtons和QLabels的窗口以及各种其他有趣的QWidget,它们都使用各种QLayout对象动态地进行布局,而我想做的是偶尔使这些小部件变得不可见。也就是说,不可见的小部件仍然占据窗口布局中的正常空间,但不会被渲染:用户只需在窗口小部件的矩形/区域中看到窗口的背景颜色。

hide()和/或setVisible(false)将不会做这个伎俩,因为它们会使窗口小部件完全从布局中移除,允许其他小部件扩展以占用“新建可用”空间;一个我想避免的效果。

我想我可以使每个QWidget类型的子类覆盖paintEvent()(和mousePressEvent()和etc)成为一个no-op(如果适用),但我更喜欢一个不需要我创建的解决方案三打不同的QWidget子类。

最佳答案
我知道的唯一体面的方法是将事件过滤器附加到窗口小部件,并过滤掉重绘事件。它将工作,无论这个小部件是多么复杂 – 它可以有子窗口小部件。

以下是一个完整的独立示例。然而,它带有一些注意事项,需要进一步的开发才能完成。只有油漆事件被覆盖,因此您仍然可以与窗口小部件交互,您将看不到任何效果。

鼠标点击,鼠标进入/离开事件,焦点事件等仍然会到达窗口小部件。如果小部件依赖某些事情在重新绘制时完成,也许是由于在这些事件触发的update()),可能会有麻烦。

至少你需要一个case语句来阻止更多的事件 – 说鼠标移动和点击事件。处理焦点是一个问题:如果小部件在集中时被隐藏,并且每当重新获取焦点时,就需要将焦点移到链中的下一个小部件。

鼠标跟踪也带来一些担忧,您可能想假装该小部件丢失鼠标跟踪,如果之前跟踪。正确地模拟这将需要一些研究,我不知道我的头顶部Qt向窗口小部件提供的确切的鼠标跟踪事件协议是什么。

//main.cpp
#include <QEvent>
#include <QPaintEvent>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QGridLayout>
#include <QDialogButtonBox>
#include <QApplication>

class Hider : public QObject
{
    Q_OBJECT
public:
    Hider(QObject * parent = 0) : QObject(parent) {}
    bool eventFilter(QObject *, QEvent * ev) {
        return ev->type() == QEvent::Paint;
    }
    void hide(QWidget * w) {
        w->installEventFilter(this);
        w->update();
    }
    void unhide(QWidget * w) {
        w->removeEventFilter(this);
        w->update();
    }
    Q_SLOT void hideWidget()
    {
        QObject * s = sender();
        if (s->isWidgetType()) { hide(qobject_cast<QWidget*>(s)); }
    }
};

class Window : public QWidget
{
    Q_OBJECT
    Hider m_hider;
    QDialogButtonBox m_buttons;
    QWidget * m_widget;
    Q_SLOT void on_hide_clicked() { m_hider.hide(m_widget); }
    Q_SLOT void on_show_clicked() { m_hider.unhide(m_widget); }
public:
    Window() {
        QGridLayout * lt = new QGridLayout(this);
        lt->addWidget(new QLabel("label1"), 0, 0);
        lt->addWidget(m_widget = new QLabel("hiding label2"), 0, 1);
        lt->addWidget(new QLabel("label3"), 0, 2);
        lt->addWidget(&m_buttons, 1, 0, 1, 3);
        QWidget * b;
        b = m_buttons.addButton("&Hide", QDialogButtonBox::ActionRole);
        b->setObjectName("hide");
        b = m_buttons.addButton("&Show", QDialogButtonBox::ActionRole);
        b->setObjectName("show");
        b = m_buttons.addButton("Hide &Self", QDialogButtonBox::ActionRole);
        connect(b, SIGNAL(clicked()), &m_hider, SLOT(hideWidget()));
        QMetaObject::connectSlotsByName(this);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Window w;
    w.show();
    return a.exec();
}

#include "main.moc"

转载注明原文:如何让Qt小部件看不见,而不改变其他Qt小部件的位置? - 代码日志