본문 바로가기

PyQt GUI

PyQt GUI (4) : 위젯 이벤트 연결 (버튼 클릭 시 반응 하게 하기) - clicked.conncet()

728x90

https://www.youtube.com/watch?v=jnWiIMWVcdA

이전까지의 포스팅은 위젯을 생성하고 이 위젯을 원하는 위치에 배치하여 UI를 띄우는 것이 주된 내용이었습니다. 실제 UI에서는 사용자가 위젯을 사용하기에 따라서 프로그램이 반응을 해야 합니다. 예를들어서, 버튼을 클릭했을 때 프로세스가 실행이 된다든가, 콤보박스에서 원하는 아이템을 선택했을 때, 프로그램에서는 어떤 아이템을 선택했는지를 인지한다든가 입니다. 

 

이번 포스팅에서는 각 위젯에 이벤트를 어떻게 처리 하는지, 즉 사용자의 위젯 사용에 따라서 프로그램이 어떻게 반응해야 하는지를 설계해 보도록 하겠습니다. 우선 전체 코드는 아래와 같습니다. 

import sys
from PyQt5.QtWidgets import *

class Main(QDialog):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        main_layout = QVBoxLayout()

        pushbutton = QPushButton("Click Me !")
        pushbutton.clicked.connect(self.button_clicked)
        main_layout.addWidget(pushbutton)

        self.lineedit = QLineEdit()
        main_layout.addWidget(self.lineedit)

        combobox = QComboBox()
        combobox.addItems(["dog", "cat", "rabbit", "lion"])
        combobox.currentTextChanged.connect(self.combobox_changed)
        main_layout.addWidget(combobox)

        self.lineedit_combox = QLineEdit()
        main_layout.addWidget(self.lineedit_combox)

        checkbox = QCheckBox("item")
        checkbox.stateChanged.connect(self.checkbox_changed)
        main_layout.addWidget(checkbox)

        self.linedit_checkbox = QLineEdit()
        main_layout.addWidget(self.linedit_checkbox)

        radio_1, radio_2 = QRadioButton("A"), QRadioButton("B")
        radio_1.toggled.connect(self.radio_1_toggled)
        radio_2.toggled.connect(self.radio_2_toggled)
        main_layout.addWidget(radio_1)
        main_layout.addWidget(radio_2)
        self.lineedit_radio_1 = QLineEdit()
        self.lineedit_radio_2 = QLineEdit()
        main_layout.addWidget(self.lineedit_radio_1)
        main_layout.addWidget(self.lineedit_radio_2)

        self.setLayout(main_layout)
        self.resize(400, 400)
        self.show()

    ###############
    ### actions ###
    ###############
    def button_clicked(self):
        self.lineedit.setText("button clicked.")

    def combobox_changed(self, item):
        self.lineedit_combox.setText('Your selection : ' + item)

    def checkbox_changed(self, state):
        self.linedit_checkbox.setText(str(state))

    def radio_1_toggled(self, state):
        self.lineedit_radio_1.setText(str(state))

    def radio_2_toggled(self, state):
        self.lineedit_radio_2.setText(str(state))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Main()
    sys.exit(app.exec_())

이 프로그램을 실행하면, 

와 깉이 간단하게 PushButton, LineEdit, ComboBox, CheckBox, RadioButton으로 구성된 UI를 확인할 수 있습니다. 

 

이전 포스팅까지는 이 위젯을 배치하고 UI를 띄우는 것에서 멈췄지만, 이번 포스팅에서는 각 위젯에 작용을 가함에 따라서 프로그램이 반작용을 하는 것을 정의해 두었습니다. 따라서 위 Click Me ! 버튼을 클릭하게 되면, 바로 아래에 있는 LineEdit에 "button clicked." 라는 문구가 뜨게 됩니다. 

이처럼 PushButton 위젯을 클릭했을 때, 어떠한 이벤트를 연결하기 위해서는 

 

.clicked.connect(함수)

 

와 같이 버튼이 클릭 되었을 때, 어떤 함수에 연결(connect)시킬지를 지정해 주면 됩니다. 위 코드에서 이 부분은

pushbutton.clicked.connect(self.button_clicked)
def button_clicked(self):
    self.lineedit.setText("button clicked.")

