要使用QImage绘制一些点,QWidget.update()太慢了,有更快的方法吗?

时间:2017-03-29 07:18:10

标签: qt qimage

我正在尝试使用QImage在窗口上绘制一个点,并尽快更新此点的位置(每次更新少于1毫秒)。我已经编写了下面的代码并运行它,但结果是它太慢了(每次更新大约50ms)。我搜索了瓶颈,发现这种缓慢的原因是调用QWidget.update()需要太长时间。所以只要使用Widget.update()我就会发现它不会更快。所以我想我需要另一种方式。有没有更快的方法来做到这一点?所有代码和结果如下。

结果:

enter image description here

qimageBehaviorForStackOverflowQuestion.pro

######################################################################
# Automatically generated by qmake (3.1) Wed Mar 29 15:18:09 2017
######################################################################

TEMPLATE = app
TARGET = qimageBehaviorForStackOverflowQuestion
INCLUDEPATH += .
QT += widgets

# Input
HEADERS += qimageBehaviorForStackOverflowQuestion.h
SOURCES += qimageBehaviorForStackOverflowQuestion.cpp

qimageBehaviorForStackOverflowQuestion.h

#include <iostream>
#include <QApplication>
#include <QWidget>
#include <QTimer>
#include <QPainter>
#include <QPushButton>
#include <QImage>
#include <QTime>

class MyWidget : public QWidget {
  Q_OBJECT
 private:
  QImage *image;
  int px, py;
  uchar d[100*100*4];
  QTimer *timer;
  QTime time;
public:
  MyWidget();
  void paintEvent(QPaintEvent * event);
public slots: 
  void doPaint();
};

qimageBehaviorForStackOverflowQuestion.cpp

#include "qimageBehaviorForStackOverflowQuestion.h"

int my_counter = 0;

MyWidget::MyWidget() : QWidget(0), px(0), py(0){
  image = new QImage(d, 100, 100, QImage::Format_ARGB32);
  for(int cnt = 0, a, r, g, b; cnt < 100*100*4;){
    a = 255; //alpha
    r = 0;   //red
    g = 0;   //green
    b = 0;   //blue

    d[cnt] = b; cnt++;
    d[cnt] = g; cnt++;
    d[cnt] = r; cnt++;
    d[cnt] = a; cnt++;
  }
  // connect QTimer.timeout to my doPaint method
  timer = new QTimer();
  connect(timer, SIGNAL(timeout()), this, SLOT(doPaint()));
  timer->start(1);
};

void MyWidget::doPaint(){
  // manipulate the positions of the points
  if(px < 100){
    int cnt = 0, b = 255, g = 255, r = 255, a = 255;
    d[4 * px + cnt] = b; cnt++;
    d[4 * px + cnt] = g; cnt++;
    d[4 * px + cnt] = r; cnt++;
    d[4 * px + cnt] = a; cnt++;
    px++;
  }
  // update the window
  update();
};

void MyWidget::paintEvent(QPaintEvent * event){
    QPainter painter(this);
    painter.drawImage(0, 0, *image);
}

int main(int argc, char *argv[]){
  QApplication app(argc, argv);
  MyWidget *widget = new MyWidget();
  widget->show();
  return app.exec();
}

2 个答案:

答案 0 :(得分:1)

经过几个小时的谷歌搜索后,我找到了更快的方法。它变得非常快(一旦20FPS现在大约500FPS)。我现在使用的是QGraphicsView FrameworkQPixmap以及QGraphicsPixmapItem。但是我不知道这是正确或有效的方式,如果它不能纠正我。如果您知道有更快的方式请告诉我。我会以任何方式向您展示代码。我希望它可以帮助那些解决同样问题的人。

qgraphicsSceneExample.h

    #include <iostream>
    #include <QApplication>
    #include <QGraphicsView>
    #include <QGraphicsScene>
    #include <QGraphicsItem>
    #include <QTimer>
    #include <QPainter>
    #include <QPushButton>
    #include <QImage>
    #include <QTime>
    #include <QStyleOptionGraphicsItem>
    #include <QWidget>
    #include <QPixmap>
    #include <QGraphicsPixmapItem>


    class MyView : public QGraphicsView {
        Q_OBJECT
    private:
        QGraphicsScene *scene;
        QImage *image;
        QPixmap *pixmap;
        QGraphicsPixmapItem *gpixmapItem;
        int px, py;
        uchar d[100*100*4];
        QTimer *timer;
        QTime time;
    public:
        MyView();
        //void paintEvent(QPaintEvent * event);
    public slots:
        void doPaint();
    };

qgraphicsSceneExample.cpp

#include "qgraphicsSceneExample.h"

int my_counter = 0;

MyView::MyView() : px(0), py(0){

    image = new QImage(d, 100, 100, QImage::Format_ARGB32);
    for(int cnt = 0, a, r, g, b; cnt < 100*100*4;){
        a = 255; //alpha
        r = 0;   //red
        g = 0;   //green
        b = 0;   //blue

        d[cnt] = b; cnt++;
        d[cnt] = g; cnt++;
        d[cnt] = r; cnt++;
        d[cnt] = a; cnt++;
    }

    // connect QTimer.timeout to my doPaint method
    timer = new QTimer();
    connect(timer, SIGNAL(timeout()), this, SLOT(doPaint()));
    scene = new QGraphicsScene(0);
    pixmap = new QPixmap(QPixmap::fromImage(*image));
    gpixmapItem = scene->addPixmap(*pixmap);
    this->setScene(scene);

    timer->start(1);
};


void MyView::doPaint(){
    // manipulate the positions of the points
    if(px < 100){
        int cnt = 0, b = 255, g = 255, r = 255, a = 255;
        d[4 * px + cnt] = b; cnt++;
        d[4 * px + cnt] = g; cnt++;
        d[4 * px + cnt] = r; cnt++;
        d[4 * px + cnt] = a; cnt++;
        px++;
    }
    pixmap = new QPixmap(QPixmap::fromImage(*image));
    gpixmapItem->setPixmap(*pixmap);
    std::cout << my_counter++ << "\n";
};

int main(int argc, char *argv[]){
    QApplication app(argc, argv);
    MyView *myView = new MyView();
    myView->show();
    return app.exec();
}

答案 1 :(得分:0)

例如,考虑将Px的增量更改为大于+1,+ 5。这会将doPaint()函数的调用减少5倍。并将加快绘图速度。因为你的问题是你要经常更新图纸100次。

P.S:你还应该停止计时器在绘图结束时停止调用doPaint()函数。因为它每1ms被调用一次。因为timeout()每1ms会发出jQuery(".together_description").each(function() { var myInput = jQuery(this).val(); jQuery(this).trigger("click"); jQuery(this).focus(); jQuery(this).val(myInput + ' courtesy of XXX'); }); 个信号。

修改 还要考虑更改非常轻的超时(每1ms&lt; =&gt; 1000 FPS更新)。