qt5如果我只想重新绘制一个小部件,如何防止重新绘制整个窗口



最小代码示例:

class Boo : public QPushButton{
public:
Boo(QWidget* w) : QPushButton(w){}
virtual void paintEvent(QPaintEvent* ev){
qDebug()<<__FUNCTION__<<this->objectName();
}
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
virtual void paintEvent(QPaintEvent* ev){
qDebug()<<__FUNCTION__;
}
private:
QTimer t;
Ui::MainWindow *ui;
Boo *b1, *b2;
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
b1 = new Boo(this);
b1->setObjectName("O1");
b2 = new Boo(this);
b2->setObjectName("O2");
connect(&t, &QTimer::timeout, this, [this](){
b2->repaint();
});
t.start();
t.setInterval(10);
}

无限输出:MainWindow::paintEvent Boo::paint-Event"O1";Boo::paintEvent";O2";

但我只为按钮b2调用重新绘制。使用";QWidget::重新绘制(int x,int y,int w,int h("或:QWidget::update((";还调用主窗口的重新绘制。

Qt5.12/5.15和windows11上存在问题,但看起来像是一般的qt错误。

这个问题导致在我们更复杂的GUI应用程序中GPU消耗很高。

好的。我自己找到了原因,添加后:

...
b1->setGeometry(15,15, 12, 12);
...
b2->setGeometry(35,35, 14, 14);
...
virtual void paintEvent(QPaintEvent* ev){
qDebug()<<__FUNCTION__<<ev->rect();
}

ouput说,实际的重新喷漆只针对按钮区域:

主窗口::paintEvent QRect(35,35 14x14(Boo::paintEvent";O2";QRect(0,0 14x14(

重要的是:为按钮创建setGeometry,而不仅仅是添加为子项。在其他情况下(当然,仅适用于玩具示例(,用未设置的几何体重新绘制按钮将导致用未设置几何体重新粉刷每个按钮。

Qt默认情况下也会重新绘制所有父级,以允许小部件部分透明。如果Qt在更新时没有重新绘制父对象,则前一个paintEvent的一些像素可能仍然可见。

当不需要透明背景时,Qt提供了两种方法来优化这种行为:

  • 设置autoFillBackground。如果背景颜色不透明,则首选此选项
  • 设置Qt::WA_OpaquePaintEvent表示将绘制整个小部件(使用不透明颜色(

更多信息

  • Qt文档:QWidget:透明和双缓冲

最新更新