Qt开发-QT Widgets

前言

Qt QuickQt Widgets这两种技术,官方是强推Qt Quick的。

https://download.qt.io/official_releases/QtForPython/

常见属性

结合控件的SizePolicy属性,来控制布局管理中的控件的尺寸自适应方式。一些常用值的含义:

  • Fixed:控件不能放大或者缩小,控件的大小就是它的sizeHint。

  • Minimum:控件的sizeHint为控件的最小尺寸。控件不能小于这个sizeHint,但是可以放大。

  • Maximum:控件的sizeHint为控件的最大尺寸,控件不能放大,但是可以缩小到它的最小的允许尺寸。

  • Preferred:控件的sizeHint是它的sizeHint,但是可以放大或者缩小。

  • Expandint:控件可以自行增大或者缩小。

注:sizeHint(布局管理中的控件默认尺寸,如果控件不在布局管理中就为无效的值)

加载UI的两种方式

方式1

转成代码后加载

UI文件转Python代码

1
pyside2-uic form.ui -o ui_form.py

显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import sys
from PySide2.QtWidgets import QApplication, QWidget
from ui_form import Ui_Widget


class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_Widget()
self.ui.setupUi(self)


if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

注意默认会报错

QLayout: Attempting to add QLayout “” to MainWindow “Widget”, which already has a layout

不要使用QMainWindow,因为它默认已经有布局了,所以要把QMainWindow更换为QWidget

方式2

默认代码

直接加载UI文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import os
from pathlib import Path
import sys

from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader


class Widget(QWidget):
def __init__(self):
super(Widget, self).__init__()
self.load_ui()

def load_ui(self):
loader = QUiLoader()
path = os.fspath(Path(__file__).resolve().parent / "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()


if __name__ == "__main__":
app = QApplication([])
widget = Widget()
widget.show()
sys.exit(app.exec_())

上面是工具自动生成的代码,运行时我们会发现,虽然我们设置过窗口的布局,但是页面依旧不会根据窗口缩放自动调整。

原因是

我们的UI本身就是窗口,但是load(ui_file, self),这样的写法是把UI中窗口放在了当前的窗口中,当前窗口还要设置布局。

解决缩放问题

我们可以改成这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import os
from pathlib import Path
import sys

from PySide2.QtWidgets import QApplication, QWidget,QVBoxLayout
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader


class Widget(QWidget):
def __init__(self):
super(Widget, self).__init__()
self.load_ui()

def load_ui(self):
loader = QUiLoader()
path = os.fspath(Path(__file__).resolve().parent / "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
ui = loader.load(ui_file, self)
ui_file.close()
layout = QVBoxLayout()
layout.addWidget(ui)
self.setLayout(layout)
self.resize(800, 600)


if __name__ == "__main__":
app = QApplication([])
widget = Widget()
widget.show()
sys.exit(app.exec_())

这样太麻烦了,我们可以直接用UI生成的窗口,如下:

简单写法

改成如下即可:

1
2
3
4
5
6
7
8
9
10
import sys

from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader

if __name__ == "__main__":
app = QApplication([])
ui = QUiLoader().load('form.ui')
ui.show()
sys.exit(app.exec_())

推荐写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
from pathlib import Path
import sys

from PySide2.QtWidgets import QApplication, QWidget,QVBoxLayout
from PySide2.QtCore import Signal,QObject
from PySide2.QtUiTools import QUiLoader


class MyWin(QObject):
def __init__(self):
self.load_ui()

def load_ui(self):
self.ui = QUiLoader().load("form.ui")


if __name__ == "__main__":
app = QApplication([])
myWin = MyWin()
myWin.ui.show();
sys.exit(app.exec_())

窗口设置

去掉顶部按钮

1
2
3
from PySide2.QtCore import QFile, Qt

self.setWindowFlags(Qt.FramelessWindowHint)

工具条

经常我们会实现显示在桌面一侧的工具条,工具条一般都是置顶的,但是如果工具条会伸展或者不规则,我们就需要窗口的透明区域能够鼠标穿透。

窗口背景透明鼠标穿透置顶

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from PySide2.QtUiTools import QUiLoader
from PySide2.QtCore import QFile, Qt


class MyWin(QObject):
def __init__(self):
self.load_ui()

def load_ui(self):
self.ui = QUiLoader().load("form.ui")


if __name__ == "__main__":
app = QApplication([])
myWin = MyWin()
myWin.ui.setAttribute(Qt.WA_TranslucentBackground,True);
myWin.ui.setWindowFlags(Qt.FramelessWindowHint|Qt.Window|Qt.WindowStaysOnTopHint);
myWin.ui.show();

sys.exit(app.exec_())

注意

setAttribute(Qt.WA_TranslucentBackground,True)这句主要作用就是让窗口的透明区域鼠标穿透

setWindowFlags(Qt.FramelessWindowHint|Qt.Window|Qt.WindowStaysOnTopHint)设置窗口状态

  • Qt.FramelessWindowHint 无边框
  • Qt.Window 显示在状态栏
  • Qt.WindowStaysOnTopHint 窗口置顶

设置窗口的属性一定要在调用show()之前