PyQt5 기본

장승현·2023년 4월 11일
0

PyQt5

목록 보기
1/3
post-thumbnail

소개

PyQt5는 Qt 레이아웃에 Python 코드를 연결하여 GUI 프로그램을 만들 수 있게 해주는 프레임워크이다. Qt는 플랫폼에 관계없이 다양한 기능을 포함하는 C++ 라이브러리이자 개발툴로, PyGTK, PySide, Tkinter 등 Python의 다양한 GUI 프레임워크와 비교하여 가장 간단한 설계와 준수한 디자인을 가지고 있다. 아나콘다를 통해서 설치가 가능하다.

기본 개념

QtMainWindow 구성 요소

메인창(MainWindow)는 MenuBar, ToolBars, Dock Widgets, Central Widget, StatusBar로 구성되며 고유의 Layout을 보유하고 있다. MenuBar는 어플리케이션의 명령의 집합이다. ToolBar는 사용자의 편의를 고려한 명령의 집합이다. Dock Widgets은 MainWindow에 도킹 가능한 Widget이다. 가운데 영역의 Central Widget에는 어떠한 Widget도 삽입 가능하며, 이들은 모두 QMainWindow 클래스를 상속받아 생성 가능하다. Widget은 프로그램에서 기능을 하는 최소한의 객체이다.

Layout

Layout은 어플리케이션 창에 Widget들을 배치하는 방식이다. 절대적 배치, 박스 레이아웃, 그리드 레이아웃 방식이 있다. 절대적 배치는 각 Widget의 위치와 크기를 픽셀 단위로 설정해서 배치한다. 이때 창의 크기를 조절해도 Widget의 위치와 크기는 변하지 않으며, 일일이 직접 설정해야 하기 때문에 번거롭다. 박스 레이아웃은 수평과 수직 중 한가지의 방향으로만 Widget이 위치되며, 행 또는 열이 존재한다. 그리드 레이아웃은 수평과 수직으로 동시에 위치시킬 수 있다.

Event Loop

모든 Qt 프로그램은 QApplication이라는 클래스를 통해 상호작용한다. Click 또는 Drag&Drop과 같은 하나의 입력 작업을 Event라 하며, Qt 프로그램 안에서 이런 정보들이 Event Queue에 쌓인다. QApplication은 이를 모니터링하며 처리되지 않은 이벤트를 순차적으로 처리한다. 이벤트를 처리하는 Event Handler가 특정 이벤트를 처리하기 위해 움직이는 동안 QApplication은 잠시 멈춘다. 이후 처리가 끝나면 다시 QApplication이 남은 이벤트를 처리하며 이러한 과정을 Event Loop라 한다. 이 Event Loop를 실행하기 위해서는 .exec_() 메서드를 사용한다.

Signal 과 Slot

Signal은 말 그대로 사용자가 위젯의 상태를 변화시켰을 때, 이를 알려주어 코드 내에서 특정 행동을 할 수 있게 하는 신호이다. Slot은 이러한 Signal을 받아 특정 행동을 하는 함수이다. 각 Widget마다 정해진 Signal이 존재하기도 하며, 이를 사용자가 정의하여 사용할 수도 있다.

간단한 예제

기본 창 띄우기

import sys
from PyQt5.QtWidgets import *

class MainWindow(QMainWindow):
    '''
    main window를 설정하는 클래스
    '''
    def __init__(self):
        '''
        QMainWindow를 상속받아 main window를 만든다.
        '''
        super().__init__()

if __name__ == "__main__":
    # QApplcation은 프로그램을 실행시켜주는 클래스
    app = QApplication(sys.argv)

    # 위에서 만든 MainWindow 클래스의 인스턴스를 생성
    main = MainWindow()

    # main window ui를 보여주는 메서드 실행
    main.show()

    # 프로그램을 Event Loop로 진입시키는 메서드 실행(프로그램을 실행)
    app.exec_()

현재 창은 QMainWindow를 상속받았기에 위에서 설명한 MenuBar, ToolBars, StatusBar 등의 고유 Layout을 보유하고 있다. 하지만 이에 대한 설정은 하지 않았기에 현재는 확인할 수 없다.

import sys
from PyQt5.QtWidgets import *

