在父窗口小部件内移动子窗口小部件而无需重新绘制

时间:2019-01-26 17:34:51

标签: c++ qt

我正在尝试使子窗口小部件与父窗口小部件的右下角对齐。子窗口小部件的重新绘制成本很高,因此我想避免这样做。因为我只移动具有静态内容的子窗口小部件,所以从理论上讲不需要重新绘制。但是我不知道如何实现这一目标。我对resizeEvent()做出反应,在其中我将孩子的位置更新到了角落。我已经设置了小部件属性(尝试错误方法),以最大程度地减少绘画事件。但是,在调整父级的大小时-以及放大和缩小时,仍然需要一些子级重绘事件。当缓慢地调整大小并且仅在一个方向(x或y)上调整时,似乎仅粉刷了1像素宽带。当更快地同时在两个方向上调整大小时,子窗口小部件将全部重新绘制。是否可以调整代码以避免完全重绘子窗口小部件?我想避免自己为这种情况编写手动双缓冲算法,我希望Qt能够以某种方式为我解决此问题。是吗?

#include <QApplication>
#include <QDebug>
#include <QPainter>
#include <QPaintEvent>
#include <QWidget>

class ChildWidget : public QWidget
{
public:
    ChildWidget(QWidget *parent) : QWidget(parent)
    {
        setAttribute(Qt::WA_StaticContents);
        setAttribute(Qt::WA_OpaquePaintEvent);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        qDebug() << "paintEvent" << event->rect();
        QPainter painter(this);
        painter.fillRect(event->rect(), QBrush(QColor("red")));
    }
};

class ParentWidget : public QWidget
{
public:
    ParentWidget()
    {
        m_childWidget = new ChildWidget(this);
        m_childWidget->resize(100, 100);
        setAttribute(Qt::WA_StaticContents);
        resize(200, 200);
    }

protected:
    void resizeEvent(QResizeEvent *event) override
    {
        QWidget::resizeEvent(event);
        m_childWidget->move(width() - 100, height() - 100);
    }

private:
    ChildWidget *m_childWidget;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ParentWidget w;
    w.show();

    return a.exec();
}

注意:在我的最终用例中,该父窗口小部件旨在由几个不重叠的子窗口小部件完全覆盖,并且这些子窗口小部件中的每个子窗口将是不透明的,并将负责绘制整个区域。即无需对Alpha通道进行特殊处理。这对于设置窗口小部件属性可能是重要的信息。

注意:我尝试了一种技巧,不是立即移动子项,而是使用QTimer::singleShot(0, [this]{m_childWidget->move(width() - 100, height() - 100);});来推迟子项,这可以防止在父级窗口小部件调整大小期间重新绘制,但仅在父级大小增大的情况下才可以。当它收缩时,它与以前相同。

0 个答案:

没有答案