如何避免paintevent()被调用时窗口部件被遮挡和揭露 [英] how to avoid paintevent() being called when the widget was obscured and uncovered

查看:400
本文介绍了如何避免paintevent()被调用时窗口部件被遮挡和揭露的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在qwidget中绘制一些带有随机颜色的菱形。该窗口部件应该重新绘制只有当窗口的大小调整。问题是,当窗口小部件被遮挡,现在已被揭露,它是重画。在这种情况下,我如何避免调用paintevent()?先感谢。

  void Dialog :: paintEvent(QPaintEvent * e) 
{
QPainter painter(this);
QRect background(0,0,this-> geometry()。width(),this-> geometry()。height());

painter.setBrush(QBrush(Qt :: white));
painter.setPen(Qt :: NoPen);
// QBrush bbrush(Qt :: black,Qt :: SolidPattern);
painter.drawRect(background);

int width = this-> geometry()。width();
int height = this-> geometry()。height();
int rec_size = 64;
int rows = floor((double)height /(double)rec_size);
int cols = floor((double)width /(double)rec_size);

QPointF points [4];

for(int i = 0; i {
for(int j = 0; j< floor(cols); j ++)
{
painter.setBrush(QBrush(colors [rand()%color_size]));

points [0] = QPointF(rec_size *(j),rec_size *(i + 0.5));
points [1] = QPointF(rec_size *(j + 0.5),rec_size *(i));
points [2] = QPointF(rec_size *(j + 1),rec_size *(i + 0.5));
points [3] = QPointF(rec_size *(j + 0.5),rec_size *(i + 1));

painter.drawPolygon(points; 4);
}
}
}


解决方案>

你假设一个解决方案,其实你应该关注这个问题。你的问题不是当调用 paintEvent 时。 Qt的语义是这样的: paintEvent 可以在主线程中的任何时间调用。您必须处理它。



您需要做的是将随机颜色存储在容器中,以便在绘画时重新使用它们。在下面的示例中,颜色是根据需要生成的,并且存储在按行和列索引的动态增长列表中。这样,当您调整窗口小部件的大小时,现有项目的颜色不必更改。



下面的示例允许您选择是否在调整大小时保留颜色。

/ p>

代码使用Qt 5和C ++ 11。请注意,在现代代码中不建议使用 rand()%range - 它不保留分布的均匀性



  #include< QApplication> 
#include< QWidget>
#include< QPushButton>
#include< QCheckBox>
#include< QGridLayout>
#include< QPainter>
#include< random>

std :: default_random_engine rng;

class Dialog:public QWidget {
Q_OBJECT
Q_PROPERTY(bool recolorOnResize READ recolorOnResize WRITE setRecolorOnResize)
QList< QColor> m_palette;
QList< QList< QColor>> m_chosenColors;
bool m_recolorOnResize;
void paintEvent(QPaintEvent *){
QPainter p(this);
p.fillRect(rect(),Qt :: white);
p.setRenderHint(QPainter :: Antialiasing);

int rec_size = 64;
int rows = height()/ rec_size;
int cols = width()/ rec_size;
std :: uniform_int_distribution< int> dist(0,m_palette.size() - 1);
while(m_chosenColors.size()< rows)m_chosenColors<< QList< QColor>();
for(QList< QColor>& colors:m_chosenColors)
while(colors.size()< cols)
colors< m_palette.at(dist(rng));

QPointF points [4];
for(int i = 0; i< rows; i ++){
for(int j = 0; j points [0] = QPointF(rec_size * j),rec_size *(i + 0.5));
points [1] = QPointF(rec_size *(j + 0.5),rec_size *(i));
points [2] = QPointF(rec_size *(j + 1),rec_size *(i + 0.5));
points [3] = QPointF(rec_size *(j + 0.5),rec_size *(i + 1));
p.setBrush(m_chosenColors [i] [j]);
p.drawPolygon(points,4);
}
}
}
void resizeEvent(QResizeEvent *){
if(m_recolorOnResize)m_chosenColors.clear();
}
public:
Dialog(QWidget * parent = 0):QWidget(parent),m_recolorOnResize(false){
m_palette< #E2C42D< #E5D796< #BEDA2C< #D1DD91< #E2992D< #E5C596;
setAttribute(Qt :: WA_OpaquePaintEvent);
}
Q_SLOT void randomize(){
m_chosenColors.clear();
update();
}
bool recolorOnResize()const {return m_recolorOnResize; }
void setRecolorOnResize(bool recolor){
m_recolorOnResize = recolor;
setAttribute(Qt:WA_StaticContents,!m_recolorOnResize);
}
};

int main(int argc,char * argv [])
{
QApplication a(argc,argv);
QWidget w;
QGridLayout l(& w);
Dialog d;
QCheckBox recolor(Recolor on Resize);
QPushButton update(Repaint),randomize(Randomize); $ b $ d d.setMinimumSize(256,128);
l.addWidget(& d,0,0,1,2);
l.addWidget(& recolor,1,0,1,2);
l.addWidget(& update,2,0);
l.addWidget(& randomize,2,1);
recolor.setChecked(d.recolorOnResize());
QObject :: connect(& recolor,& QAbstractButton :: toggled,[& d](bool checked){
d.setRecolorOnResize(checked);}
);
QObject :: connect(& update,& QAbstractButton :: clicked& d,static_cast< void(QWidget :: *)()>(& QWidget :: update));
QObject :: connect(& randomize,& QAbstractButton :: clicked,& d,& Dialog :: randomize);
w.show();
return a.exec();
}

