2013-08-20 1 views
1

사용자가 기본 창을 기다리는 동안 작은 애니메이션 (애니메이션 GIF)을 표시해야하는 간단한 스플래시 화면 확장자가 있습니다. 문제는 첫 번째 프레임 만이 아니라 모든 도시되어있다 :QSplashScreen에 QMovie 표시

class SplashScreen : public QSplashScreen 
{ 
     Q_OBJECT 

    public: 
     explicit SplashScreen(const QPixmap& pixmap, const QString& animation, Qt::WindowFlags flags = 0); 

    protected: 
     void paintEvent(QPaintEvent* event); 

    signals: 
     void frameChanged(); 

    private slots: 
     void convertFrameChanged(int) 
     { 
      repaint(); 
     } 

    private: 
     QMovie movie; 

}; 


SplashScreen::SplashScreen(const QPixmap& pixmap, const QString& animation, Qt::WindowFlags flags) 
    : QSplashScreen(pixmap, flags), 
     movie(animation) 
{ 
    movie.start(); 
    connect(&(movie), SIGNAL(frameChanged(int)), this, SLOT(convertFrameChanged(int))); 
} 

void SplashScreen::paintEvent(QPaintEvent* event) 
{ 
    QSplashScreen::paintEvent(event); 

    QPixmap frame = movie.currentPixmap(); 
    QRect rect = frame.rect(); 
    rect.moveCenter(this->rect().center()); 
    if (rect.intersects(event->rect())) 
    { 
     QPainter painter(this); 
     painter.drawPixmap(rect.left(), rect.top(), frame); 
    } 
} 

편집 : 스플래시 스크린에

QTimer *timer = new QTimer(this); 
connect(timer, SIGNAL(timeout()), this, SLOT(doRefresh())); 
timer->start(1000); 

라이트 슬롯 :

가되는 SplashScreen 생성자 QTimer으로 칠 호출 시도 :

void doRefresh() 
    { 
     repaint(); 
    } 

그러나 이것도 작동하지 않았습니다. doRefresh가 호출되지 않습니다. 그것은 QTimer 또한 기존의 이벤트 루프가 이미 필요합니다 보인다.

답변

1

QApplication :: exec() 함수가 호출되기 전에 스플래시 화면이 표시된다고 가정하면 이벤트가 처리되지 않을 가능성이 있으므로 QApplication 객체에서 processEvents를 호출해야합니다.

주 도움말 예 : -

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 
    QPixmap pixmap(":/splash.png"); 
    QSplashScreen splash(pixmap); 
    splash.show(); 
    app.processEvents(); // need to process events manually 
    ... 
    QMainWindow window; 
    window.show(); 
    splash.finish(&window); 
    return app.exec(); 

}은 상단에 남아 보장하기 위해 QTimer와는 시작 화면에() 인상 호출에서는이 상황에서

는하지만, processEvents 필요 QTimer가 작동 할 것을 요구하십시오.

는 마우스 버튼을 클릭하면 시작 화면을 기각하는 Qt는 도움에 상태로 : - 이벤트 루프 실행이 시작되기 전에 시작 화면은 일반적으로 표시되기 때문에

, 정기적으로의 QApplication를 호출 할 필요가 :: processEvents()는 마우스 클릭을 받는다.

동일한 내용이 애니메이션 gif에 적용될 수 있습니다.

+0

관련성이 있지만 문제가 해결되지 않았을 수 있습니다. GIF는 첫 번째 프레임 만 표시합니다. QMovie는 frameChanged 이벤트를 한 번만 내 보냅니다 (그러나 gif에는 둘 이상의 이벤트가 있음). – Beachwalker

+0

질문에 주 코드를 추가하여 스플래시 화면과 QApplication을 인스턴스화 할 수 있습니까? – TheDarkKnight

+0

이제는 모두 작동합니까? – TheDarkKnight

1

문제가 심각합니다. 애니메이션 작업을하려면 메인 스레드에서 프로세스 이벤트를 허용해야합니다. 반면에 초기화 프로세스는 메인 스레드에서도 수행됩니다.
첫 번째 방법은 가능한 한 자주 app.processEvents()을 추가하지만 프레임 속도가 너무 낮아 제한적이므로 쓸모가 없습니다.

  • 당신이 초기화하는 동안 무엇을하고 있는지 :

    당신은 두 가지 중요한 질문에 대한 답변이 제대로 해결하려면?

  • 이 초기화를 별도의 스레드로 옮길 수 있습니까?

일단 내가 초기화하는 동안 큰 인덱스가 작성된 곳에서 응용 프로그램을 만들었습니다. 이것은 40 초 정도 걸렸습니다. 나는 QtConcurrent::run(this, &MyClass::MyMethodToBuildIndex)을 사용하여 별도의 스레드로 건물 인덱스를 옮겨서 MyClass::MyMethodToBuildIndex (주기적 자동 연결이 전체 트릭을 수행함)에서 주기적으로 신호를 방출하여 진행 상황을 보여줍니다.
비슷한 로그 시간 초기화가있는 경우이 솔루션을 사용하면 QMovie의 애니메이션을 사용할 수 있습니다. 문제는 신호와 슬롯을 똑똑하게 연결하여 적절한 타이밍으로 창이 표시되고 숨겨집니다.


매우 간단합니다. 세부 사항은 응용 프로그램을 어떻게 디자인 했느냐에 달려 있습니다. 나는 보통 비지니스 로직을 가진 별도의 클래스를 만든다. 당신이 다음 QSignalMapper 도울 수 대신 close QSplashScreen::finish를 사용해야하는 경우

int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 
    SplashScreen splash(); 
    splash.show(); 
    app.processEvents(); // need to process events manually 

    QMainWindow window; 
    SomeLogicClass data; 
    window.setData(&data); 

    connect(&data, SIGNAL(initializationProgressChanged(int)), 
      &spash, SLOT(setProgress(int))); 

    // show main window when initialization is finished 
    connect(&data, SIGNAL(initializationFinished()), 
      &window, SLOT(show())); 

    // close splash when initialization is finished 
    connect(&data, SIGNAL(initializationFinished()), 
      &spash, SLOT(close())); 

    // this line I usually hide behind some method like: startBackgroundInitialization 
    QtCuncurent::run(&data, &SomeLogicClass::heavyInitialization); 

    return app.exec(); 
} 

:이 클래스는 초기화하는 동안 수행이 뭔가를 할 수있는 몇 가지 무거운 계산을 포함합니다.
connect의 마지막 인수는 기본 값 Qt::AutoConnection이며 주 스레드에서 슬롯을 실행하도록 지정합니다.

+0

흥미로운 것 같습니다. 좀 더 명확하게하기 위해 힌트, 코드 또는 링크를 더 줄 수 있습니까? – Beachwalker

+0

답변 업데이트를 참조하십시오. 초기화하는 동안 일어나는 일을 쓰지 않았으므로 어떻게 할 수 있는지에 대한 일반적인 설명을 해주었습니다. –