PyQT 사용하기
25 Mar 2021 | Python PyQT이번 포스팅에서는 pyqt5의 기본적인 사용법에 대해서 알아보려고 한다.
설치
pip install pyqt5
pip install pyqt5-tools
or
pip3 install pyqt5
pip3 install pyqt5-tools
이 후 설치가 되었나 확인해보자.
python
>>> import PyQt5
디자이너도 설치되었는지 확인하자. 환경변수로 저장되었을테니 터미널(윈도우에서는 CMD) 에서 실행하자.
designer
디자이너가 켜지면 성공이다.
QT 디자이너
디자이너는 크게 설명하진 않겠다.
.ui -> .py 으로 바꾸는 방법만을 설명하겠다.
일단 예시코드로 둔 배쉬 쉘 스크립트를 올리겠다.
#!/bin/bash
python -m PyQt5.uic.pyuic -x $1 -o ~/Desktop/frames-client/client/gui/$1.py;
설명하자면, 매개변수를 하나 받아 지정된 경로에 저장하는것이다.
뒤에 .py를 안붙이면 에러가 난다.
사용법은 이렇다.
python -m PyQt5.uic.pyuic -x {.ui 파일} -o {저장할 파일}
상대경로로 하면 python이 설치되어있는 곳 부터 시작하므로, 절대경로를 지정해주는 것을 추천한다.
좀 더 보기 쉽게
ui파일을 바꿔봤는데… 좀 가독성이 안좋아서 내 맘대로 리팩토링을 해봤다.
기존 파일
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setGeometry(QtCore.QRect(530, 10, 261, 181))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.label = QtWidgets.QLabel(self.frame)
self.label.setGeometry(QtCore.QRect(110, 10, 56, 12))
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "한글"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
뭐 변환된 그대로 쓰려면 써도 된다.
하지만 나는 병적으로 클래스화를 좋아하여 바꾸었다.
변환 결과
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from .gui_objectmaker import ObjectMaker
LOCATION = "MainWindow"
OM = ObjectMaker(LOCATION)
class Ui_Main(object):
def __init__(self, W, H):
super().__init__()
self.__app = QtWidgets.QApplication(sys.argv)
# Make MainWindow
self.__MainWindow = OM.makeMainWindow(W,H)
#Central Widget
self.__centralwidget = OM.makeCentralWidget(self.__MainWindow)
#StatusBar (하단)
self.statusbar = OM.makeStatusBar(self.__MainWindow)
# SetUp Ui
self.setupTemperature(W,H)
QtCore.QMetaObject.connectSlotsByName(self.__MainWindow)
def startUi(self):
self.__MainWindow.show()
sys.exit(self.__app.exec_())
def setupTemperature(self,W,H):
half_W = int(W / 2)
half_H = int(H / 2)
tick_W = int(W / TICK)
tick_H = int(H / TICK)
frame_W = half_W - 2 * (tick_W)
frame_H = 29 * tick_H
# Temperature Frame
self.FR_TEMP = OM.makeFrame(self.__centralwidget,
startX = half_W + tick_W,
startY = tick_H,
W = frame_W,
H = frame_H)
self.LB_TEMP_Main = OM.makeLabel(self.FR_TEMP,
frame_W/2 - 28, tick_H, 56, 12, "한글")
특징점을 찾아보자.
- OM 이라는 클래스를 만들었다. 화면을 많이 만들것인데 메소드를 중복해서 사용할 필요를 못느껴서 상위레벨로 포장한 메소드의 묶음 클래스를 만들었다.
- 크기를 절대적인 크기에서 상대적으로 바꾸었다. 레이아웃쪽을 공부하여 더 효율적인 방법을 찾아 볼 예정이다.
- Width, Height를 변수로 받는다. 취향이다.
OM
from PyQt5 import QtCore, QtWidgets
class ObjectMaker:
def __init__(self, crtWindow):
self.__crtWindow = crtWindow
self.__callNum = 0
self.__translate = QtCore.QCoreApplication.translate
def makeMainWindow(self, W, H):
mainWindow = QtWidgets.QMainWindow()
mainWindow.setObjectName(self.__crtWindow)
mainWindow.resize(W, H)
return mainWindow
def makeCentralWidget(self, location):
centralwidget = QtWidgets.QWidget(location)
centralwidget.setObjectName(self.__makeObjectName("centralwidget"))
location.setCentralWidget(centralwidget)
return centralwidget
def makeStatusBar(self, location):
statusbar = QtWidgets.QStatusBar(location)
statusbar.setObjectName(self.__makeObjectName("statusbar"))
location.setStatusBar(statusbar)
return statusbar
def makeLabel(self,location,startX,startY,W,H,text=""):
label = QtWidgets.QLabel(location)
label.setGeometry(QtCore.QRect(startX,startY,W,H))
label.setObjectName(self.__makeObjectName("label"))
label.setText(self.__translate(self.__crtWindow, text))
return label
def makeFrame(self, location, startX, startY, W, H):
frame = QtWidgets.QFrame(location)
frame.setGeometry(QtCore.QRect(startX,startY,W,H))
frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
frame.setFrameShadow(QtWidgets.QFrame.Raised)
frame.setObjectName(self.__makeObjectName("frame"))
return frame
def __callNameNum(self):
self.__callNum += 1
return (self.__callNum - 1)
def __makeObjectName(self, name):
return self.__crtWindow + name + str(self.__callNameNum)
OM의 메소드들이다. 특이점을 찾아보자.
-
__callNameNum() 과 __makeObjectName()의 존재 의미 한가지 윈도우에서는 이름이 중복되면 안된다.
따라서 고유한 넘버링을 통해 중복을 피한다.
하지만 이 때 호출하기 어려워 질 가능성이 있으니, 고려하여 사용하면 된다. -
각종 매개변수들
코드를 보면 이해가 빠를 것이라고 생각한다.
기본적으로 뼈대만 만들어두고, 호출하는 곳에서 상세 조정을 하는 것이 좋아보인다.
main
def main():
mainUi = Ui_Main(1440,900)
mainUi.startUi()
크기를 지정하고 실행하는 방식으로 구현했다.
W,H를 인자로 받아 유연하다.
다음엔 멀티스레딩을 이용한 opencv 실시간 화면 송출을 포스팅하겠다.