PySide6之初級使用


  • 背景介紹
    pyside6提供了Qt6的Python側API. 在GUI程序撰寫方面, 筆者不太喜歡頻繁的編譯過程, 傾向於隨時更改代碼即時查看效果. 因此, 推薦在簡單應用的情況下使用pyside6, 而非直接的Qt6. 本文以一個簡單的計算器實現作為案例展示筆者pyside6使用流程.
  • 使用pyside6-designer繪制並生成ui文件
    ①. 安裝pyside6
         終端運行: pip install pyside6 
    ②. 打開pyside6-designer
         終端運行: pyside6-designer 
    ③. 於pyside6-designer中利用左側控件欄繪制出如下界面

    注意, 可以在右側對象欄中改變相應控件對象的名稱.
    ④. 保存該界面為ui文件, 並命名為calculator.ui. calculator.ui文件內容如下,
      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <ui version="4.0">
      3  <class>Form</class>
      4  <widget class="QWidget" name="Form">
      5   <property name="geometry">
      6    <rect>
      7     <x>0</x>
      8     <y>0</y>
      9     <width>440</width>
     10     <height>288</height>
     11    </rect>
     12   </property>
     13   <property name="windowTitle">
     14    <string>Form</string>
     15   </property>
     16   <layout class="QVBoxLayout" name="verticalLayout">
     17    <item>
     18     <widget class="QTextBrowser" name="txtb_show"/>
     19    </item>
     20    <item>
     21     <layout class="QGridLayout" name="gridLayout">
     22      <item row="0" column="0">
     23       <widget class="QPushButton" name="btn_ac">
     24        <property name="text">
     25         <string>AC</string>
     26        </property>
     27       </widget>
     28      </item>
     29      <item row="0" column="3">
     30       <widget class="QPushButton" name="btn_divide">
     31        <property name="text">
     32         <string>÷</string>
     33        </property>
     34       </widget>
     35      </item>
     36      <item row="1" column="0">
     37       <widget class="QPushButton" name="btn_7">
     38        <property name="text">
     39         <string>7</string>
     40        </property>
     41       </widget>
     42      </item>
     43      <item row="1" column="1">
     44       <widget class="QPushButton" name="btn_8">
     45        <property name="text">
     46         <string>8</string>
     47        </property>
     48       </widget>
     49      </item>
     50      <item row="1" column="2">
     51       <widget class="QPushButton" name="btn_9">
     52        <property name="text">
     53         <string>9</string>
     54        </property>
     55       </widget>
     56      </item>
     57      <item row="1" column="3">
     58       <widget class="QPushButton" name="btn_multiply">
     59        <property name="text">
     60         <string>×</string>
     61        </property>
     62       </widget>
     63      </item>
     64      <item row="2" column="0">
     65       <widget class="QPushButton" name="btn_4">
     66        <property name="text">
     67         <string>4</string>
     68        </property>
     69       </widget>
     70      </item>
     71      <item row="2" column="1">
     72       <widget class="QPushButton" name="btn_5">
     73        <property name="text">
     74         <string>5</string>
     75        </property>
     76       </widget>
     77      </item>
     78      <item row="2" column="2">
     79       <widget class="QPushButton" name="btn_6">
     80        <property name="text">
     81         <string>6</string>
     82        </property>
     83       </widget>
     84      </item>
     85      <item row="2" column="3">
     86       <widget class="QPushButton" name="btn_subtract">
     87        <property name="text">
     88         <string></string>
     89        </property>
     90       </widget>
     91      </item>
     92      <item row="3" column="0">
     93       <widget class="QPushButton" name="btn_1">
     94        <property name="text">
     95         <string>1</string>
     96        </property>
     97       </widget>
     98      </item>
     99      <item row="3" column="1">
    100       <widget class="QPushButton" name="btn_2">
    101        <property name="text">
    102         <string>2</string>
    103        </property>
    104       </widget>
    105      </item>
    106      <item row="3" column="2">
    107       <widget class="QPushButton" name="btn_3">
    108        <property name="text">
    109         <string>3</string>
    110        </property>
    111       </widget>
    112      </item>
    113      <item row="3" column="3">
    114       <widget class="QPushButton" name="btn_add">
    115        <property name="text">
    116         <string>+</string>
    117        </property>
    118       </widget>
    119      </item>
    120      <item row="4" column="3">
    121       <widget class="QPushButton" name="btn_equal">
    122        <property name="text">
    123         <string>=</string>
    124        </property>
    125       </widget>
    126      </item>
    127      <item row="4" column="0">
    128       <widget class="QPushButton" name="btn_0">
    129        <property name="text">
    130         <string>0</string>
    131        </property>
    132       </widget>
    133      </item>
    134      <item row="4" column="1">
    135       <widget class="QPushButton" name="btn_lbracket">
    136        <property name="text">
    137         <string>(</string>
    138        </property>
    139       </widget>
    140      </item>
    141      <item row="4" column="2">
    142       <widget class="QPushButton" name="btn_rbracket">
    143        <property name="text">
    144         <string>)</string>
    145        </property>
    146       </widget>
    147      </item>
    148      <item row="0" column="2">
    149       <widget class="QPushButton" name="btn_dot">
    150        <property name="text">
    151         <string>.</string>
    152        </property>
    153       </widget>
    154      </item>
    155      <item row="0" column="1">
    156       <widget class="QPushButton" name="btn_ce">
    157        <property name="text">
    158         <string>CE</string>
    159        </property>
    160       </widget>
    161      </item>
    162     </layout>
    163    </item>
    164   </layout>
    165  </widget>
    166  <resources/>
    167  <connections/>
    168 </ui>
    View Code
  • 使用pyside6演示ui文件
    本文以一個main.py文件為例, 采用如下方式演示ui文件, 並補充其中操作邏輯. main.py文件內容如下,
     1 # 計算器實現案例
     2 
     3 from PySide6 import QtCore
     4 from PySide6 import QtWidgets
     5 from PySide6 import QtUiTools
     6 
     7 
     8 class Calculator(QtWidgets.QWidget):     # 此處繼承的類型需與designer中選擇的類型保持一致
     9 
    10     def __init__(self, parent=None):
    11         super(Calculator, self).__init__(parent)
    12 
    13         uiname = "/Users/xxhbdk/Desktop/projects_blog/pyside6/calculator.ui"  # 1. 設置ui文件路徑
    14         self.ui = QtUiTools.QUiLoader().load(uiname)  # 2. 實例化
    15         self.ui.setParent(self)                       # 3. 設置父控件
    16         self.__equal_tab = False
    17 
    18         self.__create_connections()
    19 
    20 
    21     def __create_connections(self):
    22         self.ui.btn_ac.clicked.connect(self.__print_clr_all)
    23         self.ui.btn_ce.clicked.connect(self.__print_clr_end)
    24         self.ui.btn_lbracket.clicked.connect(lambda : self.__print_line_end("("))
    25         self.ui.btn_rbracket.clicked.connect(lambda : self.__print_line_end(")"))
    26         self.ui.btn_divide.clicked.connect(lambda : self.__print_line_end("÷"))
    27         self.ui.btn_7.clicked.connect(lambda : self.__print_line_end("7"))
    28         self.ui.btn_8.clicked.connect(lambda : self.__print_line_end("8"))
    29         self.ui.btn_9.clicked.connect(lambda : self.__print_line_end("9"))
    30         self.ui.btn_multiply.clicked.connect(lambda : self.__print_line_end("×"))
    31         self.ui.btn_4.clicked.connect(lambda : self.__print_line_end("4"))
    32         self.ui.btn_5.clicked.connect(lambda : self.__print_line_end("5"))
    33         self.ui.btn_6.clicked.connect(lambda : self.__print_line_end("6"))
    34         self.ui.btn_subtract.clicked.connect(lambda : self.__print_line_end("-"))
    35         self.ui.btn_1.clicked.connect(lambda : self.__print_line_end("1"))
    36         self.ui.btn_2.clicked.connect(lambda : self.__print_line_end("2"))
    37         self.ui.btn_3.clicked.connect(lambda : self.__print_line_end("3"))
    38         self.ui.btn_add.clicked.connect(lambda : self.__print_line_end("+"))
    39         self.ui.btn_0.clicked.connect(lambda : self.__print_line_end("0"))
    40         self.ui.btn_dot.clicked.connect(lambda : self.__print_line_end("."))
    41         self.ui.btn_equal.clicked.connect(self.__equal)
    42 
    43 
    44     def __equal(self):
    45         txt =  self.ui.txtb_show.toPlainText()
    46         txt = txt.replace("×", "*")
    47         txt = txt.replace("÷", "/")
    48         try:
    49             ret = str(round(eval(txt), 9))
    50         except Exception as e:
    51             ret = str(e)
    52 
    53         self.__print_line_new(ret)
    54         self.__equal_tab = True
    55 
    56 
    57     def __print_line_end(self, msg):
    58         if self.__equal_tab:
    59             self.__print_clr_all()
    60             self.__equal_tab = False
    61         self.ui.txtb_show.insertPlainText(msg)
    62 
    63 
    64     def __print_clr_all(self):
    65         self.ui.txtb_show.clear()
    66 
    67 
    68     def __print_clr_end(self):
    69         self.ui.txtb_show.textCursor().deletePreviousChar()
    70 
    71 
    72     def __print_line_new(self, msg):
    73         self.ui.txtb_show.append(msg)
    74         
    75         
    76 
    77 if __name__ == "__main__":
    78     app = QtWidgets.QApplication([])
    79 
    80     obj = Calculator()
    81     obj.show()
    82 
    83     app.exec()
    View Code
    可見, ui文件的引入步驟如下,
    ①. 設置ui文件路徑
    ②. 實例化
    ③. 設置父控件
    執行上述main.py, 演示界面如下,
  • 使用pyside6-uic翻譯ui文件為py文件
    於終端運行如下命令翻譯ui文件, 並生成同名py文件,
    pyside6-uic ./calculator.ui -o ./calculator.py 
    其中, calculator.ui需要提供正確的路徑, calculator.py為翻譯后的py文件. calculator.py文件內容如下,
      1 # -*- coding: utf-8 -*-
      2 
      3 ################################################################################
      4 ## Form generated from reading UI file 'calculator.ui'
      5 ##
      6 ## Created by: Qt User Interface Compiler version 6.2.2
      7 ##
      8 ## WARNING! All changes made in this file will be lost when recompiling UI file!
      9 ################################################################################
     10 
     11 from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
     12     QMetaObject, QObject, QPoint, QRect,
     13     QSize, QTime, QUrl, Qt)
     14 from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
     15     QFont, QFontDatabase, QGradient, QIcon,
     16     QImage, QKeySequence, QLinearGradient, QPainter,
     17     QPalette, QPixmap, QRadialGradient, QTransform)
     18 from PySide6.QtWidgets import (QApplication, QGridLayout, QPushButton, QSizePolicy,
     19     QTextBrowser, QVBoxLayout, QWidget)
     20 
     21 class Ui_Form(object):
     22     def setupUi(self, Form):
     23         if not Form.objectName():
     24             Form.setObjectName(u"Form")
     25         Form.resize(440, 288)
     26         self.verticalLayout = QVBoxLayout(Form)
     27         self.verticalLayout.setObjectName(u"verticalLayout")
     28         self.txtb_show = QTextBrowser(Form)
     29         self.txtb_show.setObjectName(u"txtb_show")
     30 
     31         self.verticalLayout.addWidget(self.txtb_show)
     32 
     33         self.gridLayout = QGridLayout()
     34         self.gridLayout.setObjectName(u"gridLayout")
     35         self.btn_ac = QPushButton(Form)
     36         self.btn_ac.setObjectName(u"btn_ac")
     37 
     38         self.gridLayout.addWidget(self.btn_ac, 0, 0, 1, 1)
     39 
     40         self.btn_divide = QPushButton(Form)
     41         self.btn_divide.setObjectName(u"btn_divide")
     42 
     43         self.gridLayout.addWidget(self.btn_divide, 0, 3, 1, 1)
     44 
     45         self.btn_7 = QPushButton(Form)
     46         self.btn_7.setObjectName(u"btn_7")
     47 
     48         self.gridLayout.addWidget(self.btn_7, 1, 0, 1, 1)
     49 
     50         self.btn_8 = QPushButton(Form)
     51         self.btn_8.setObjectName(u"btn_8")
     52 
     53         self.gridLayout.addWidget(self.btn_8, 1, 1, 1, 1)
     54 
     55         self.btn_9 = QPushButton(Form)
     56         self.btn_9.setObjectName(u"btn_9")
     57 
     58         self.gridLayout.addWidget(self.btn_9, 1, 2, 1, 1)
     59 
     60         self.btn_multiply = QPushButton(Form)
     61         self.btn_multiply.setObjectName(u"btn_multiply")
     62 
     63         self.gridLayout.addWidget(self.btn_multiply, 1, 3, 1, 1)
     64 
     65         self.btn_4 = QPushButton(Form)
     66         self.btn_4.setObjectName(u"btn_4")
     67 
     68         self.gridLayout.addWidget(self.btn_4, 2, 0, 1, 1)
     69 
     70         self.btn_5 = QPushButton(Form)
     71         self.btn_5.setObjectName(u"btn_5")
     72 
     73         self.gridLayout.addWidget(self.btn_5, 2, 1, 1, 1)
     74 
     75         self.btn_6 = QPushButton(Form)
     76         self.btn_6.setObjectName(u"btn_6")
     77 
     78         self.gridLayout.addWidget(self.btn_6, 2, 2, 1, 1)
     79 
     80         self.btn_subtract = QPushButton(Form)
     81         self.btn_subtract.setObjectName(u"btn_subtract")
     82 
     83         self.gridLayout.addWidget(self.btn_subtract, 2, 3, 1, 1)
     84 
     85         self.btn_1 = QPushButton(Form)
     86         self.btn_1.setObjectName(u"btn_1")
     87 
     88         self.gridLayout.addWidget(self.btn_1, 3, 0, 1, 1)
     89 
     90         self.btn_2 = QPushButton(Form)
     91         self.btn_2.setObjectName(u"btn_2")
     92 
     93         self.gridLayout.addWidget(self.btn_2, 3, 1, 1, 1)
     94 
     95         self.btn_3 = QPushButton(Form)
     96         self.btn_3.setObjectName(u"btn_3")
     97 
     98         self.gridLayout.addWidget(self.btn_3, 3, 2, 1, 1)
     99 
    100         self.btn_add = QPushButton(Form)
    101         self.btn_add.setObjectName(u"btn_add")
    102 
    103         self.gridLayout.addWidget(self.btn_add, 3, 3, 1, 1)
    104 
    105         self.btn_equal = QPushButton(Form)
    106         self.btn_equal.setObjectName(u"btn_equal")
    107 
    108         self.gridLayout.addWidget(self.btn_equal, 4, 3, 1, 1)
    109 
    110         self.btn_0 = QPushButton(Form)
    111         self.btn_0.setObjectName(u"btn_0")
    112 
    113         self.gridLayout.addWidget(self.btn_0, 4, 0, 1, 1)
    114 
    115         self.btn_lbracket = QPushButton(Form)
    116         self.btn_lbracket.setObjectName(u"btn_lbracket")
    117 
    118         self.gridLayout.addWidget(self.btn_lbracket, 4, 1, 1, 1)
    119 
    120         self.btn_rbracket = QPushButton(Form)
    121         self.btn_rbracket.setObjectName(u"btn_rbracket")
    122 
    123         self.gridLayout.addWidget(self.btn_rbracket, 4, 2, 1, 1)
    124 
    125         self.btn_dot = QPushButton(Form)
    126         self.btn_dot.setObjectName(u"btn_dot")
    127 
    128         self.gridLayout.addWidget(self.btn_dot, 0, 2, 1, 1)
    129 
    130         self.btn_ce = QPushButton(Form)
    131         self.btn_ce.setObjectName(u"btn_ce")
    132 
    133         self.gridLayout.addWidget(self.btn_ce, 0, 1, 1, 1)
    134 
    135 
    136         self.verticalLayout.addLayout(self.gridLayout)
    137 
    138 
    139         self.retranslateUi(Form)
    140 
    141         QMetaObject.connectSlotsByName(Form)
    142     # setupUi
    143 
    144     def retranslateUi(self, Form):
    145         Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
    146         self.btn_ac.setText(QCoreApplication.translate("Form", u"AC", None))
    147         self.btn_divide.setText(QCoreApplication.translate("Form", u"\u00f7", None))
    148         self.btn_7.setText(QCoreApplication.translate("Form", u"7", None))
    149         self.btn_8.setText(QCoreApplication.translate("Form", u"8", None))
    150         self.btn_9.setText(QCoreApplication.translate("Form", u"9", None))
    151         self.btn_multiply.setText(QCoreApplication.translate("Form", u"\u00d7", None))
    152         self.btn_4.setText(QCoreApplication.translate("Form", u"4", None))
    153         self.btn_5.setText(QCoreApplication.translate("Form", u"5", None))
    154         self.btn_6.setText(QCoreApplication.translate("Form", u"6", None))
    155         self.btn_subtract.setText(QCoreApplication.translate("Form", u"\u2212", None))
    156         self.btn_1.setText(QCoreApplication.translate("Form", u"1", None))
    157         self.btn_2.setText(QCoreApplication.translate("Form", u"2", None))
    158         self.btn_3.setText(QCoreApplication.translate("Form", u"3", None))
    159         self.btn_add.setText(QCoreApplication.translate("Form", u"+", None))
    160         self.btn_equal.setText(QCoreApplication.translate("Form", u"=", None))
    161         self.btn_0.setText(QCoreApplication.translate("Form", u"0", None))
    162         self.btn_lbracket.setText(QCoreApplication.translate("Form", u"(", None))
    163         self.btn_rbracket.setText(QCoreApplication.translate("Form", u")", None))
    164         self.btn_dot.setText(QCoreApplication.translate("Form", u".", None))
    165         self.btn_ce.setText(QCoreApplication.translate("Form", u"CE", None))
    166     # retranslateUi
    View Code
  • 使用pyside6演示py文件
    同樣以一個main.py文件為例, 展示如何引入翻譯后的calculator.py, 並演示之.
    當前工程結構如下,

    main.py文件內容如下,
     1 # 計算器實現案例
     2 
     3 from PySide6 import QtCore
     4 from PySide6 import QtWidgets
     5 from PySide6 import QtUiTools
     6 import argparse                  # 0. 額外導入, 暫時無需關注
     7 
     8 from calculator import Ui_Form   # 1. 引入calculator模塊
     9 
    10 
    11 class Calculator(QtWidgets.QWidget):     # 此處繼承的類型需與designer中選擇的類型保持一致
    12 
    13     def __init__(self, parent=None):
    14         super(Calculator, self).__init__(parent)
    15 
    16         # uiname = "/Users/xxhbdk/Desktop/projects_blog/pyside6/calculator.ui"  # ui文件路徑
    17         # self.ui = QtUiTools.QUiLoader().load(uiname)
    18         # self.ui.setParent(self)
    19         self.ui = Ui_Form()      # 2. 實例化
    20         self.ui.setupUi(self)    # 3. 設置父控件
    21         self.__equal_tab = False
    22 
    23         self.__create_connections()
    24 
    25 
    26     def __create_connections(self):
    27         self.ui.btn_ac.clicked.connect(self.__print_clr_all)
    28         self.ui.btn_ce.clicked.connect(self.__print_clr_end)
    29         self.ui.btn_lbracket.clicked.connect(lambda : self.__print_line_end("("))
    30         self.ui.btn_rbracket.clicked.connect(lambda : self.__print_line_end(")"))
    31         self.ui.btn_divide.clicked.connect(lambda : self.__print_line_end("÷"))
    32         self.ui.btn_7.clicked.connect(lambda : self.__print_line_end("7"))
    33         self.ui.btn_8.clicked.connect(lambda : self.__print_line_end("8"))
    34         self.ui.btn_9.clicked.connect(lambda : self.__print_line_end("9"))
    35         self.ui.btn_multiply.clicked.connect(lambda : self.__print_line_end("×"))
    36         self.ui.btn_4.clicked.connect(lambda : self.__print_line_end("4"))
    37         self.ui.btn_5.clicked.connect(lambda : self.__print_line_end("5"))
    38         self.ui.btn_6.clicked.connect(lambda : self.__print_line_end("6"))
    39         self.ui.btn_subtract.clicked.connect(lambda : self.__print_line_end("-"))
    40         self.ui.btn_1.clicked.connect(lambda : self.__print_line_end("1"))
    41         self.ui.btn_2.clicked.connect(lambda : self.__print_line_end("2"))
    42         self.ui.btn_3.clicked.connect(lambda : self.__print_line_end("3"))
    43         self.ui.btn_add.clicked.connect(lambda : self.__print_line_end("+"))
    44         self.ui.btn_0.clicked.connect(lambda : self.__print_line_end("0"))
    45         self.ui.btn_dot.clicked.connect(lambda : self.__print_line_end("."))
    46         self.ui.btn_equal.clicked.connect(self.__equal)
    47 
    48 
    49     def __equal(self):
    50         txt =  self.ui.txtb_show.toPlainText()
    51         txt = txt.replace("×", "*")
    52         txt = txt.replace("÷", "/")
    53         try:
    54             ret = str(round(eval(txt), 9))
    55         except Exception as e:
    56             ret = str(e)
    57 
    58         self.__print_line_new(ret)
    59         self.__equal_tab = True
    60 
    61 
    62     def __print_line_end(self, msg):
    63         if self.__equal_tab:
    64             self.__print_clr_all()
    65             self.__equal_tab = False
    66         self.ui.txtb_show.insertPlainText(msg)
    67 
    68 
    69     def __print_clr_all(self):
    70         self.ui.txtb_show.clear()
    71 
    72 
    73     def __print_clr_end(self):
    74         self.ui.txtb_show.textCursor().deletePreviousChar()
    75 
    76 
    77     def __print_line_new(self, msg):
    78         self.ui.txtb_show.append(msg)
    79         
    80         
    81 
    82 if __name__ == "__main__":
    83     app = QtWidgets.QApplication([])
    84 
    85     obj = Calculator()
    86     obj.show()
    87 
    88     app.exec()
    View Code
    可見, 主要是將ui文件的引入步驟替換如下:
    ①. 引入翻譯后的py文件模塊
    ②. 實例化
    ③. 設置父控件
    執行上述main.py, 演示界面如下,
  • 使用nuitka工具打包為獨立app
    ①. 安裝nuitka
         終端運行: pip3 install nuitka 
    ②. 將當前工程打包為獨立app
         終端運行: nuitka3 --onefile --macos-disable-console --enable-plugin=pyside6 main.py -o calculator.app 
    打包完成后, 於當前目錄下生成可執行文件"calculator.app". 雙擊該可執行文件, 運行效果如下,

    可以看到, 可執行文件運行符合預期.
  • 注意事項
    ①. macos下python部分模塊導入可能存在問題, 終端運行app發現后, 可手動在py文件中額外導入, 如筆者手動額外導入的argparse模塊;
    ②. macos下nuitka最終輸出文件之后綴".app"需手動添加, 如不添加, 則運行帶有終端;
    ③. 本文着重闡述pyside6配合nuitka之使用流程, 具體API使用細節, 請大家參考官方文檔等資料.
  • 參考文檔
    ①. https://doc.qt.io/qtforpython/contents.html
    ②. https://nuitka.net/doc/user-manual.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM