QApplication :: exec ()를 호출하지 않고 위젯을 표시하는 올바른 방법은 무엇입니까?

Nov 20 2020

테스트 목적으로 위젯을 만들고 표시하고 싶습니다. 지금은 올바르게 렌더링하기 위해 위젯 만 필요하지만 향후에는이를 확장하여 위젯이 어떻게 작동하는지 확인하기 위해 다양한 이벤트를 시뮬레이션 할 수 있습니다.

다양한 소스에서 다음이 작동하는 것처럼 보입니다.

QApplication app;

QPushButton button("Hello");
button.show();

// Might also be necessary:
QApplication::processEvents();

그러나 나를 위해 위젯이 올바르게 렌더링되지 않습니다. 위젯을 표시하기 위해 창이 생성되지만 완전히 검은 색입니다.

다음 줄을 추가하여 위젯이 올바르게 렌더링되도록 할 수 있습니다.

std::this_thread::sleep_for(std::chrono::milliseconds(10));
QApplication::processEvents();

위젯이 올바르게 렌더링되는 데 필요한 최소 시간은 10 밀리 초입니다.

누구든지 시간 지연없이 이것을 작동시키는 방법을 알고 있거나 지연이 필요한 이유를 알고 있습니까?

답변

4 pptaszni Nov 20 2020 at 17:13

Qt GUI 애플리케이션을 테스트하려면 최소한 QApplication인스턴스와 이벤트 루프가 처리되어야합니다. 가장 빠른 방법은 QTEST_MAIN매크로를 사용하는 것입니다 . 이 답변 은 그것이 정확히 무엇을하는지 좋은 방식으로 설명합니다. 그러나 더 많은 유연성을 갖기 위해 (예 : GTest, GMock 사용) QAplication테스트 메인에서 인스턴스를 생성 할 수도 있습니다 (를 호출 할 필요 없음 exec).

그런 다음 이벤트를 처리하려면 QTest :: qWait를 호출해야합니다 . 이렇게하면 지정된 시간 동안 이벤트가 처리됩니다. qWaitFor술어를 허용하는 것을 사용하는 것이 좋습니다. 이렇게하면 테스트에서 경쟁 조건을 피할 수 있습니다.

특정 시나리오에서 일부 신호가 방출 될 것으로 예상 할 때 QSignalSpy :: wait 의 유사한 기능을 사용할 수도 있습니다 .

한 항목에서 다른 항목으로 일부 매개 변수가 전달 될 때까지 기다리는 작은 예 :

QSignalSpy spy(&widget1, &Widget1::settingsChanged);
widget2->applySettings();
ASSERT_TRUE(spy.wait(5000));
// do some further tests based on the content of passed settings
1 VincentFourmond Nov 20 2020 at 16:39

응용 프로그램이 exec를 실행하지 않는 이유는 무엇입니까? 위젯을 표시하는 프로세스는 "정적"이 아닙니다. 화면에 위젯을 "그리지"않는 대신 다양한 이벤트를 수신하고 창 관리자로부터 그리기 이벤트를 수신하는 애플리케이션이 있습니다. 애플리케이션은 창 관리자가 요청할 때만 위젯을 그릴 수 있습니다.

두 번째 코드가 작동하는 이유는 창 관리자가 조건에서 "그리기"요청 보낼 때까지 충분히 오래 기다리기 때문 입니다. 이것이 항상 작동한다는 보장은 없습니다.

위젯의 표시를 보장하려면 루프를 시작하고 적어도 하나의 그리기 이벤트를받을 때까지 기다려야하지만, 그렇다고해서 절대 안전한 것은 아닙니다.

ypnos Nov 20 2020 at 16:58

Vincent Fourmond가 전문적으로 설명했듯이 위젯은 일회성 거래가 아닙니다. GUI는 차단되지 않으며이를 위해 이벤트 루프 에서 실행되어야합니다 .

exec()메서드는 폴링으로 모방 한이 이벤트 루프를 시작합니다. Qt의 이벤트 루프를 다른 이벤트 루프와 결합하는 것이 가능하지만 더 간단한 솔루션을 권장합니다.

시작될 때 메소드를 호출하여 이벤트 루프 내에서 프로그램을 진행하십시오. 이를 수행하는 방법에 대한 훌륭한 답변을 여기에서 찾으십시오.https://stackoverflow.com/a/8877968/21974

단위 테스트를 언급했듯이 수명주기가 끝날 때 (위젯이 파괴되기 전) 검사를 수행하는 데 사용할 수있는 신호도 있습니다 QApplication::aboutToQuit.. 이것은 마지막 창이 닫힐 때 (프로그래밍 방식으로 또는 사용자에 의해) 발생합니다.