1

我想为我的女朋友的学士论文写一个改变失明的程序。它显示 X 毫秒的图片,显示一个简短的“闪烁图像”(在本例中为灰色),然后显示与第一个图像略有不同的图像。然后又是一个闪烁的图像。

然后一切从头开始。它工作正常,只有图形伪影。我认为画布/ QGraphicsView 刷新它的速度不够快,因此它们在刷新期间是“线条”。

图像显示时间:70 ms,闪烁时间:30 ms。所以它的 100 毫秒 = 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();

}
4

1 回答 1

3

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

如果您真的想要精确的时间,我建议您使用 OpenGL,您可以使用监视器的垂直同步信息对绘图进行计时。

您在绘图过程中看到的线条可能正在撕裂。您也可以通过使用显示器的垂直同步信息来避免这种情况。

您还使用 Qt 的计时器来计算 10 毫秒的间隔。那是行不通的。超时时间至少为 10 毫秒,但不能保证正好是 10 毫秒。实际上它更多,因此 100 次超时的总时间可能在 1100 毫秒左右。甚至更多,取决于您的操作系统。在 Windows 中,默认计时器分辨率为 16 毫秒。然后 100 次超时加起来约为 1700 毫秒。您可以使用timeBeginPeriod更改计时器分辨率。

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

于 2012-06-17T12:03:10.477 回答