# 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
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.