2012-06-17 3 views
1

Я хотел написать программу слепоты с изменой для моей подруги бакалавра. Он показывает за X миллисекунд изображение, показывает короткое «мерцающее изображение» (в данном случае только серое), а затем показывает немного другое изображение, а затем первое. Затем снова изображение мерцания.QGraphicsView мерцает

Затем все начинается с самого начала. Он работает отлично allready, есть только графические артефакты. Я думаю, что canvas/QGraphicsView обновляет его недостаточно быстро, поэтому они являются «линиями» во время обновления.

Время отображения изображения: 70 мс, время мерцания: 30 мс. Таким образом, его 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(); 

} 

ответ

3

Помните, что если частота обновления вашего монитора составляет 60 Гц, то каждое изображение перерисовывается один раз в 16 мс. Вы не можете рисовать с точным временем, например, 30 мс, возможно только синхронизация с интервалами 16,666 мс. И, по крайней мере, в Windows вы не можете легко узнать, когда изображение, показанное на мониторе, изменится. Если ваш код показывает изображение, например, на 10 мс, то вы либо видите изображение, либо нет. Если вы показываете изображение в течение 25 мс, вы либо видите изображение один раз (16.666 мс), либо дважды (33.333 мс).

Если вы действительно хотите точное время, я бы порекомендовал использовать OpenGL, где вы можете время рисовать, используя информацию о вертикальной синхронизации монитора.

Линии, которые вы видите во время рисования, вероятно, tearing. Вы можете уйти от этого, также используя информацию о вертикальной синхронизации монитора.

Вы также используете таймер Qt для подсчета интервалов в 10 мс. Это не работает. Тайм-аут составляет не менее 10 мс, но не гарантируется ровно 10 мс. На практике это больше, поэтому общее время 100 тайм-аутов, вероятно, составляет около 1100 мс. И даже больше, в зависимости от вашей операционной системы. В Windows разрешение по умолчанию по умолчанию составляет 16 мс. Затем 100 тайм-аутов составляют около 1700 мс. Вы можете изменить разрешение таймера с помощью timeBeginPeriod.

Для более точного отсчета времени запустите таймер в течение периода, который вы хотите подождать. Если вы хотите сделать что-то через 70 мс, измените интервал таймера на 70 мс вместо семи тайм-аутов 10 мс.

+0

Я второй взгляд Року. В общем, вы можете использовать 'QElapsedTimer', чтобы проверить, сколько времени прошло с некоторой ссылкой, и действовать при прохождении в реальном времени, не предполагая ничего о том, когда событие таймера могло быть запущено. Установите таймер на огонь, когда захотите, но внутри 'timerEvent' или ваш слот выберите вещь, которая будет отображаться в зависимости от того, насколько далеко в реальном времени. –

+1

Я использовал сейчас 16 секундных перехватов, так как кажется более точным. Теперь красивая, но меньше работа: P. Я пытаюсь использовать QGLWidget как Viewport (добавляется opengl в файл pro), чтобы избежать разрыва, который, кажется, является проблемой. Спасибо вам за помощь :) – user1439712

Смежные вопросы