我想在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<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);
}
}
}
答案 0 :(得分:5)
您预先假定了一个解决方案,实际上您应该专注于该问题。您的问题不在于何时调用paintEvent
。 Qt的语义是这样的,paintEvent
可以在主线程中的任何时间调用。你必须应付它。
相反,您需要做的是将随机颜色存储在容器中,以便在绘制时重复使用它们。在下面的示例中,颜色是按需生成的,并存储在由行和列索引的动态增长列表中。这样,当您调整窗口小部件的大小时,现有项目的颜色不必更改。然后,您可以通过简单地清除容器并强制更新来随时重新生成颜色。
以下示例允许您选择是否在调整大小时保留颜色。
代码使用Qt 5和C ++ 11。请注意,现代代码中不鼓励使用rand() % range
- 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"