티스토리 뷰

Python/PyQt5

PyQt5와 QtDesigner 연습 1

editor752 2019. 10. 31. 18:40

PyQt5를 배우면서 QtDesigner도 함께 공부하고 있다. 우선 이렇게 학습하는 게 효과적인지는 모르겠지만 분명한 것은 혼자 삽질하는 시간이 꽤 길다는 점이다. 취미로 하는 프로그래밍인 탓에 본업에 바쁘면 한동안 손을 못 대기 되는데 이 둘을 함께 공부하면서 그 학습 휴지기의 여파가 크다는 것도 문제다. 만약 이 글을 읽는 사람 중에 PyQt5와 QtDesigner의 효과적인 학습법을 알고 있는 분은 꼭 댓글로 남겨 주시길.

PyQt5의 소스 코드는 아래와 같다.

code 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import sys
 
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QDial
from PyQt5.QtWidgets import QSlider
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QBoxLayout
from PyQt5.QtCore import Qt
 
__author__ = "Deokyu Lim <hong18s@gmail.com>"
 
 
class Form(QWidget):
    def __init__(self):
        QWidget.__init__(self, flags=Qt.Widget)
        self.dl = QDial()
        self.sd = QSlider(Qt.Horizontal)
        self.init_widget()
 
    def init_widget(self):
        self.setWindowTitle("Signal Slot")
        form_lbx = QBoxLayout(QBoxLayout.TopToBottom, parent=self)
        self.setLayout(form_lbx)
 
        # 시그널 슬롯 연결
        # 다이얼의 값이 변하면 슬라이더의 값을 변경하는 슬롯과 연결
        # 슬라이더의 값이 변화하면 다이얼의 값을 변경하는 슬롯과 연결
        # 두 위젯의 valueChange 시그널은 현재값을 int형으로 반환
        # 두 위젯의 setValue 슬롯은 int형만을 받는다.
        self.dl.valueChanged.connect(self.sd.setValue)
        self.sd.valueChanged.connect(self.dl.setValue)
 
        form_lbx.addWidget(self.dl)
        form_lbx.addWidget(self.sd)
 
 
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    exit(app.exec_())
 
cs

별도의 ui 파일을 사용하지 않고 직접 코딩하여 다이얼과 슬라이더를 구현한 소스코드이다. 이를 QtDesigner를 이용해서 ui 파일(ui.ui)을 만들도 이 ui 파일을 불러와서 사용하는 코드로 바꾸어 보았다.

code 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import sys
 
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QApplication
from PyQt5 import uic
 
class Form(QWidget):
 
    def __init__(self):
        QWidget.__init__(self)
        self.ui = uic.loadUi("/Users/dexion/PyQtDesigner/signalEx/ui.ui", self)
        self.ui.show()
 
 
    def init_widget(self):
        self.setWindowTitle("Signal Slot")
 
 
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    exit(app.exec_())
        
 
 
cs

사실 PyQt5도 QtDesigner도 알지 못한 채 소스 코드를 보고 통박(?)을 굴려 끼워 맞춘 것이라 각 라인의 정확한 의미까지 파악하지는 못한다. code 1을 code 2로 변환할 때 고려한 사항을 간단히 정리해 둔다.

  1. QtDesigner로 만든 ui(위 코드에서는 ui.ui)를 불러오기 위해서는 uic를 임포트한다(from PyQt5 import uic).
  2. Form을 초기화할 때 ui 파일을 해당 위젯의 ui 메서드에 연결한다(self.ui = uic.loadUi("/Users/dexion/PyQtDesigner/signalEx/ui.ui", self)).
  3. 이때 ui 파일을 찾지 못한다면 파일의 절대 경로를 적어 준다.

아래는 QtDesigner로 만든 ui.ui 파일이다. QtDesigner가 직관적이긴 했지만 GUI 툴로 프로그래밍을 해본 적이 거의 없어서 이 간단한 ui를 만드는 데도 꽤 시간이 걸렸다. 윈도우 폼을 만들거라면 역시 C#이나 본격적으로 학습할 걸 그랬다는 생각이…. CUI가 좋은 변태적인 성격을 어찌하겠는가? 그럼에도 GUI를 할 수밖에 없는 게 현실이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>206</width>
    <height>173</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <item>
    <widget class="QDial" name="dial"/>
   </item>
   <item>
    <widget class="QSlider" name="horizontalSlider">
     <property name="orientation">
      <enum>Qt::Horizontal</enum>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>dial</sender>
   <signal>valueChanged(int)</signal>
   <receiver>horizontalSlider</receiver>
   <slot>setValue(int)</slot>
   <hints>
    <hint type="sourcelabel">
     <x>113</x>
     <y>92</y>
    </hint>
    <hint type="destinationlabel">
     <x>119</x>
     <y>147</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>horizontalSlider</sender>
   <signal>valueChanged(int)</signal>
   <receiver>dial</receiver>
   <slot>setValue(int)</slot>
   <hints>
    <hint type="sourcelabel">
     <x>94</x>
     <y>151</y>
    </hint>
    <hint type="destinationlabel">
     <x>100</x>
     <y>111</y>
    </hint>
   </hints>
  </connection>
 </connections>
 <slots>
  <slot>slider()</slot>
 </slots>
</ui>
 
 
 
cs

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함
05-19 01:37