QGraphicsView闪烁

时间:2012-06-17 11:06:21

标签: qt user-interface qgraphicsview double-buffering

我想为我女朋友的学士论文写一个改变失明计划。它显示一个图片的X毫秒,显示一个短的“闪烁图像”(在这种情况下只是灰色),然后显示与第一个略有不同的图像。然后是一个闪烁的图像。

然后,每个人都从头开始。它工作得很好,只有图形工件。画布/ QGraphicsView刷新它的速度不够快,所以它们在刷新过程中是“线条”。

显示图像的时间:70 ms,闪烁时间:30 ms。所以它的100 ms =每秒10 FPS。虽然这可以在不使用gpu的情况下实现。但它看起来不是。

我可以使用双缓冲或其他东西来避免GPU的东西吗?或者我需要使用QGL吗? 它大约1兆字节图像。

我加载一次然后只是显示它们。也许我在现场做错事。

我会附上我的源代码,也许你有一些想法。

亲切的问候:)

#ifndef PICTURES_H
#define PICTURES_H

#include <QMainWindow>
#include <QImage>
#include <QPixmap>
#include <QGraphicsPixmapItem>
#include <iostream>
#include <QDir>
#include <QGraphicsScene>
#include <QDebug>
#include <QTimer>


namespace Ui {
class pictures;
}

class pictures : public QMainWindow
{
    Q_OBJECT

public:
    explicit pictures(QWidget *parent = 0);
    ~pictures();

    void loadPics();
    void showPics();

public slots:
    void stopClicked();
    void clearPictures();
    void timePassed();
    void changeImage();
    void changeImageGrey();

private:
    int counter;
    int image_counter;
    int stop_time;
    Ui::pictures *ui;
    QVector<int> times;
    QTimer* timer;
    QTimer* timerImageChange;
    QTimer* timerGrey;

    int imageChangeTime;
    int greyTime;

    QVector<QGraphicsPixmapItem*> images;
    QGraphicsScene* scene;
    QGraphicsScene* scene_grey;
    QGraphicsPixmapItem* item1;
};

#endif // PICTURES_H


#include "pictures.h"
#include "ui_pictures.h"

pictures::pictures(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::pictures), times()
{
    counter = 1;
    stop_time = 0;
    image_counter = 0;
    timer = new QTimer(this);
    timerGrey = new QTimer(this);
    timerImageChange = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timePassed()));
    connect(timerImageChange, SIGNAL(timeout()), this, SLOT(changeImageGrey()));
    connect(timerGrey, SIGNAL(timeout()), this, SLOT(changeImage()));

    greyTime = 200;
    imageChangeTime = 500;


    qDebug() << "Hello im here in pictures";

    ui->setupUi(this);
    this->loadPics();
    connect(ui->pushButtonStop, SIGNAL(clicked()), this, SLOT(stopClicked()));
    connect(ui->pushButtonNext, SIGNAL(clicked()), this, SLOT(clearPictures()));

    timer->start(10);
    timerImageChange->start(imageChangeTime);
}

pictures::~pictures()
{
    delete ui;
}

void pictures::loadPics()
{
    qDebug() << QDir::toNativeSeparators((QDir::current().absolutePath() + QDir::separator () + "debug" + QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"1.jpg"));
    //QImage imageOne(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" + QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"1.jpg"));
    //QImage imageTwo(QString("./pics/")+counter+"/2.png");
    //QImage imageThree(QString("./pics/")+counter+"/3.jpg");
    //QImage imageFour(QString("./pics/")+counter+"/2.png");

    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"1.jpg")));
    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"2.jpg")));
    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"3.jpg")));
    images.append(new QGraphicsPixmapItem(QDir::toNativeSeparators(QDir::current().absolutePath() + QDir::separator () + "debug" +  QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+"4.jpg")));


    //QGraphicsPixmapItem* item1( QPixmap::fromImage(imageOne));
    item1 = images[image_counter];
    //QGraphicsPixmapItem item2( QPixmap::fromImage(imageTwo));
    //QGraphicsPixmapItem item3( QPixmap::fromImage(imageThree));
    //QGraphicsPixmapItem item4( QPixmap::fromImage(imageFour));
    scene = new QGraphicsScene;
    scene_grey = new QGraphicsScene;

    int maximum = item1->boundingRect().width() > item1->boundingRect().height() ? item1->boundingRect().width() : item1->boundingRect().height();
    int dimension_width  = ui->graphicsView->rect().width();
    int dimension_height = ui->graphicsView->rect().height();

    //int biggest_canvas_dimension = (((float)item1->boundingRect().width())/dimension_width) > (((float)item1->boundingRect().height())/dimension_height) ? dimension_width : dimension_height;
    int biggest_canvas_dimension = dimension_width > dimension_height ? dimension_width : dimension_height;

    if(maximum > ui->graphicsView->rect().width() || maximum > ui->graphicsView->rect().height())
    {
        dimension_width = (int) (item1->boundingRect().width() * ((float)(biggest_canvas_dimension )/maximum));
        dimension_height = (int) (item1->boundingRect().height() * ((float)(biggest_canvas_dimension)/maximum));
        item1->setPixmap(item1->pixmap().scaled(dimension_width,dimension_height));

        qDebug() << "Width: " << dimension_width << " Height " << dimension_height << " Pic High" << item1->boundingRect().height();
    }

    //item1->setPixmap(item1->pixmap().scaled(QSize(ui->graphicsView->rect().width(), ui->graphicsView->rect().height())));
    scene->setSceneRect(ui->graphicsView->rect());
    scene->addItem(item1);

    scene_grey->setSceneRect(ui->graphicsView->rect());
    scene_grey->addItem(images[1]);


    ui->graphicsView->setScene(scene);
    ui->graphicsView->adjustSize();

    //ui->graphicsView->show();


}

