[PyQt5] UI 동작 순서

김유상·2022년 12월 22일
0
  1. 생성자를 통한 UI 초기화가 이루어진다.
  2. 이후 사용자와의 GUI 상호작용을 통해 사용자에게서 받은 signal에 해당하는 slot을 호출한다.
  3. 호출한 slot 내에 존재하는 GUI 수정 항목들은 QApplication 내부 스택에 쌓이게 된다.
  4. slot에 대한 모든 호출 스택을 벗어나면 QApplication에서 직접 내부 스택의 내용들을 한꺼번에 적용한다.

이 과정에서 GUI 수정 항목과 로직 사이의 관계는 전부 무시되는 결과가 나타나는데
결국에는 GUI 수정 항목들은 모든 로직이 수행된 후에야 적용되므로 사용자 눈에는 한번에 적용되는 것처럼 보여지게 된다.

def __init__(self):
    label = QLabel('busy')

def open_large_file(self, file_name):
    label = QLabel('busy') # 무시됨...
    # QMessageBox.information(self, 'info', 'It's too large file!')
    with open(file_name) as f: # 로드하는데 오래 걸리는 파일!
        file = json.load(f)
    label = QLabel('free')

그러면 일부 UI적으로 겹친 부분은 아예 표시가 되었는지도 모르고 지나치는 상황이 발생할 수 있는데,

그나마 임시방편으로 사용할 수 있는 것이 QMessageBox이다. QMessageBox는 호출과 동시에 화면에 표시되어야 하므로 이전에 쌓여 있던 QApplication 내부 스택을 모두 적용할 수 있다. 아마 수동적으로 호출하는 방법이 있을 것도 같은데 아직 발견하지 못했다.

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = LabelingMain()
    app.installEventFilter(window)
    sys.exit(app.exec_()) #이 부분에서 모든 변경 사항을 한 번에 적용하게 된다.

수동으로 호출하는 방법을 알아냈다!

현재 window 혹은 widget의 객체의 repaint를 호출하면 QApplication(상위 객체)으로 하여금 즉시 화면에 반영하도록 할 수 있다.

self.repaint()

processEvents() 또한 선언을 통해 QApplication 내에 pending event에 대해 처리할 수 있다고 한다. 이 방법도 화면을 즉시 반영하는데 도움을 주지만 공식 문서에서는 실제로 사용하는 것을 권장하지 않는다고 한다. 하지만 thread-safe를 보장하기 때문에 필요한 상황이라면 사용해도 될 것 같다.

QApplication.processEvents()

Referenced: https://m.blog.naver.com/pjt3591oo/221145439454, https://doc.qt.io/qt-6/qcoreapplication.html

profile
continuous programming

0개의 댓글