2012-06-17 2 views
1

나는 여자 친구 학사 학위 논문에 대한 변화 실명 방지 프로그램을 쓰고 싶었습니다. X 밀리 초 동안 사진을 보여 주며 짧은 깜박임 이미지 (이 경우 회색)를 보여 주며 첫 번째 사진과 약간 다른 이미지를 보여줍니다. 다시 깜박임 이미지.QGraphicsView 깜박임

그런 다음 모든 것이 처음부터 시작됩니다. 이미 잘 작동하고 그래픽 아티팩트가 있습니다. 캔버스/QGraphicsView는 내가 생각하기에 충분히 빨리 리프레쉬하지 않으므로 리프레시 중에는 "라인"이됩니다.

표시 할 이미지 시간 : 70ms, 깜박임 시간 : 30ms. 따라서 초당 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(); 

} 

답변

3

모니터 주사율이 60 Hz에서의 경우, 각각의 이미지가 16 밀리 번 다시 그려 것을 기억하십시오. 30ms와 같은 정확한 타이밍으로 그릴 수 없으며, 16.666ms 간격으로 타이밍 만 가능합니다. 적어도 Windows에서는 모니터에 표시되는 이미지가 언제 바뀌는 지 쉽게 알 수 없습니다. 예를 들어 코드에 10ms 동안 이미지가 표시되면 이미지가 표시되거나 표시되지 않습니다. 이미지를 25ms 동안 표시하면 이미지는 한 번 (16.666ms) 또는 두 번 (33.333ms) 보입니다.

정확한 타이밍을 원하면 모니터의 수직 동기화 정보를 사용하여 도면의 시간을 조정할 수있는 OpenGL을 사용하는 것이 좋습니다.

그리기 중에 표시되는 줄은 아마도 tearing입니다. 또한 모니터의 수직 동기화 정보를 사용하여 멀리 떨어져있을 수 있습니다.

또한 Qt의 타이머를 사용하여 10ms 간격으로 계산합니다. 그건 작동하지 않습니다. 제한 시간은 최소 10ms이지만 정확히 10ms가되는 것은 아닙니다. 실제로는 더 많으므로 100 개의 제한 시간의 총 시간은 아마도 약 1100ms입니다. 운영 체제에 따라 훨씬 더 많습니다. Windows에서 기본 타이머 해상도는 16ms입니다. 그런 다음 100 개의 제한 시간이 최대 약 1700 ms가됩니다. timeBeginPeriod을 사용하여 타이머 해상도를 변경할 수 있습니다.

정확한 타이밍을 얻으려면 기다려야 할 기간 동안 타이머를 시작하십시오. 70 밀리 초 후에 뭔가를하고 싶다면 10 밀리 초의 시간 초과 대신 7 밀리 초로 타이머 간격을 변경하십시오.

+0

두 번째 로쿠의 통찰력. 일반적으로 어떤 참조 이후 실제로 경과 한 시간을 확인하기 위해'QElapsedTimer'를 사용하고, 타이머 이벤트가 발생했을 때를 가정하지 않고 실시간으로 진행할 수 있습니다. 타이머를 설정하고 싶으면 타이머를 설정하십시오. 그러나'timerEvent' 또는 슬롯 안에 실시간이 얼마나 멀었는지에 따라 표시 할 것을 선택하십시오. –

+1

더 정확한 것 같아서 16 초 intervalls를 사용했습니다. 지금은 아름답지만 일은 적습니다 : P. 임, QGLWidget을 뷰포트 (OpenGL을 프로 파일에 추가)로 시도하여 문제가되는 찢어짐을 피하십시오. 도와 주셔서 감사합니다 :) – user1439712