离线
PySide2 ---- 之所以称为PySide,是因为“ side”是芬兰语中的“ binder”, 也就是"绑定"
离线
这两个软件包都包装了相同的库Qt5,因此具有99.9%相同的API(请参见下面的一些区别)。为一个编写的代码通常可以与其他代码原样使用,只需将导入从更改为PyQt5即可PySide2。您从一个库中学到的任何内容都可以轻松地应用到另一个库中的项目。
离线
另外,无论您选择使用哪种,都应该熟悉另一种,因此您可以充分利用所有可用的在线资源,例如使用PyQt5教程来构建PySide2应用程序,反之亦然。
离线
UI files
Both packages use slightly different approaches for loading .ui files exported from Qt Creator/Designer. PyQt5 provides the uic submodule which can be used to load UI files directly, to produce an object. This feels pretty Pythonic (if you ignore the camelCase).
import sys
from PyQt5 import QtWidgets, uic
app = QtWidgets.QApplication(sys.argv)
window = uic.loadUi("mainwindow.ui")
window.show()
app.exec()
The equivalent with PySide2 is one line longer, since you need to create a QUILoader object first. Unfortunately the api of these two interfaces is different too (.load vs .loadUI) and take different parameters.
import sys
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtUiTools import QUiLoader
loader = QUiLoader()
app = QtWidgets.QApplication(sys.argv)
window = loader.load("mainwindow.ui", None)
window.show()
app.exec_()
To load a UI onto an object in PyQt5, for example in your QMainWindow.__init__, you can call uic.loadUI passing in self (the target widget) as the second parameter.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import uic
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
uic.loadUi("mainwindow.ui", self)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
The PySide2 loader does not support this — the second parameter to .load is the parent widget of the widget you're creating. This prevents you adding custom code to the __init__ block of the widget, but you can work around this with a separate function.
import sys
from PySide2 import QtWidgets
from PySide2.QtUiTools import QUiLoader
loader = QUiLoader()
def mainwindow_setup(w):
w.setTitle("MainWindow Title")
app = QtWidgets.QApplication(sys.argv)
window = loader.load("mainwindow.ui", None)
mainwindow_setup(window)
window.show()
app.exec()
Converting UI files to Python
Both libraries provide identical scripts to generate Python importable modules from Qt Designer .ui files. For PyQt5 the script is named pyuic5 —
pyuic5 mainwindow.ui -o MainWindow.py
You can then import the UI_MainWindow object, subclass using multiple inheritance from the base class you're using (e.g. QMainWIndow) and then call self.setupUI(self) to set the UI up.
import sys
from PyQt5 import QtWidgets
from MainWindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setupUi(self)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
For PySide2 it is named pyside2-uic —
pyside2-uic mainwindow.ui -o MainWindow.py
The subsequent setup is identical.
import sys
from PySide2 import QtWidgets
from MainWindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setupUi(self)
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
For more information on using Qt Designer with either PyQt5 or PySide2 see the Qt Creator tutorial.
PyQt5 与 PySide2 加载 .ui 界面文件的差异.
离线
Supporting both in libraries
You don't need to worry about this if you're writing a standalone app, just use whichever API you prefer.If you're writing a library, widget or other tool you want to be compatible with both PyQt5 and PySide2 you can do so easily by adding both sets of imports.
import sys
if 'PyQt5' in sys.modules:
# PyQt5
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slotelse:
# PySide2
from PySide2 import QtGui, QtWidgets, QtCore
from PySide2.QtCore import Signal, Slot
测试了一下:
import sys
if 'PySide' in sys.modules:
# PySide2
print("import PySide2")
from PySide2.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PySide2.QtCore import Signal, Slot
else:
# PyQt5
print("import PyQt5")
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot
if __name__ == '__main__':
app = QApplication(sys.argv)
mainwindow1 = QDialog()
label = QLabel("显示测试")
button = QPushButton("请点击我噢")
boxlayout1 = QVBoxLayout()
boxlayout1.addWidget(label)
boxlayout1.addWidget(button)
mainwindow1.setLayout(boxlayout1)
mainwindow1.show()
mainwindow1.setWindowTitle("测试标题")
mainwindow1.resize(80, 150)
sys.exit(app.exec_())
完全没有问题,随心所欲, 喜欢import哪个库都可以了.
离线
import sys, os
#os.environ["QT_BINDING"] = "PyQt5"
os.environ["QT_BINDING"] = "PySide2"
if os.environ["QT_BINDING"] == "PyQt5": ###'PyQt5.Widgets' in sys.modules:
print("import PyQt5")
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot
from PyQt5 import uic
elif os.environ["QT_BINDING"] == "PySide2":
print("import PySide2")
from PySide2.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PySide2.QtCore import Signal, Slot
from PySide2.QtUiTools import QUiLoader
if __name__ == '__main__':
app = QApplication(sys.argv)
if os.environ["QT_BINDING"] == "PyQt5":
window = uic.loadUi("mainwindow.ui")
elif os.environ["QT_BINDING"] == "PySide2":
uiloader = QUiLoader()
window = uiloader.load("mainwindow.ui")
window.show()
sys.exit(app.exec_())
现学现用, 通过设置环境变量 QT_BINDING 来决定import PySide2, 还是 import PyQt5
离线
import sys, os
#os.environ["QT_BINDING"] = "PyQt5"
os.environ["QT_BINDING"] = "PySide2"
if os.environ["QT_BINDING"] == "PyQt5": ###'PyQt5.Widgets' in sys.modules:
print("import PyQt5")
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot, QTimer
from PyQt5 import uic
elif os.environ["QT_BINDING"] == "PySide2":
print("import PySide2")
from PySide2.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PySide2.QtCore import Signal, Slot, QTimer
from PySide2.QtUiTools import QUiLoader
@Slot()
def SlotTimeOut():
print("超时 timout")
if __name__ == '__main__':
app = QApplication(sys.argv)
if os.environ["QT_BINDING"] == "PyQt5":
window = uic.loadUi("mainwindow.ui")
elif os.environ["QT_BINDING"] == "PySide2":
uiloader = QUiLoader()
window = uiloader.load("mainwindow.ui")
a = 0
timer1 = QTimer()
timer1.timeout.connect(SlotTimeOut)
timer1.start(1000)
window.show()
sys.exit(app.exec_())
添加了一个槽函数, PyQt5/PySide2 测试均 OK
离线
import sys, os
os.environ["QT_BINDING"] = "PyQt5"
# os.environ["QT_BINDING"] = "PySide2"
if os.environ["QT_BINDING"] == "PyQt5": ###'PyQt5.Widgets' in sys.modules:
print("import PyQt5")
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot, QTimer
from PyQt5 import uic
elif os.environ["QT_BINDING"] == "PySide2":
print("import PySide2")
from PySide2.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PySide2.QtCore import Signal, Slot, QTimer
from PySide2.QtUiTools import QUiLoader
@Slot(int)
def SlotTimeOut(i):
print("定时器" + str(i) + "超时 timout: ")
if __name__ == '__main__':
app = QApplication(sys.argv)
if os.environ["QT_BINDING"] == "PyQt5":
window = uic.loadUi("mainwindow.ui")
elif os.environ["QT_BINDING"] == "PySide2":
uiloader = QUiLoader()
window = uiloader.load("mainwindow.ui")
a = 0
timer1 = QTimer()
timer1.timeout.connect(lambda: SlotTimeOut(1))
timer1.start(1000)
timer2 = QTimer()
timer2.timeout.connect(lambda: SlotTimeOut(2))
timer2.start(3005)
window.show()
sys.exit(app.exec_())
槽函数加了一个签名, 用了 lambda 表达式.
输出:
import PyQt5
定时器1超时 timout:
定时器1超时 timout:
定时器1超时 timout:
定时器2超时 timout:
定时器1超时 timout:
定时器1超时 timout:
定时器1超时 timout:
定时器2超时 timout:
定时器1超时 timout:
离线
import sys, os
os.environ["QT_BINDING"] = "PyQt5"
# os.environ["QT_BINDING"] = "PySide2"
if os.environ["QT_BINDING"] == "PyQt5": ###'PyQt5.Widgets' in sys.modules:
print("import PyQt5")
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PyQt5.QtCore import pyqtSignal as Signal, pyqtSlot as Slot, QTimer
from PyQt5 import uic
elif os.environ["QT_BINDING"] == "PySide2":
print("import PySide2")
from PySide2.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QVBoxLayout, QDialog
from PySide2.QtCore import Signal, Slot, QTimer
from PySide2.QtUiTools import QUiLoader
@Slot(int)
def SlotTimeOut(i):
print("定时器" + str(i) + "超时 timout: ")
@Slot(bool)
def SlotDelButtonClicked(checked):
print("按钮被选中? " + str(checked))
if __name__ == '__main__':
app = QApplication(sys.argv)
if os.environ["QT_BINDING"] == "PyQt5":
window = uic.loadUi("mainwindow.ui")
elif os.environ["QT_BINDING"] == "PySide2":
uiloader = QUiLoader()
window = uiloader.load("mainwindow.ui")
a = 0
timer1 = QTimer()
timer1.timeout.connect(lambda: SlotTimeOut(1))
timer1.start(1000)
timer2 = QTimer()
timer2.timeout.connect(lambda: SlotTimeOut(2))
timer2.start(3005)
window.startStopButton.clicked.connect(lambda: SlotTimeOut(3))
window.DelPointButton.setCheckable(True)
# window.DelPointButton.setChecked(True)
window.DelPointButton.clicked.connect(SlotDelButtonClicked)
window.show()
sys.exit(app.exec_())
再添加一个按钮点击的槽函数.
离线