【问题标题】:how to avoid paintevent() being called when the widget was obscured and uncovered如何避免在小部件被遮挡和未覆盖时调用paintevent()
【发布时间】:2018-08-18 20:16:32
【问题描述】:

我想在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);
        }
    }
}

【问题讨论】:

    标签: c++ qt qt4 qt5


    【解决方案1】:

    您假设了一个解决方案,实际上您应该专注于问题。您的问题与何时调用 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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-06
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 2015-03-20
      相关资源
      最近更新 更多