Life Seed

[Pyside6] Using .ui files from Designer 본문

Python/GUI - Qt for Python(Pyside6)

[Pyside6] Using .ui files from Designer

lifeseed 2025. 7. 2. 00:49

https://doc.qt.io/qtforpython-6/index.html 사이트의 Tutorial에 대한 내용을 정리입니다.

Tutorials 를 클릭하여 확인할 수 있습니다.

 

https://doc.qt.io/qtforpython-6/tutorials/index.html

 

이 번 예제에서는 QtDesigner를 통해 만든 ui 파일을 이용하여 GUI를 표현하는 두가지 방법에 대해 살펴볼 것입니다.

첫번째는  pyside6-uic를 이용하여 ui파일을 py로 변환한 후 GUI를 표현하는 방법이며, 

또 다른 한가지는 QUiLoader를 이용하여 ui파일을 direct로 읽어서 GUI를 표현하는 방법입니다.

 

QT Designer로 구성한 화면입니다.

mainwindow.ui 파일로 저장되며 다음과 같은 xml 코드를 가집니다. (QtDesigner가 생성한 코드)

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QPushButton" name="pushButton">
    <property name="geometry">
     <rect>
      <x>260</x>
      <y>200</y>
      <width>191</width>
      <height>101</height>
     </rect>
    </property>
    <property name="text">
     <string>PushButton</string>
    </property>
   </widget>
   <widget class="QPushButton" name="pushButton2">
    <property name="geometry">
     <rect>
      <x>260</x>
      <y>120</y>
      <width>191</width>
      <height>61</height>
     </rect>
    </property>
    <property name="text">
     <string>PushButton</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>33</height>
    </rect>
   </property>
  </widget>
 <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

 

pyside6-uic mainwindow.ui -o mainwindow_ui.py

명령을 수행하면 다음과 같은 mainwindow_ui.py파일이 생성됩니다. (코딩하는 것이 아님)

# -*- coding: utf-8 -*-

################################################################################
## Form generated from reading UI file 'mainwindow.ui'
##
## Created by: Qt User Interface Compiler version 6.7.3
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################

from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
    QMetaObject, QObject, QPoint, QRect,
    QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
    QFont, QFontDatabase, QGradient, QIcon,
    QImage, QKeySequence, QLinearGradient, QPainter,
    QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QMainWindow, QMenuBar, QPushButton,
    QSizePolicy, QStatusBar, QWidget)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(u"centralwidget")
        self.pushButton = QPushButton(self.centralwidget)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setGeometry(QRect(260, 200, 191, 101))
        self.pushButton2 = QPushButton(self.centralwidget)
        self.pushButton2.setObjectName(u"pushButton2")
        self.pushButton2.setGeometry(QRect(260, 120, 191, 61))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 800, 33))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)

        QMetaObject.connectSlotsByName(MainWindow)
    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))
        self.pushButton.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
        self.pushButton2.setText(QCoreApplication.translate("MainWindow", u"PushButton", None))
    # retranslateUi

 

1. pyside6-uic를 이용한 ui.py 파일을 이용하는 경우

import sys
from PySide6.QtWidgets import QApplication, QMainWindow
from mainwindow_ui import Ui_MainWindow

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.on_button_clicked)
    def on_button_clicked(self):
        print("Button clicked!")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

 

1) from mainwindow_ui import Ui_MainWinodw

QtDesigner에서 생성한 UI 파일을 변환한 ui.py파일을 import한다. 

 

2) UI 설정

self.ui = Ui_MainWindow()

self.ui.setupUi(self)

구문을 통하여 ui 를 가져온다.

QtDesigner에서 구현한 Widget등을 self.ui. 선언을 통해 가져올 수 있따.

 

 

2. QUiLoader를 이용하는 경우

import sys
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QMainWindow, QApplication, QPushButton
from PySide6.QtCore import QFile, QIODevice

class MainWindow(QMainWindow):
    def load_ui_file(self, ui_file_name):
        loader = QUiLoader()
        ui_file = QFile(ui_file_name)
        if not ui_file.open(QIODevice.ReadOnly):
            print(f"Cannot open {ui_file_name}: {ui_file.errorString()}")
            sys.exit(-1)

        self.window = loader.load(ui_file)
        ui_file.close()

    def __init__(self):
        super(MainWindow, self).__init__()
        # Load the UI file
        ui_file_name = './mainwindow.ui'
        self.load_ui_file(ui_file_name)

        if not self.window:
            print("Failed to load UI file.")
            sys.exit(-1)

        pushBtn = self.window.findChild(QPushButton, "pushButton")
        if pushBtn:
            pushBtn.setText("Click Me")
            pushBtn.setToolTip("Click this button to perform an action")
            pushBtn.clicked.connect(self.on_pushButton_clicked)

        self.window.setWindowTitle("Main Window")
        self.window.setGeometry(100, 100, 800, 600)

    def on_pushButton_clicked(self):
        print("Button clicked!")
        # Add your button click logic here


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    if not window:
        print("Failed to create main window.")
        sys.exit(-1)

    window.window.show()
    sys.exit(app.exec())

 

1) from PySide6.QtUiTools import QUiLoader

QUiLoader를 사용하기 위해 import 되어야 한다.

 

2) load_ui_file 함수

def load_ui_file(self, ui_file_name):
    loader = QUiLoader()
    ui_file = QFile(ui_file_name)
    if not ui_file.open(QIODevice.ReadOnly):
        print(f"Cannot open {ui_file_name}: {ui_file.errorString()}")
        sys.exit(-1)
    self.window = loader.load(ui_file)
    ui_file.close()

 

QUiLoader를 이용하여 mainwindow.ui 파일에서 Ui정보를 self.window로 가져온다.

 

3) Widget 가져오기

pushBtn = self.window.findChild(QPushButton, "pushButton")
if pushBtn:
    pushBtn.setText("Click Me")
    ...

 

findChild를 이용하여 QtDesigner에서 구현된 Widget 정보를 가져온다.

이후 사용법은 동일하다.

 

3. pyside6-uic  or QUiLoader

ui 파일을 자주 변경해야 할 경우 당연 QUiLoader를 이용하는 것이 편리할 듯 하지만....

우선 widget 정보를 가져오는 코드의 길이가 만만치 않다.

또한 ui파일을 따로 배포해야하는 불편함도....

 

pyside6-uic를 이용해 변환한 후 사용하는 것의 불편함은... 말그대로 ui를 수정해야 할 때마다 변환해야 한다는 것인데....

그 불편함을 Visual Studio Code의 Extension중 하나인 Qt for Python이 한방에 해결 해 준다.

이 Extension을 설치하면 ui파일에 마우스 오른쪽 클릭시 관련 메뉴들이 추가된다.

 

Edit Qt UI File을 이용하여 designer를 바로 호출 할 수 있으며, 

Compile Qt UI File 메뉴를 이용하여 uic 변환을 바로 할 수 있다.

 

그러나 Compile Qt UI File을 사용하지 않아도, Designer에서 ui파일을 저장을 하면 자동으로 uic 변환을 해준다.

개인적으로는 굳이 QUiLoader를 사용할 필요가 있을까 싶긴 하지만...

 

위 예제를 기본으로 필요한 대로 확장해서 사용하면 될듯...

 

 

반응형