class MainWindow(QMainWindow):
    '''
    main window를 설정하는 클래스
    '''
    def __init__(self):
        '''
        QMainWindow를 상속받아 main window를 만든다.
        '''
        super().__init__()
        self.initUi()

    def initUi(self):
        '''
        main window의 초기 화면을 설정하는 메서드
        '''
        # menuBar 메서드를 통해 QMenuBar 클래스의 인스턴스 생성
        menubar = self.menuBar()
        # addMenu 메서드를 사용하여 File이라는 이름을 가진 QMenu 클래스의 인스턴스를 생성
        file_menu = menubar.addMenu("File")
        # addAction 메서드를 사용하여 File menu가 클릭되었을 때, Load File라는 텍스트의 QAction 인스턴스를 생성
        load_action = file_menu.addAction("Load File")
        # action이 활성화 됐을 때 실행할 함수를 연결
        load_action.triggered.connect(self.loadFile)

	@pyqtSlot()
    def loadFile(self):
        '''
        QFileDialog 클래스의 정적 메소드를 이용해 파일을 불러오는 메서드
        '''
        file = QFileDialog.getOpenFileName(self)


if __name__ == "__main__":
    # QApplcation은 프로그램을 실행시켜주는 클래스
    app = QApplication(sys.argv)

    # 위에서 만든 MainWindow 클래스의 인스턴스를 생성
    main = MainWindow()

    # main window ui를 보여주는 메서드 실행
    main.show()

    # 프로그램을 Event Loop로 진입시키는 메서드 실행(프로그램을 실행)
    app.exec_()

위 코드에서 load_action.triggered는 Signal이며, 연결된 함수는 Slot이다.

ToolBar 만들기

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MainWindow(QMainWindow):
    '''
    main window를 설정하는 클래스
    '''
    def __init__(self):
        '''
        QMainWindow를 상속받아 main window를 만든다.
        '''
        super().__init__()
        self.initUi()

    def initUi(self):
        '''
        main window의 초기 화면을 설정하는 메서드
        '''
        # addToolBar 메서드를 통해 QToolBar 클래스의 인스턴스 생성
        load_toolbar = self.addToolBar("Load")
        # addAction 메서드를 사용하여 클릭되었을 때, Load File라는 텍스트의 QAction 인스턴스를 생성
        load_action = load_toolbar.addAction("Load")
        # action이 활성화 됐을 때 실행할 함수를 연결
        load_action.triggered.connect(self.loadFile)

    @pyqtSlot()
    def loadFile(self):
        '''
        QFileDialog 클래스의 정적 메소드를 이용해 파일을 불러오는 메서드
        '''
        file = QFileDialog.getOpenFileName(self)


if __name__ == "__main__":
    # QApplcation은 프로그램을 실행시켜주는 클래스
    app = QApplication(sys.argv)

    # 위에서 만든 MainWindow 클래스의 인스턴스를 생성
    main = MainWindow()

    # main window ui를 보여주는 메서드 실행
    main.show()

    # 프로그램을 Event Loop로 진입시키는 메서드 실행(프로그램을 실행)
    app.exec_()

StatusBar 만들기

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MainWindow(QMainWindow):
    '''
    main window를 설정하는 클래스
    '''
    def __init__(self):
        '''
        QMainWindow를 상속받아 main window를 만든다.
        '''
        super().__init__()
        self.initUi()

    def initUi(self):
        '''
        main window의 초기 화면을 설정하는 메서드
        '''
        # statusBar 메서드를 통해 QStatusBar 클래스의 인스턴스 생성
        statusbar = self.statusBar()
        # showMessage 메서드를 사용하여 statusBar에 Ready라는 메세지 출력
        statusbar.showMessage("Ready")


if __name__ == "__main__":
    # QApplcation은 프로그램을 실행시켜주는 클래스
    app = QApplication(sys.argv)

    # 위에서 만든 MainWindow 클래스의 인스턴스를 생성
    main = MainWindow()

    # main window ui를 보여주는 메서드 실행
    main.show()

    # 프로그램을 Event Loop로 진입시키는 메서드 실행(프로그램을 실행)
    app.exec_()

Dock Widget 만들기

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class MainWindow(QMainWindow):
    '''
    main window를 설정하는 클래스
    '''
    def __init__(self):
        '''
        QMainWindow를 상속받아 main window를 만든다.
        '''
        super().__init__()
        self.initUi()

    def initUi(self):
        '''
        main window의 초기 화면을 설정하는 메서드
        '''
        # QDockWidget 클래스에 DockWidget이라는 텍스트와 MainWindow 클래스를 인자로 하여 인스턴스를 생성
        dock_widget = QDockWidget(title="DockWidget", parent=self)


if __name__ == "__main__":
    # QApplcation은 프로그램을 실행시켜주는 클래스
    app = QApplication(sys.argv)

    # 위에서 만든 MainWindow 클래스의 인스턴스를 생성
    main = MainWindow()

    # main window ui를 보여주는 메서드 실행
    main.show()

    # 프로그램을 Event Loop로 진입시키는 메서드 실행(프로그램을 실행)
    app.exec_()

Reference

https://wikidocs.net/35482

profile
늦더라도 끝이 강한 내가 되자

0개의 댓글