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

Qt 要使用QImage绘制一些点,QWidget.update()太慢了,有更快的方法吗?,qt,qimage,Qt,Qimage,我试图使用QImage在窗口上绘制一个点,并尽可能快地更新该点的位置(每次更新不超过1ms)。我已经编写了下面的代码并运行了它,但是结果是它太慢了(每次更新大约50毫秒)。我搜索了瓶颈,发现导致速度缓慢的原因是调用QWidget.update()花费的时间太长。所以我想只要使用Widget.update()它不会更快。所以我想我需要另一种方式。有没有更快的办法?所有代码和结果如下所示 结果: qimageBehaviorForStackOverflowQuestion.pro ########

我试图使用
QImage
在窗口上绘制一个点,并尽可能快地更新该点的位置(每次更新不超过1ms)。我已经编写了下面的代码并运行了它,但是结果是它太慢了(每次更新大约50毫秒)。我搜索了瓶颈,发现导致速度缓慢的原因是调用
QWidget.update()
花费的时间太长。所以我想只要使用
Widget.update()
它不会更快。所以我想我需要另一种方式。有没有更快的办法?所有代码和结果如下所示

结果:

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();
};
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类MyWidget:publicqwidget{
Q_对象
私人:
QImage*图像;
int-px,py;
uchar d[100*100*4];
QTimer*定时器;
时间;
公众:
MyWidget();
无效油漆事件(QPaintEvent*事件);
公众时段:
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();
}
#包括“qimageBehaviorForStackOverflowQuestion.h”
int my_计数器=0;
MyWidget::MyWidget():QWidget(0)、px(0)、py(0){
image=新的QImage(d,100100,QImage::Format_ARGB32);
对于(int cnt=0,a,r,g,b;cnt<100*100*4;){
a=255;//α
r=0;//红色
g=0;//绿色
b=0;//蓝色
d[cnt]=b;cnt++;
d[cnt]=g;cnt++;
d[cnt]=r;cnt++;
d[cnt]=a;cnt++;
}
//将QTimer.timeout连接到我的doPaint方法
计时器=新的QTimer();
连接(计时器、信号(超时())、此、插槽(doPaint());
定时器->启动(1);
};
void MyWidget::doPaint(){
//操纵点的位置
如果(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++;
}
//更新窗口
更新();
};
void MyWidget::paintEvent(QPaintEvent*event){
油漆工(本);
painter.drawImage(0,0,*图像);
}
int main(int argc,char*argv[]){
QApplication应用程序(argc、argv);
MyWidget*widget=newmywidget();
widget->show();
返回app.exec();
}

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

附言:绘图完成后,还应停止计时器以停止调用doPaint()函数。因为它每1ms调用一次。因为
timer.start(1)
将每隔1ms发出
timeout()
信号

编辑:
还要考虑改变非常超时的超时(每1ms更新1000 fps)。p> 在谷歌搜索了几个小时后,我找到了更快的方法。它变得非常快(曾经的20FPS现在大约是500FPS)。我现在使用的是
QGraphicsView框架
QPixmap
QGraphicsPixmapItem
。然而,我不知道这是正确的或有效的方法,如果它不是请纠正我。如果你知道还有更快的方法,请告诉我。不管怎样,我给你看代码。我希望它能帮助解决同样问题的人

qgraphicsceneexample.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();
    };
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类MyView:公共QGraphicsView{
Q_对象
私人:
qgraphicscene*场景;
QImage*图像;
QPixmap*pixmap;
QGraphicsPixmapItem*gpixmapItem;
int-px,py;
uchar d[100*100*4];
QTimer*定时器;
时间;
公众:
MyView();
//无效油漆事件(QPaintEvent*事件);
公众时段:
void doPaint();
};
qgraphicsceneexample.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();
}
#包括“qgraphicsceneexample.h”
int my_计数器=0;
MyView::MyView():px(0),py(0){
image=新的QImage(d,100100,QImage::Format_ARGB32);
对于(int cnt=0,a,r,g,b;cnt<100*100*4;){
a=255;//α
r=0;//红色
g=0;//绿色
b=0;//蓝色
d[cnt]=b;cnt++;
d[cnt]=g;cnt++;
d[cnt]=r;cnt++;
d[cnt]=a;cnt++;
}
//将QTimer.timeout连接到我的doPaint方法
计时器=新的QTimer();
连接(计时器、信号(超时())、此、插槽(doPaint());
场景=新的Qgraphicscene(0);
pixmap=新的QPixmap(QPixmap::fromImage(*image));
gpixmapItem=场景->添加pixmap(*pixmap);
这个场景;
定时器->启动(1);
};
void MyView::doPaint(){
//操纵点的位置
如果(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=新的QPixmap(QPixmap::fromImage(*image));
gpixmapItem->setPixmap(*pixmap);

std::你没试过Qgraphicscene吗?@NI1light:没试过。Qgraphicscene提示了吗?这对我很有帮助。好吧,这是真的,但我想知道提高FPS的方法。目前大约20 FPS是我的限制…但我认为这不是真正的限制。这是一个限制。因为你的眼睛至少需要13毫秒才能看到图像。是的。但是你可以测试和测试看看什么最适合你的应用。update()调用paintEvent,我不知道绘制小部件需要多少时间。