#includemain.moc


i want to draw some rhombuses with random colors in a qwidget. The widget should be repainted only when the window is resized .The problem is that when the widget was obscured and has now been uncovered , it is repainted. How can i avoid calling paintevent() in this case?Thanks in advance.

void Dialog::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    QRect background(0,0,this->geometry().width(),this->geometry().height());

    painter.setBrush( QBrush( Qt::white ) );
    painter.setPen( Qt::NoPen );
    // QBrush bbrush(Qt::black,Qt::SolidPattern);
    painter.drawRect(background);

    int width = this->geometry().width();
    int height = this->geometry().height();
    int rec_size=64;
    int rows=floor((double)height/(double)rec_size);
    int cols=floor((double)width/(double)rec_size);

    QPointF points[4];

    for (int i=0;i<floor(rows);i++)
    {
        for (int j=0;j<floor(cols);j++)
        {
            painter.setBrush( QBrush( colors[rand() % color_size] ) );

            points[0] = QPointF(rec_size*(j),rec_size*(i+0.5));
            points[1] = QPointF(rec_size*(j+0.5),rec_size*(i));
            points[2] = QPointF(rec_size*(j+1),rec_size*(i+0.5));
            points[3] = QPointF(rec_size*(j+0.5),rec_size*(i+1));

            painter.drawPolygon(points, 4);
        }
    }
}

解决方案

You are presupposing a solution, where in fact you should be focusing on the problem instead. Your problem isn't about when paintEvent is called. Qt's semantics are such that the paintEvent can be called at any time in the main thread. You must cope with it.

What you need to do, instead, is store the randomized colors in a container, to re-use them when painting. In the example below, the colors are generated on demand, and are stored in a dynamically growing list indexed by row and column. This way when you resize the widget, the colors of the existing items don't have to change. You can then regenerate the colors at any time by simply clearing the container and forcing an update.

The example below allows you to select whether to preserve the colors during resizing.

The code uses Qt 5 and C++11. Note that the use of rand() % range is discouraged in modern code - it doesn't preserve the uniformity of the distribution.

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QCheckBox>
#include <QGridLayout>
#include <QPainter>
#include <random>

std::default_random_engine rng;

class Dialog : public QWidget {
   Q_OBJECT
   Q_PROPERTY(bool recolorOnResize READ recolorOnResize WRITE setRecolorOnResize)
   QList<QColor> m_palette;
   QList<QList<QColor>> m_chosenColors;
   bool m_recolorOnResize;
   void paintEvent(QPaintEvent *) {
      QPainter p(this);
      p.fillRect(rect(), Qt::white);
      p.setRenderHint(QPainter::Antialiasing);

      int rec_size=64;
      int rows=height()/rec_size;
      int cols=width()/rec_size;
      std::uniform_int_distribution<int> dist(0, m_palette.size()-1);
      while (m_chosenColors.size() < rows) m_chosenColors << QList<QColor>();
      for (QList<QColor> & colors : m_chosenColors)
         while (colors.size() < cols)
            colors << m_palette.at(dist(rng));

      QPointF points[4];
      for (int i=0; i<rows; i++) {
         for (int j=0; j<cols; j++) {
            points[0] = QPointF(rec_size*(j),rec_size*(i+0.5));
            points[1] = QPointF(rec_size*(j+0.5),rec_size*(i));
            points[2] = QPointF(rec_size*(j+1),rec_size*(i+0.5));
            points[3] = QPointF(rec_size*(j+0.5),rec_size*(i+1));
            p.setBrush(m_chosenColors[i][j]);
            p.drawPolygon(points, 4);
         }
      }
   }
   void resizeEvent(QResizeEvent *) {
      if (m_recolorOnResize) m_chosenColors.clear();
   }
public:
   Dialog(QWidget * parent = 0) : QWidget(parent), m_recolorOnResize(false) {
      m_palette << "#E2C42D" << "#E5D796" << "#BEDA2C" << "#D1DD91" << "#E2992D" << "#E5C596";
      setAttribute(Qt::WA_OpaquePaintEvent);
   }
   Q_SLOT void randomize() {
      m_chosenColors.clear();
      update();
   }
   bool recolorOnResize() const { return m_recolorOnResize; }
   void setRecolorOnResize(bool recolor) {
      m_recolorOnResize = recolor;
      setAttribute(Qt::WA_StaticContents, !m_recolorOnResize);
   }
};

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QWidget w;
   QGridLayout l(&w);
   Dialog d;
   QCheckBox recolor("Recolor on Resize");
   QPushButton update("Repaint"), randomize("Randomize");
   d.setMinimumSize(256, 128);
   l.addWidget(&d, 0, 0, 1, 2);
   l.addWidget(&recolor, 1, 0, 1, 2);
   l.addWidget(&update, 2, 0);
   l.addWidget(&randomize, 2, 1);
   recolor.setChecked(d.recolorOnResize());
   QObject::connect(&recolor, &QAbstractButton::toggled, [&d](bool checked){
      d.setRecolorOnResize(checked);}
   );
   QObject::connect(&update, &QAbstractButton::clicked, &d, static_cast<void(QWidget::*)()>(&QWidget::update));
   QObject::connect(&randomize, &QAbstractButton::clicked, &d, &Dialog::randomize);
   w.show();
   return a.exec();
}

#include "main.moc"

这篇关于如何避免paintevent()被调用时窗口部件被遮挡和揭露的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