QT for Python 6.1.2
写在前面
pyside6
遵循 LGPL
/ GPL
的开源协议。官网
本笔记只为记录本人的学习状态,不做其他用途。
安装/更新/VSCode插件
安装:python -m pip install pyside6
更新:python -m pip install --upgrade pyside6
安装 Visual Studio Code 插件:(Ctrl
+P
)-> ext install seanwu.vscode-qt-for-python
窗口
基本窗口
import sys
from PySide6 import QtCore, QtWidgets
from PySide6.QtWidgets import QLabel
class DemoWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.label = QLabel("Hello World", alignment=QtCore.Qt.AlignCenter)
self.layout = QtWidgets.QVBoxLayout(self) # 窗口布局
self.layout.addWidget(self.label) # 控件绑定到布局中
self.setLayout(self.layout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = DemoWidget()
widget.resize(200, 150)
widget.show()
sys.exit(app.exec())
对话框
import sys
from PySide6 import QtWidgets
class DemoDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(DemoDialog, self).__init__(parent)
self.setWindowTitle("对话框")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = DemoDialog()
dialog.show()
sys.exit(app.exec())
布局
垂直布局
from PySide6 import QtWidgets
layout = QtWidgets.QVBoxLayout(self) # 窗口布局
# 顺序添加
layout.addWidget(obj1)
layout.addWidget(obj2)
# 比例添加( obj1 和 obj2 将以 1:2 的比例,划分所有的垂直区域)
layout.addWidget(obj1, 1)
layout.addWidget(obj2, 2)
'''最后记得绑定到主窗口
self 表示 继承 QWidget 的类对象
'''
self.setLayout(layout)
水平布局
from PySide6 import QtWidgets
layout = QtWidgets.QHBoxLayout()
# 顺序添加
layout.addWidget(obj1)
layout.addWidget(obj2)
# 比例添加( obj1 和 obj2 将以 1:2 的比例,划分所有的水平区域)
layout.addWidget(obj1, 1)
layout.addWidget(obj2, 2)
'''最后记得绑定到主窗口
self 表示 继承 QWidget 的类对象
'''
self.setLayout(layout)
布局区域
widget = QtWidgets.QWidget()
widget.setLayout(layout)
'''用此方法可以将一个布局添加进另一个布局中
即:
layout2 = QtWidgets.QHBoxLayout()
layout2.addWidget(widget)
'''
基本控件
标签
from PySide6.QtWidgets import QLabel
from PySide6 import QtCore
# 简单文本
label = QLabel("Hello World")
# 对齐方式
label = QLabel("Hello World", alignment=QtCore.Qt.AlignCenter)
# HTML文本
label = QLabel("<font style='color: red;'>红色</font>")
输入框
from PySide6.QtWidgets import QLineEdit
edit = QLineEdit("输入...")
# 取输入框内的文本
edit_text = edit.text()
按钮
import sys
from PySide6 import QtCore, QtWidgets
from PySide6.QtWidgets import QPushButton
class DemoWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.button = QPushButton('按钮')
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.addWidget(self.button)
self.button.clicked.connect(self.hello)
@QtCore.Slot()
def hello(self):
print("Hello World!")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = DemoWidget()
widget.resize(200, 150)
widget.show()
sys.exit(app.exec())
列表控件
普通列表
from PySide6 import QtCore, QtWidgets
list_widget = QtWidgets.QListWidget()
for i in range(10):
item = QtWidgets.QListWidgetItem(f"Item {i}")
item.setTextAlignment(QtCore.Qt.AlignCenter)
list_widget.addItem(item)
表格控件
普通表格
import sys
from PySide6 import QtWidgets
from PySide6.QtGui import QColor
from PySide6.QtWidgets import QTableWidget, QTableWidgetItem
colors = [
("Red", "#FF0000"),
("Green", "#00FF00"),
("Blue", "#0000FF"),
("Black", "#000000"),
("White", "#FFFFFF"),
("Electric Green", "#41CD52"),
("Dark Blue", "#222840"),
("Yellow", "#F9E56d"),
]
class DemoDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(DemoDialog, self).__init__(parent)
self.setWindowTitle("表格")
table = QTableWidget()
table.setRowCount(len(colors))
table.setColumnCount(len(colors[0]) + 1)
table.setHorizontalHeaderLabels(["Name", "Hex Code", "Color"])
for i, (name, code) in enumerate(colors):
item_name = QTableWidgetItem(name)
item_code = QTableWidgetItem(code)
item_color = QTableWidgetItem()
item_color.setBackground(self.get_rgb_from_hex(code))
table.setItem(i, 0, item_name)
table.setItem(i, 1, item_code)
table.setItem(i, 2, item_color)
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.addWidget(table)
def get_rgb_from_hex(self, code):
code_hex = code.replace("#", "")
rgb = tuple(int(code_hex[i:i+2], 16) for i in (0, 2, 4))
return QColor.fromRgb(rgb[0], rgb[1], rgb[2])
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = DemoDialog()
dialog.show()
sys.exit(app.exec())
树控件
基本树
import sys
from PySide6 import QtWidgets
from PySide6.QtWidgets import QTreeWidget, QTreeWidgetItem
data = {
"Project A": ["file_a.py", "file_a.txt", "something.xls"],
"Project B": ["file_b.csv", "photo.jpg"],
"Project C": [],
}
class DemoDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(DemoDialog, self).__init__(parent)
self.setWindowTitle("树")
tree = QTreeWidget()
tree.setColumnCount(2)
tree.setHeaderLabels(["Name", "Type"])
items = []
for key, values in data.items():
item = QTreeWidgetItem([key])
for value in values:
ext = value.split(".")[-1].upper()
child = QTreeWidgetItem([value, ext])
item.addChild(child)
items.append(item)
tree.insertTopLevelItems(0, items)
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.addWidget(tree)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = DemoDialog()
dialog.show()
sys.exit(app.exec())
.ui文件
UI设计器
安装: python -m pip install pyside6
命令行运行:pyside6-designer
间接运行
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>110</x>
<y>80</y>
<width>201</width>
<height>81</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
假设上述 XML 命名为 main.ui
那么将其转换为py文件:pyside6-uic main.ui > main.py
,输出到 main.py 文件中。默认
生成的类名为 Ui_MainWindow
。
因此,代码中引入:from main import Ui_MainWindow
,完整代码:
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
from main import Ui_MainWindow
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
报错:ValueError: source code string cannot contain null bytes
,将编码改为 utf-8
即可。
直接运行
import sys
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QApplication
from PySide6.QtCore import QFile, QIODevice
app = QApplication(sys.argv)
ui_file = QFile("main.ui")
if not ui_file.open(QIODevice.ReadOnly):
print(f"Cannot open main.ui: {ui_file.errorString()}")
sys.exit(-1)
loader = QUiLoader()
window = loader.load(ui_file)
ui_file.close()
if not window:
print(loader.errorString())
sys.exit(-1)
window.show()
sys.exit(app.exec())
.qml文件
基本
import QtQuick 2.0
Rectangle {
width: 200
height: 200
color: "green"
Text {
text: "Hello World"
anchors.centerIn: parent
}
}
代码中引入,并运行
:
from PySide6.QtWidgets import QApplication
from PySide6.QtQuick import QQuickView
from PySide6.QtCore import QUrl
app = QApplication([])
view = QQuickView()
url = QUrl("view.qml")
view.setSource(url)
view.setResizeMode(QQuickView.SizeRootObjectToView)
view.show()
app.exec()
官方示例
import QtQuick 2.0
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import QtQuick.Controls.Material 2.12
ApplicationWindow {
id: page
width: 800
height: 400
visible: true
GridLayout {
id: grid
columns: 2
rows: 3
ColumnLayout {
spacing: 2
Layout.preferredWidth: 400
Text {
id: leftlabel
Layout.alignment: Qt.AlignHCenter
color: "white"
font.pointSize: 16
text: "Qt for Python"
Layout.preferredHeight: 100
Material.accent: Material.Green
}
RadioButton {
id: italic
text: "Italic"
onToggled: {
leftlabel.font.italic = con.getItalic(italic.text)
leftlabel.font.bold = con.getBold(italic.text)
leftlabel.font.underline = con.getUnderline(italic.text)
}
}
RadioButton {
id: bold
text: "Bold"
onToggled: {
leftlabel.font.italic = con.getItalic(bold.text)
leftlabel.font.bold = con.getBold(bold.text)
leftlabel.font.underline = con.getUnderline(bold.text)
}
}
RadioButton {
id: underline
text: "Underline"
onToggled: {
leftlabel.font.italic = con.getItalic(underline.text)
leftlabel.font.bold = con.getBold(underline.text)
leftlabel.font.underline = con.getUnderline(underline.text)
}
}
RadioButton {
id: noneradio
text: "None"
checked: true
onToggled: {
leftlabel.font.italic = con.getItalic(noneradio.text)
leftlabel.font.bold = con.getBold(noneradio.text)
leftlabel.font.underline = con.getUnderline(noneradio.text)
}
}
}
ColumnLayout {
id: rightcolumn
spacing: 2
Layout.columnSpan: 1
Layout.preferredWidth: 400
Layout.preferredHeight: 400
Layout.fillWidth: true
RowLayout {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Button {
id: red
text: "Red"
highlighted: true
Material.accent: Material.Red
onClicked: {
leftlabel.color = con.getColor(red.text)
}
}
Button {
id: green
text: "Green"
highlighted: true
Material.accent: Material.Green
onClicked: {
leftlabel.color = con.getColor(green.text)
}
}
Button {
id: blue
text: "Blue"
highlighted: true
Material.accent: Material.Blue
onClicked: {
leftlabel.color = con.getColor(blue.text)
}
}
Button {
id: nonebutton
text: "None"
highlighted: true
Material.accent: Material.BlueGrey
onClicked: {
leftlabel.color = con.getColor(nonebutton.text)
}
}
}
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Text {
id: rightlabel
color: "white"
text: "Font size"
Material.accent: Material.White
}
Slider {
width: rightcolumn.width*0.6
Layout.alignment: Qt.AlignRight
id: slider
value: 0.5
onValueChanged: {
leftlabel.font.pointSize = con.getSize(value)
}
}
}
}
}
}
Python 代码
:
import sys
import os
from pathlib import Path
from PySide6.QtCore import QObject, Slot
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
class Bridge(QObject):
@Slot(str, result=str)
def getColor(self, color_name):
if color_name.lower() == "red":
return "#ef9a9a"
elif color_name.lower() == "green":
return "#a5d6a7"
elif color_name.lower() == "blue":
return "#90caf9"
else:
return "white"
@Slot(float, result=int)
def getSize(self, s):
size = int(s * 42) # Maximum font size
if size <= 0:
return 1
else:
return size
@Slot(str, result=bool)
def getItalic(self, s):
if s.lower() == "italic":
return True
else:
return False
@Slot(str, result=bool)
def getBold(self, s):
if s.lower() == "bold":
return True
else:
return False
@Slot(str, result=bool)
def getUnderline(self, s):
if s.lower() == "underline":
return True
else:
return False
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
# Instance of the Python object
bridge = Bridge()
# Expose the Python object to QML
context = engine.rootContext()
context.setContextProperty("con", bridge)
# Get the path of the current directory, and then add the name
# of the QML file, to load it.
qmlFile = Path(__file__).parent / 'view.qml'
engine.load(os.fspath(qmlFile.resolve()))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
样式
官方参考
直接绑定
ctrl.setStyleSheet("""
background-color: #000000;
color: #FFFFFF;
""")
间接绑定
新建一个样式文件:style.qss
(类似于 CSS)
编辑样式文件:
QLabel#test {
color: red;
}
#test
来自于控件 .setObjectName('test')
设定的名称 test
。如果不指定,直接写为 QLabel {color: red;}
将作用于所有的 QLabel
实体。
代码中导入样式文件:
...
app = QApplication()
with open("style.qss", "r") as f:
_style = f.read()
app.setStyleSheet(_style)
...
自定义
自定义字体/图标
颜色
from PySide6.QtGui import QColor
# '#F25A5B
QColor.fromRgb('F2', '5A', '5B')
'''适用于 setBackground() 等方法
'''
对齐方式
from PySide6 import QtCore
'''参数设置
其它的类比即可
'''
QLabel("Hello World", alignment=QtCore.Qt.AlignCenter)
'''属性设置
具体有没有下面的属性,需要结合官方文档查看
'''
# 设置文本居中对齐
ctrl.setTextAlignment(QtCore.Qt.AlignCenter)
官方示例代码
总览
模块名 | 应用场景 | 注意点 |
---|---|---|
QtWidgets |
窗口小部件,用于添加按钮、标签等控件 | 在不同平台有不同的外观 |