으로, pushbutton을 클릭했을 때, button_clicked 메소드가 실행이 되는데, button_clicked 메소드에서는 self.lineedit에 "button clicked."라는 문구를 쓰게 합니다. lineedit위젯에 .setText("텍스크문구")를 하게 되면 lineedit의 입력창에 "텍스트문구"가 입력되게 됩니다. 

 

기본값이 "dog"으로 돼 있는 콤보박스의 선택을 "cat"으로 변경하면, 

와 같이 콤보박스 바로 아래칸에 "Your selection : cat"과 같이 문구가 뜹니다. 위 PushButton의 경우와 마찬가지로 콤보박스의 선택이 바뀌게 되면, 콤보박스의 바로 아래 lineedit에 "Your selection : cat" 문구가 출력이 되도록 이벤트를 연결했기 때문입니다. 

 

콤보박스와 관련된 부분은

combobox.currentTextChanged.connect(self.combobox_changed)
def combobox_changed(self, item):
    self.lineedit_combox.setText('Your selection : ' + item)

으로 .currnetTextChanged.connect(함수)를 통해서, 콤보박스의 선택 아이템이 바뀐 경우 함수를 호출 하도록 이벤트 설정을 할 수 있습니다. 호출된 이벤트인 combobox_changed는 기본적으로 combobox에서 어떤 아이템이 선택이 되었는지에 대한 정보인 item을 입력으로 받을 수 있습니다. 

 

체크박스를 클릭/언클릭 했을 때 역시 이벤트를 정의할 수 있습니다. 

위 이미지와 같이 item 이라는 체크박스를 체크하면 아래의 lineedit에 2가, 언체크 하면(체크를 해제하면) 0이 출력됨을 확인할 수 있습니다. 전체 코드에서 이 체크박스와 관련된 부분은

checkbox.stateChanged.connect(self.checkbox_changed)
def checkbox_changed(self, state):
    self.linedit_checkbox.setText(str(state))

로, 체크박스의 상태(선택, 해제)가 바뀜에 따라서 .stateChanged.connect(함수) 를 이용하여 이벤트 설정을 해 줄 수 있습니다. 선택에서 해제로 혹은 반대로 해제에서 선택으로 체크박스의 상태가 바뀔 때 마다 "함수"가 호출되게 됩니다. 

 

위 코드에서는 checkbox_changed 메소드가 호출이 되는데, 이 메소드에서는 체크박스의 상태(state)를 인자로 받아서 lineedit에 출력을 합니다. 위 콤보박스와 마찬가지로, stateChanged 는 체크박스의 상태(state)를 하나 입력해 주는데, 선택된 경우에는 이 값이 2, 해제된 경우에는 이 값이 0 이 됩니다. 

 

마지막으로 라디오 버튼의 예시 입니다. 라디오 버튼은 여러개의 버튼 중에서 단지 하나만을 선택할 수 있는데요, 위 UI에서 A, B 중에서 하나만을 선택할 수 있습니다. A가 선택된 상태에서 B를 선택하게 되면 A는 자동으로 해제가 되고 B가 선택이 되게 됩니다. 

실제 실행한 예시 입니다. A가 원래 선택된 상태에 있다가 B를 선택하게 되면 아래에 있는 LineEdit에 차례로 A, B의 상태를 기술하는 False, True가 뜨게 됩니다. 위 부분에 해당되는 코드는

radio_1, radio_2 = QRadioButton("A"), QRadioButton("B")
radio_1.toggled.connect(self.radio_1_toggled)
radio_2.toggled.connect(self.radio_2_toggled)

def radio_1_toggled(self, state):
    self.lineedit_radio_1.setText(str(state))
def radio_2_toggled(self, state):
    self.lineedit_radio_2.setText(str(state))

입니다. RadioButton에서 선택, 비선택에 따른 변화는 toggled를 통해서 감지할 수 있고, 선택, 비선택의 상태가 바뀔 때 바다 toggled.connect("함수")를 통해서 함수를 호출 할 수 있습니다. 

 

radio_1, radio_2는 각각 radio_1_toggled, radio_2_toggled 메소드를 호출하게 되는데, 위 CheckBox의 예에서와 같이 toggled는 해당 라디오버튼의 상태(state)를 입력해 주기 때문에 radio_1_toggled, radio_2_toggled 메소드에서는 state를 바로 인자로 받을 수 있습니다. 라디오버튼의 상태는 True/False가 됩니다. 

728x90