void pictures::timePassed()
{
    stop_time += 10;
}

void pictures::stopClicked()
{
    timerImageChange->stop();
    timerGrey->stop();
    times.append(stop_time);
    ui->pushButtonStop->setEnabled(false);
    ui->pushButtonNext->setEnabled(true);
    counter++;
    qDebug() << "Time: " << stop_time;

    stop_time = 0;
    timer->stop();
}

void pictures::clearPictures()
{
    scene->deleteLater();
    images.clear();
    loadPics();
    ui->pushButtonStop->setEnabled(true);
    ui->pushButtonNext->setEnabled(false);
    timer->start(10);
    timerImageChange->start(imageChangeTime);
}

void pictures::changeImageGrey()
{
    timerGrey->start(greyTime);
    timerImageChange->stop();
    image_counter = (image_counter+1)%4;

    //scene_grey->removeItem(scene_grey->items().at(0));
    //scene_grey->addItem(images[image_counter]);

    scene->removeItem(scene->items().at(0));
    scene->addItem(images[image_counter]);



    /*int maximum = item1->boundingRect().width() > item1->boundingRect().height() ? item1->boundingRect().width() : item1->boundingRect().height();
    int dimension_width  = ui->graphicsView->rect().width();
    int dimension_height = ui->graphicsView->rect().height();

    int biggest_canvas_dimension = dimension_width > dimension_height ? dimension_width : dimension_height;

    if(maximum > ui->graphicsView->rect().width() || maximum > ui->graphicsView->rect().height())
    {
        dimension_width = (int) (item1->boundingRect().width() * ((float)(biggest_canvas_dimension )/maximum));
        dimension_height = (int) (item1->boundingRect().height() * ((float)(biggest_canvas_dimension)/maximum));
        item1->setPixmap(item1->pixmap().scaled(dimension_width,dimension_height));
    }*/
    //scene->setSceneRect(ui->graphicsView->rect());

    //ui->graphicsView->setScene(scene_grey);

}

void pictures::changeImage()
{
    timerImageChange->start(imageChangeTime);
    timerGrey->stop();
    image_counter = (image_counter+1)%4;

    qDebug() << "    item1 = images[" + QString::number(image_counter) + "]";

    scene->removeItem(scene->items().at(0));

    item1 = images[image_counter];

    //qDebug() << QDir::toNativeSeparators((QDir::current().absolutePath() + QDir::separator () + "debug" + QDir::separator () + "pics" + QDir::separator () + QString::number(counter) + QDir::separator()+ QString::number(image_counter+1) +".jpg"));


    int maximum = item1->boundingRect().width() > item1->boundingRect().height() ? item1->boundingRect().width() : item1->boundingRect().height();
    int dimension_width  = ui->graphicsView->rect().width();
    int dimension_height = ui->graphicsView->rect().height();

    int biggest_canvas_dimension = dimension_width > dimension_height ? dimension_width : dimension_height;

    if(maximum > ui->graphicsView->rect().width() || maximum > ui->graphicsView->rect().height())
    {
        dimension_width = (int) (item1->boundingRect().width() * ((float)(biggest_canvas_dimension )/maximum));
        dimension_height = (int) (item1->boundingRect().height() * ((float)(biggest_canvas_dimension)/maximum));
        item1->setPixmap(item1->pixmap().scaled(dimension_width,dimension_height));
    }

    //item1->setPixmap(item1->pixmap().scaled(QSize(ui->graphicsView->rect().width(), ui->graphicsView->rect().height())));
    //scene->setSceneRect(ui->graphicsView->rect());
    scene->addItem(item1);
    //ui->graphicsView->setScene(scene);

    //ui->graphicsView->setScene(scene);
    //ui->graphicsView->adjustSize();

    //ui->graphicsView->show();

}

1 个答案:

答案 0 :(得分:3)

请记住,如果您的显示器刷新率为60 Hz,则每个图像在16 ms内重绘一次。您无法以30 ms的精确时序绘制,只能以16.666 ms的间隔进行计时。至少在Windows中,您无法轻易找到显示器中显示的图像何时发生变化。如果您的代码显示的图像例如为10毫秒,那么您可以看到图像,也可以不看图像。如果您显示图像25毫秒,您可以看到图像一次(16.666毫秒)或两次(33.333毫秒)。

如果您真的想要精确计时,我建议您使用OpenGL,您可以使用显示器的垂直同步信息为绘图计时。

您在绘图期间看到的线条可能是tearing。您也可以使用显示器的垂直同步信息远离它。

您还使用Qt的计时器计算10 ms的间隔。这不起作用。超时至少为10毫秒,但不能保证精确到10毫秒。在实践中它更多,因此100次超时的总时间可能大约为1100毫秒。甚至更多,取决于您的操作系统。在Windows中,默认计时器分辨率为16毫秒。然后100次超时加起来大约1700毫秒。您可以使用timeBeginPeriod更改计时器分辨率。

要获得更准确的计时,请在您想要等待的时间内启动计时器。如果您想在70 ms后执行某些操作,请将计时器间隔更改为70 ms,而不是使7个10 ms超时。