#PYTHON3 #QT #PYSISE2 #TUTORIAL #PYQT5

PySide #19: 世上唯一不變的就是變!PySide to PyQt

成也支援度,敗也支援度

DekBan
Bucketing

--

Photo by Mathew Schwartz on Unsplash

久違的Qt系列其實已倒尾聲,這幾年不知道大家的PySide2使用的如何,這一系列的文章又帶給大家多少學習成長呢? 時間不斷流逝,技術也與時俱進,Qt6已經出來,而PySide2對python的支援卻敲然生變。

本期,就讓我們來說說,作者是什麼原因被迫從PySide2轉而使用PyQt5,有同樣問題的讀者們又該怎麼樣去調整原有的程式碼。

❔Why PyQt5

對於這個系列的讀者們應該有看過本系列的第一篇文章,PySide #1: Python GUI開發,簡介 & 環境安裝,其中提到了PySide2的官方支援以及文件都相對地齊全,因次選擇了使用PySide2來做開發,實務上作者也是如此。
可惜,PySide2在Python3.10以後的支援卻跟不上了,無法支援最新的Python 3.11 以及更新的版本,而在Linux上原生支援的library,也不是PySide2而是開源的PyQt5。

種種原因下,以及開發的方便程度導致作者開始思考轉而使用PyQt5的可行性,研究後發現原來非常簡單!各位讀者完全不用擔心轉換的痛苦與不適!

PySide2 to PyQt5

從以往的教學原始碼來說,會需要修改的部分主要有3個部分。

  • 標頭替換
  • QUILoader 的修改
  • Signal / Slot 的宣告

除此之外,只需要簡單的替換PySide2到PyQt5就完成囉!

Install PyQt5

要將代碼中的Pyside2 package替換成PyQt,第一件事自然是安裝PyQt5啦!

# install Qt5 with pip
pip install PyQt5

# Or you want to use Qt6
pip install PyQt6

目前的Qt6尚不普及,許多Linux的環境都是以PyQt5為預設的library,因此作者會盡量使用Qt5作為開發工具。

1️⃣Transfer Import Package

接下來我們要來轉換原始碼中import的標頭檔,這部分也是大家會擔心的一部份,但事實上,PySide2與PyQt的Class、method、attribute幾乎是95%一模一樣,所以我們要做的就是將PySide2的前綴給替換掉。

from PySide2.QtWidgets import QButtonGroup

↓↓↓↓↓↓

from PyQt5.QtWidgets import QButtonGroup

這樣就大功告成了!其他程式碼全都不用修改唷,是不是超級簡單呢?!

2️⃣QUILoader

QUILoader是不存在於PyQt5中的,所以我們需要用其他的方法去讀取ui檔,才能對使用者介面做操作以及修改,PyQt5中有相同功能的class叫做uic。
而我們要做的就是用uic來代替QUILoader。

# Original Src
from PySide2.QtUiTools import QUiLoader

def setup_ui(self):
"""Initialize and setup user interface"""
loader = QUiLoader()
file = QFile('./user_interface/form/main_window.ui')
file.open(QFile.ReadOnly)
self._window = loader.load(file)
file.close()

↓↓↓↓↓↓

# Using PyQt5 uic
from PyQt5 import uic

def ui_setup(self):
"""Initialize user interface of main window."""
loader = uic.loadUi('./user_interface/form/main_window.ui')
self._window = loader

相比之下,大家會發現,PyQt5的uic使用起來還更加簡單呢!

3️⃣Signal / Slot

Signal / Slot的宣告方法,在PySide #5中有詳細的教學,然而在PyQt5中Signal / Slot的宣告方式變得有些不一樣。

# Origin
from PySide2.QtCore import Signal

hello_signal = Signal(str)

self.hello_signal.connect(self.say_hello)
self.hello_signal.emit('Pyside2!')

@QtCore.Slot(str)
def say_hello(self, msg):
print('Hello ' + msg)

↓↓↓↓↓↓

# PyQt5 Signal / Slot
from PyQt5.QtCore import pyqtSignal

hello_signal = pyqtSignal(str)

self.hello_signal.connect(self.say_hello)
self.hello_signal.emit('Pyside2!')

@QtCore.pyqtSlot(str) # This is Optional, actually it's not necessary
def say_hello(self, msg):
print('Hello ' + msg)

將signal的宣告修改為PyQt下的函數,同時修改Slot的decorator就可以完成轉換啦,實際上,PyQt的Slot可以不需要decorator,即使是使用一般的函數,也可以正常的連結與執行唷!

Source Code

完整代碼請看 :無

結論

這次是分享在實務開發上遇到的一些問題以及轉變,程式不斷的在進步代碼也需要持續修正,希望大家也能在這次的分享中學習到新的用法,與此同時,本系列的教學也終於能夠同時滿足PySide2以及PyQt5兩邊的使用者了!(灑花

我是夜海中的宅男DekBan,我們下次見,see ya next night.

--

--

DekBan
Bucketing

เด็กบ้าน | 🌃夜裡溜搭的宅男,漂泊於月色鋪成的海