# PyQt widget ###### tags: `python` `pyqt` `tutorials` ## 參考 - [Qt 5.13 - QWidget](https://doc.qt.io/qt-5/qwidget.html) - [PySide2 - QWidget](https://doc.qt.io/qtforpython/PySide2/QtWidgets/QWidget.html) ## 簡介 QWidget 是一種容器,可以在放入任何要顯示的物件,比較常見的用法是放入另外設計好的ui,讓ui設計上得以切割成數個檔案。 Widget 的class以及操作韓式請自行到官方文件觀看,[PySide2 - QWidget](https://doc.qt.io/qtforpython/PySide2/QtWidgets/QWidget.html)、[Qt 5.13 - QWidget](https://doc.qt.io/qt-5/qwidget.html)。 ## 操作範例 這個操作範例會再主視窗底下切割成4個widget,並設計個別的ui檔案,放入各個widget中。 專案在 [pyqt-example](https://gitlab.com/MVMC-lab/pyqt-example)的 exp04 中,可以自行 clone 下來研究。 ### 創建 mainwindow ui 創建`ui/mainwindow.ui`,並設計成以下形式,在grid layout中放入4個`widget`元件,名子分別為`widget_1`、`widget_2`、`widget_3`、`widget_4`。  ### 創建 widget a ui 創建`ui/widget_a.ui`,在 QtCreator 創建的時候模板選擇 widget 。  接著更改 object name 為 `WidgetA`。  放入元件。  ### 創建 widget b ui 創建`ui/widget_b.ui`,在 QtCreator 創建的時候模板選擇 widget 。 接著更改 object name 為 `WidgetB`。 放入元件。  ### 轉換 .ui 成 .py ``` pyuic5 ui/mainwindow.ui -o app/ui_mainwindow.py pyuic5 ui/widget_a.ui -o app/ui_widget_a.py pyuic5 ui/widget_b.ui -o app/ui_widget_b.py ``` 可以寫進 makefile 中,之後就只用呼叫`make ui`就好,比較方便。 ```makefile .PHONY:ui ui: pyuic5 ui/mainwindow.ui -o app/ui_mainwindow.py pyuic5 ui/widget_a.ui -o app/ui_widget_a.py pyuic5 ui/widget_b.ui -o app/ui_widget_b.py ``` ### 創建物件管理 widget_a app/wa.py 新增一個 `class WidgetA_Handler` ,繼承自`Ui_WidgetA`,所以要引用`ui_widget_a.py` ```py from .ui_widget_a import Ui_WidgetA class WidgetA_Handler(Ui_WidgetA): ... ``` 目標是能在任意的widget中呈現此ui,並交由此物件管理,所以在`__init__`新增一個參數叫`widget`,在把此參數傳入`setupUi`中,如此一來,在物件的初始化時期,就會在只定的widget中初始化UI了。 ```py def __init__(self, widget): self.setupUi(widget) ``` 最後加上一點操作事件,最後`app/wa.py`的程式碼如下: ```python from .ui_widget_a import Ui_WidgetA class WidgetA_Handler(Ui_WidgetA): def __init__(self, widget): super(WidgetA_Handler, self).__init__() self.setupUi(widget) self.pushButton_1.clicked.connect(self.func1) self.pushButton_2.clicked.connect(self.func2) def func1(self): self.textBrowser.append('btn1 clicked') def func2(self): self.textBrowser.append('btn2 clicked') ``` ### 創建物件管理 widget_b app/wb.py ```python from .ui_widget_b import Ui_WidgetB class WidgetB_Handler(Ui_WidgetB): def __init__(self, widget): super(WidgetB_Handler, self).__init__() self.setupUi(widget) self.pushButton_1.clicked.connect(self.func1) self.pushButton_2.clicked.connect(self.func2) def func1(self): self.lineEdit.setText('pushButton_1') def func2(self): self.lineEdit.setText('pushButton_2') ``` ### 修改 \_\_main\_\_.py 與exp01的main大致相同。 先引用`wa.py`以及`wb.py`,裡面的class。 ```py from .wa import WidgetA_Handler from .wb import WidgetB_Handler ``` 並在`class MainWindow`中,新增`WidgetA_Handler`、`WidgetB_Handler`物件,並指定要使用哪個widget。 像w1物件的型態是`WidgetA_Handler`,並呈現在`widget_1`中。 ```python self.w1 = WidgetA_Handler(self.widget_1) self.w2 = WidgetA_Handler(self.widget_2) self.w3 = WidgetB_Handler(self.widget_3) self.w4 = WidgetB_Handler(self.widget_4) ``` 最後`app/__main__.py`的程式碼如下: ```python import sys from PyQt5.QtWidgets import QMainWindow, QApplication from .ui_mainwindow import Ui_MainWindow from .wa import WidgetA_Handler from .wb import WidgetB_Handler class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setupUi(self) self.w1 = WidgetA_Handler(self.widget_1) self.w2 = WidgetA_Handler(self.widget_2) self.w3 = WidgetB_Handler(self.widget_3) self.w4 = WidgetB_Handler(self.widget_4) self.widget_2.hide() if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` ### 執行 ``` py -m app ```  ## 總結 透過上述的方法,我們可以把一個大的程式切割成許多的ui檔,py檔,以及許多物件,讓耦合度降低,這樣在寫程式的時候可以讓自己只專注在當前的功能、物件。程式的可讀性、擴充性也會提升。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up