第二章 控件学习
目录
一、层级关系
使用 PyQt5 创建一个简单的 GUI 应用程序,展示了控件层级关系的调整。
# 0. 导入需要的包和模块
from PyQt5.Qt import *
import sys
class Label(QLabel):
def mousePressEvent(self, evt):
self.raise_()
# 1. 创建一个应用程序对象
app = QApplication(sys.argv)
# 2. 控件的操作
# 2.1 创建控件
window = QWidget()
# 2.2 设置控件
window.setWindowTitle("层级关系调整")
window.resize(500, 500)
label1 = Label(window)
label1.setText("标签1")
label1.resize(200, 200)
label1.setStyleSheet("background-color: red;")
label2 = Label(window)
label2.setText("标签2")
label2.resize(200, 200)
label2.setStyleSheet("background-color: green;")
# label2.move(200, 200)
label2.move(100, 100)
# label2.lower()
# label1.raise_()
# label2.stackUnder(label1)
# 2.3 展示控件
window.show()
# 3. 应用程序的执行, 进入到消息循环
sys.exit(app.exec_())
代码解读
1.1 自定义 Label 类
class Label(QLabel):
def mousePressEvent(self, evt):
self.raise_()
创建了一个继承自
QLabel
的自定义类Label
。重写了
mousePressEvent
方法,当标签被点击时,调用self.raise_()
将该标签置于最顶层显示。
1.2 应用程序初始化
app = QApplication(sys.argv)
创建了一个
QApplication
对象,这是 PyQt5 应用程序的核心,处理应用程序的初始化和结束,以及事件处理。
1.3 主窗口和控件设置
window = QWidget()
window.setWindowTitle("层级关系调整")
window.resize(500, 500)
创建了一个
QWidget
作为主窗口。设置窗口标题和大小。
1.4 创建两个标签控件
label1 = Label(window)
label1.setText("标签1")
label1.resize(200, 200)
label1.setStyleSheet("background-color: red;")
label2 = Label(window)
label2.setText("标签2")
label2.resize(200, 200)
label2.setStyleSheet("background-color: green;")
label2.move(100, 100)
创建了两个自定义的
Label
控件,分别设置了文本、大小和背景颜色。
label2
通过move(100, 100)
方法相对于父窗口 (0,0) 点向右下方移动了 100 像素,与label1
部分重叠。
1.5 层级控制相关代码(被注释部分)
# label2.lower()
# label1.raise_()
# label2.stackUnder(label1)
lower()
: 将控件置于底层。
raise_()
: 将控件置于顶层。
stackUnder(other)
: 将控件置于指定控件other
的下方。
1.6 显示窗口并进入消息循环
window.show()
sys.exit(app.exec_())
show()
方法将窗口显示出来。
app.exec_()
启动应用程序的事件循环,处理用户输入和系统事件。
sys.exit()
确保应用程序正确退出。
这个应用程序创建了两个重叠的标签,红色标签和绿色标签。当用户点击任何一个标签时,被点击的标签会被提升到最上层显示。通过这种方式,用户可以直观地看到控件层级关系的变化。
二、窗口的操作
下面通过一个简单案例演示 QWidget 窗口的基本操作,并对代码进行详细解读。这个案例展示了 QWidget 窗口的创建、标题设置、大小调整、位置移动、图标设置、透明度调整等常见操作。
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon, QColor
# 创建应用程序对象
app = QApplication(sys.argv)
# 创建窗口实例
window = QWidget()
# 设置窗口标题
window.setWindowTitle("QWidget窗口操作示例")
# 设置窗口大小
window.resize(600, 400) # 宽度600像素,高度400像素
# 设置窗口位置(屏幕坐标)
window.move(300, 200) # 窗口左上角位于屏幕(300, 200)位置
# 设置窗口固定大小(不可调整)
# window.setFixedSize(600, 400)
# 设置窗口最小和最大尺寸限制
window.setMinimumSize(400, 300)
window.setMaximumSize(800, 600)
# 设置窗口背景颜色
window.setStyleSheet("background-color: #f0f0f0;")
# 设置窗口图标(需要准备一个icon.png文件在当前目录)
# window.setWindowIcon(QIcon('icon.png'))
# 设置窗口透明度(0.0完全透明,1.0完全不透明)
window.setWindowOpacity(0.95)
# 设置窗口是否可关闭、最小化、最大化
# window.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)
# 显示窗口
window.show()
# 进入应用程序主循环
sys.exit(app.exec_())
代码详细解读
2.1 导入必要的模块
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon, QColor
sys
模块用于获取命令行参数和程序退出
QApplication
是 PyQt 应用程序的核心,负责管理应用程序的资源和事件循环
QWidget
是所有用户界面对象的基类,可作为独立窗口使用
QIcon
用于设置窗口图标
QColor
用于处理颜色
2.2 创建应用程序和窗口
app = QApplication(sys.argv)
window = QWidget()
QApplication
必须在创建任何 GUI 组件之前创建
QWidget
实例化后就是一个空白窗口
2.3 窗口标题和大小设置
window.setWindowTitle("QWidget窗口操作示例")
window.resize(600, 400)
setWindowTitle()
设置窗口标题栏显示的文本
resize()
设置窗口的宽度和高度 (像素为单位)
2.4 窗口位置控制
window.move(300, 200)
move()
将窗口移动到屏幕指定位置- 坐标 (0,0) 是屏幕左上角
2.5 窗口尺寸限制
window.setMinimumSize(400, 300)
window.setMaximumSize(800, 600)
通过设置最小和最大尺寸,可以限制用户调整窗口的范围
如果需要固定窗口大小,可使用
setFixedSize()
2.6 窗口外观设置
window.setStyleSheet("background-color: #f0f0f0;")
window.setWindowOpacity(0.95)
使用 CSS 样式表 (
setStyleSheet()
) 设置窗口背景颜色
setWindowOpacity()
设置窗口透明度,范围从 0.0 (完全透明) 到 1.0 (完全不透明)
2.7 窗口图标设置 (需要准备图标文件)
window.setWindowIcon(QIcon('icon.png'))
setWindowIcon()
设置窗口左上角的图标需要提供一个图标文件路径
2.8 窗口标志设置 (控制窗口行为)
window.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)
setWindowFlags()
可以控制窗口的行为和外观例如:只显示关闭和最小化按钮,隐藏最大化按钮
2.9 显示窗口并进入事件循环
window.show()
sys.exit(app.exec_())
show()
将窗口显示在屏幕上
app.exec_()
启动应用程序的事件循环,处理用户输入和系统事件
sys.exit()
确保应用程序正确退出并释放资源
运行效果
运行上述代码后,会显示一个灰色背景的窗口,标题为 "QWidget 窗口操作示例",大小为 600×400 像素,位置在屏幕 (300,200) 处。你可以拖动窗口、调整大小 (受最小 / 最大尺寸限制),点击关闭按钮退出程序。
三、QWidget-API
# 0. 导入需要的包和模块
from PyQt5.Qt import *
import sys
# 1. 创建一个应用程序对象
app = QApplication(sys.argv)
window = QWidget()
window.move(200, 100)
window.resize(500, 500)
# window.setFixedSize(500, 500)
label = QLabel(window)
label.setText("平安顺遂")
label.move(100, 100)
label.setStyleSheet("background-color: cyan;")
def changeCao():
new_content = label.text() + "万事如意"
label.setText(new_content)
# label.resize(label.width() + 100, label.height())
label.adjustSize()
btn = QPushButton(window)
btn.setText("增加内容")
btn.move(100, 300)
btn.clicked.connect(changeCao)
# window.setGeometry(0, 0, 150, 150)
# print(window.x())
# print(window.width())
# print(window.geometry())
window.show()
# window.setGeometry(0, 0, 150, 150)
# 3. 应用程序的执行, 进入到消息循环
sys.exit(app.exec_())
这段代码创建了一个简单的 PyQt5 图形界面应用程序,窗口中包含一个标签 (QLabel) 和一个按钮 (QPushButton)。点击按钮会在标签文本后添加 "万事如意" 并自动调整标签大小以适应新内容。
代码详细解读
3.1 模块导入
from PyQt5.Qt import *
import sys
从 PyQt5.Qt 导入所有模块,包含了 Qt 的核心组件和 GUI 类
导入 sys 模块用于程序退出时的系统操作
3.2 应用程序和窗口初始化
app = QApplication(sys.argv)
window = QWidget()
window.move(200, 100)
window.resize(500, 500)
创建 QApplication 实例,这是每个 PyQt5 应用必须的
创建 QWidget 作为主窗口
move(200, 100)
将窗口移动到屏幕坐标 (200, 100) 处
resize(500, 500)
设置窗口大小为 500×500 像素
3.3 创建标签控件
label = QLabel(window)
label.setText("平安顺遂")
label.move(100, 100)
label.setStyleSheet("background-color: cyan;")
创建 QLabel 控件并设置父窗口为 window
设置标签文本为 "平安顺遂"
将标签移动到窗口内坐标 (100, 100) 处
使用 CSS 样式表设置标签背景颜色为青色
3.4 定义按钮点击事件处理函数
def changeCao():
new_content = label.text() + "万事如意"
label.setText(new_content)
label.adjustSize()
获取当前标签文本并追加 "万事如意"
更新标签文本
adjustSize()
自动调整标签大小以适应新文本内容
3.5 创建按钮控件
btn = QPushButton(window)
btn.setText("增加内容")
btn.move(100, 300)
btn.clicked.connect(changeCao)
创建 QPushButton 控件并设置父窗口
设置按钮文本为 "增加内容"
将按钮移动到窗口内坐标 (100, 300) 处
将按钮的 clicked 信号连接到 changeCao 函数,实现点击按钮执行函数的功能
3.6 窗口显示和应用程序进入消息循环
window.show()
sys.exit(app.exec_())
显示窗口
进入应用程序的主事件循环,处理用户输入和系统事件
当窗口关闭时,通过 sys.exit () 确保应用程序正确退出
关键知识点说明
信号与槽机制
- PyQt5 的核心机制之一,用于对象间的通信
- 这里按钮的 clicked 信号连接到 changeCao 槽函数
控件大小调整
adjustSize()
方法会根据控件内容自动调整大小- 注释掉的
label.resize(label.width() + 100, label.height())
是手动调整大小的方式坐标系统
- 窗口有自己的坐标系,左上角为 (0,0)
move(x,y)
方法设置控件在父窗口中的位置样式设置
- 使用 setStyleSheet 可以方便地设置控件外观
- 支持类似 CSS 的语法
运行程序后会显示一个窗口,包含:
一个青色背景的标签,显示 "平安顺遂"
一个 "增加内容" 按钮
每次点击按钮,标签文本会追加 "万事如意" 并自动调整大小以完整显示文本。
四、综合性案例
案例1:
# 0. 导入需要的包和模块
from PyQt5.Qt import *
import sys
class Window(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setWindowOpacity(0.9)
# 2.2 设置控件
self.setWindowTitle("顶层窗口操作-案例")
self.resize(500, 500)
# 公共数据
self.top_margin = 10
self.btn_w = 80
self.btn_h = 40
self.setup_ui()
def setup_ui(self):
# 添加三个子控件 - 窗口的右上角
close_btn = QPushButton(self)
self.close_btn = close_btn
close_btn.setText("关闭")
close_btn.resize(self.btn_w, self.btn_h)
max_btn = QPushButton(self)
self.max_btn = max_btn
max_btn.setText("最大化")
max_btn.resize(self.btn_w, self.btn_h)
mini_btn = QPushButton(self)
self.mini_btn = mini_btn
mini_btn.setText("最小化")
mini_btn.resize(self.btn_w, self.btn_h)
close_btn.pressed.connect(self.close)
def max_normal():
if self.isMaximized():
self.showNormal()
max_btn.setText("最大化")
else:
self.showMaximized()
max_btn.setText("恢复")
max_btn.pressed.connect(max_normal)
mini_btn.pressed.connect(self.showMinimized)
def resizeEvent(self, QResizeEvent):
print("窗口大小发生了改变")
# close_btn_w = btn_w
window_w = self.width()
close_btn_x = window_w - self.btn_w
close_btn_y = self.top_margin
self.close_btn.move(close_btn_x, close_btn_y)
max_btn_x = close_btn_x - self.btn_w
max_btn_y = self.top_margin
self.max_btn.move(max_btn_x, max_btn_y)
mini_btn_x = max_btn_x - self.btn_w
mini_btn_y = self.top_margin
self.mini_btn.move(mini_btn_x, mini_btn_y)
def mousePressEvent(self, QMouseEvent):
# 判定点击的是否是鼠标左键
# 在此处设计一个标记, 用作判定是否需要移动
# 一个就是窗口的原始坐标
# 鼠标按下的点
pass
def mouseMoveEvent(self, QMouseEvent):
# if 窗口的移动标记 == True:
# 根据鼠标按下的点 计算移动向量
# 根据移动向量, 和窗口的原始坐标 = 最新坐标
# 移动整个窗口的位置
pass
def mouseReleaseEvent(self, QMouseEvent):
# 把这个标记, 进行重置 False
pass
# 1. 创建一个应用程序对象
app = QApplication(sys.argv)
# 2. 控件的操作
# 2.1 创建控件
# window = QWidget(flags=Qt.FramelessWindowHint)
window = Window()
# 2.3 展示控件
window.show()
# 3. 应用程序的执行, 进入到消息循环
sys.exit(app.exec_())
这段代码实现了一个自定义标题栏的无框窗口,包含关闭、最大化 / 恢复、最小化功能,并预留了鼠标拖动移动窗口的接口。
整体架构与功能概述
class Window(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 设置窗口无边框
self.setWindowFlags(Qt.FramelessWindowHint)
# 设置窗口透明度
self.setWindowOpacity(0.9)
self.setWindowTitle("顶层窗口操作-案例")
self.resize(500, 500)
# 公共参数
self.top_margin = 10 # 顶部边距
self.btn_w = 80 # 按钮宽度
self.btn_h = 40 # 按钮高度
self.setup_ui() # 初始化界面
核心特性:通过
setWindowFlags(Qt.FramelessWindowHint)
移除系统默认标题栏,实现完全
自定义界面
视觉效果:
setWindowOpacity(0.9)
设置半透明效果,增强现代 UI 质感参数设计:通过公共变量统一管理按钮尺寸和边距,便于后续维护
自定义控制按钮实现
def setup_ui(self):
# 创建关闭按钮
close_btn = QPushButton(self)
close_btn.setText("关闭")
close_btn.resize(self.btn_w, self.btn_h)
# 创建最大化/恢复按钮
max_btn = QPushButton(self)
max_btn.setText("最大化")
max_btn.resize(self.btn_w, self.btn_h)
# 创建最小化按钮
mini_btn = QPushButton(self)
mini_btn.setText("最小化")
mini_btn.resize(self.btn_w, self.btn_h)
# 连接关闭事件
close_btn.pressed.connect(self.close)
# 实现最大化/恢复逻辑
def max_normal():
if self.isMaximized():
self.showNormal()
max_btn.setText("最大化")
else:
self.showMaximized()
max_btn.setText("恢复")
max_btn.pressed.connect(max_normal)
# 连接最小化事件
mini_btn.pressed.connect(self.showMinimized)
按钮功能:
关闭按钮:直接调用
self.close()
关闭窗口最大化 / 恢复按钮:通过
isMaximized()
判断状态,切换showMaximized()
和showNormal()
最小化按钮:调用
showMinimized()
实现窗口最小化
- 交互逻辑:使用 lambda 表达式和嵌套函数实现按钮状态切换,保持代码整洁
窗口尺寸变化响应
def resizeEvent(self, QResizeEvent):
print("窗口大小发生了改变")
window_w = self.width()
# 计算关闭按钮位置(右上角)
close_btn_x = window_w - self.btn_w
close_btn_y = self.top_margin
self.close_btn.move(close_btn_x, close_btn_y)
# 计算最大化按钮位置(关闭按钮左侧)
max_btn_x = close_btn_x - self.btn_w
max_btn_y = self.top_margin
self.max_btn.move(max_btn_x, max_btn_y)
# 计算最小化按钮位置(最大化按钮左侧)
mini_btn_x = max_btn_x - self.btn_w
mini_btn_y = self.top_margin
self.mini_btn.move(mini_btn_x, mini_btn_y)
动态布局:当窗口尺寸变化时(如最大化、手动调整),自动重新计算按钮位置
定位逻辑:
- 关闭按钮:窗口宽度 - 按钮宽度,顶部边距
- 其他按钮:依次向左偏移一个按钮宽度
调试输出:打印日志便于观察
resizeEvent
触发时机
鼠标交互接口(待完成)
def mousePressEvent(self, QMouseEvent):
# 待实现:
# 1. 判断鼠标左键点击
# 2. 记录窗口原始位置和鼠标点击位置
# 3. 设置移动标记
pass
def mouseMoveEvent(self, QMouseEvent):
# 待实现:
# 1. 根据移动标记判断是否需要移动
# 2. 计算鼠标偏移量,更新窗口位置
pass
def mouseReleaseEvent(self, QMouseEvent):
# 待实现:重置移动标记
pass
拖动功能框架:这三个方法是实现窗口拖动的核心接口
缺失逻辑:
mousePressEvent
需记录初始位置:self.oldPos = event.globalPos()
mouseMoveEvent
需计算偏移量:delta = event.globalPos() - self.oldPos
,并调用move(self.pos() + delta)
mouseReleaseEvent
可重置标记或清空位置记录
实现示例(补充后):
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.oldPos = event.globalPos()
def mouseMoveEvent(self, event):
if hasattr(self, 'oldPos'):
delta = event.globalPos() - self.oldPos
self.move(self.pos() + delta)
self.oldPos = event.globalPos()
def mouseReleaseEvent(self, event):
if hasattr(self, 'oldPos'):
del self.oldPos
主程序流程
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
标准 PyQt 流程:
- 创建应用程序实例
- 实例化自定义窗口
- 显示窗口
- 进入事件循环
扩展应用场景
- 顶层窗口设计:通过
setWindowFlags(Qt.WindowStaysOnTopHint)
可设置窗口始终置顶- 美观优化:添加按钮图标、悬停效果(
setStyleSheet
),或使用 QSS 美化界面- 触摸支持:扩展鼠标事件以支持触摸屏拖动
- 多显示器适配:在
resizeEvent
中增加对多屏幕边界的检测
案例2:
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QPushButton, QLabel,
QVBoxLayout, QHBoxLayout, QSlider, QSpinBox)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# 设置主窗口
self.setWindowTitle("窗口几何与层级演示")
self.resize(800, 600)
# 创建控制面板
control_layout = QHBoxLayout()
# 位置控制
pos_layout = QVBoxLayout()
pos_label = QLabel("位置控制", self)
self.x_spin = QSpinBox(self)
self.x_spin.setRange(0, 1000)
self.x_spin.setValue(200)
self.y_spin = QSpinBox(self)
self.y_spin.setRange(0, 1000)
self.y_spin.setValue(100)
pos_layout.addWidget(pos_label)
pos_layout.addWidget(QLabel("X坐标:", self))
pos_layout.addWidget(self.x_spin)
pos_layout.addWidget(QLabel("Y坐标:", self))
pos_layout.addWidget(self.y_spin)
# 大小控制
size_layout = QVBoxLayout()
size_label = QLabel("大小控制", self)
self.width_spin = QSpinBox(self)
self.width_spin.setRange(100, 800)
self.width_spin.setValue(300)
self.height_spin = QSpinBox(self)
self.height_spin.setRange(100, 600)
self.height_spin.setValue(200)
size_layout.addWidget(size_label)
size_layout.addWidget(QLabel("宽度:", self))
size_layout.addWidget(self.width_spin)
size_layout.addWidget(QLabel("高度:", self))
size_layout.addWidget(self.height_spin)
# 透明度控制
alpha_layout = QVBoxLayout()
alpha_label = QLabel("透明度控制", self)
self.alpha_slider = QSlider(Qt.Horizontal, self)
self.alpha_slider.setRange(50, 100)
self.alpha_slider.setValue(90)
alpha_layout.addWidget(alpha_label)
alpha_layout.addWidget(self.alpha_slider)
# 层级控制按钮
layer_layout = QVBoxLayout()
layer_label = QLabel("层级控制", self)
self.raise_btn = QPushButton("置于顶层", self)
self.lower_btn = QPushButton("置于底层", self)
layer_layout.addWidget(layer_label)
layer_layout.addWidget(self.raise_btn)
layer_layout.addWidget(self.lower_btn)
# 添加所有控制到水平布局
control_layout.addLayout(pos_layout)
control_layout.addLayout(size_layout)
control_layout.addLayout(alpha_layout)
control_layout.addLayout(layer_layout)
# 创建三个重叠的子窗口
self.create_sub_windows()
# 主布局
main_layout = QVBoxLayout()
main_layout.addLayout(control_layout)
self.setLayout(main_layout)
# 连接信号和槽
self.connect_signals()
# 显示窗口
self.show()
def create_sub_windows(self):
# 创建三个不同颜色的子窗口
self.windows = []
colors = [QColor(255, 0, 0, 200), # 红色
QColor(0, 255, 0, 200), # 绿色
QColor(0, 0, 255, 200)] # 蓝色
titles = ["窗口1", "窗口2", "窗口3"]
for i in range(3):
win = QWidget(self)
win.setWindowTitle(titles[i])
win.resize(300, 200)
win.move(200 + i*50, 100 + i*50)
win.setStyleSheet(f"background-color: rgba({colors[i].red()}, "
f"{colors[i].green()}, {colors[i].blue()}, "
f"{self.alpha_slider.value()});")
# 添加标签显示窗口信息
label = QLabel(titles[i], win)
label.setAlignment(Qt.AlignCenter)
label.setStyleSheet("color: white; font-size: 16px;")
layout = QVBoxLayout()
layout.addWidget(label)
win.setLayout(layout)
# 窗口点击事件 - 选中当前窗口
win.mousePressEvent = lambda event, idx=i: self.select_window(idx)
self.windows.append(win)
win.show()
# 默认选中第一个窗口
self.selected_idx = 0
def connect_signals(self):
# 连接控制部件的信号到相应的槽函数
self.x_spin.valueChanged.connect(self.update_window_geometry)
self.y_spin.valueChanged.connect(self.update_window_geometry)
self.width_spin.valueChanged.connect(self.update_window_geometry)
self.height_spin.valueChanged.connect(self.update_window_geometry)
self.alpha_slider.valueChanged.connect(self.update_window_opacity)
self.raise_btn.clicked.connect(self.raise_selected_window)
self.lower_btn.clicked.connect(self.lower_selected_window)
def select_window(self, idx):
"""选中指定索引的窗口"""
self.selected_idx = idx
# 更新控制面板的值为当前选中窗口的属性
win = self.windows[idx]
self.x_spin.setValue(win.x())
self.y_spin.setValue(win.y())
self.width_spin.setValue(win.width())
self.height_spin.setValue(win.height())
def update_window_geometry(self):
"""更新选中窗口的大小和位置"""
win = self.windows[self.selected_idx]
win.setGeometry(self.x_spin.value(), self.y_spin.value(),
self.width_spin.value(), self.height_spin.value())
def update_window_opacity(self):
"""更新所有窗口的透明度"""
alpha = self.alpha_slider.value()
for win in self.windows:
# 提取原有颜色并更新透明度
style = win.styleSheet()
# 简单的字符串处理来更新透明度
style = style.replace(f"rgba(", f"rgba({{}}, {{}}, {{}}, {alpha})")
win.setStyleSheet(style)
def raise_selected_window(self):
"""将选中的窗口置于顶层"""
self.windows[self.selected_idx].raise_()
def lower_selected_window(self):
"""将选中的窗口置于底层"""
for i, win in enumerate(self.windows):
if i != self.selected_idx:
win.raise_()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
代码解读
4.1 窗口大小和位置控制
# 位置控制
self.x_spin = QSpinBox(self)
self.x_spin.setRange(0, 1000)
self.y_spin = QSpinBox(self)
self.y_spin.setRange(0, 1000)
# 大小控制
self.width_spin = QSpinBox(self)
self.width_spin.setRange(100, 800)
self.height_spin = QSpinBox(self)
self.height_spin.setRange(100, 600)
# 更新窗口几何属性
def update_window_geometry(self):
win = self.windows[self.selected_idx]
win.setGeometry(self.x_spin.value(), self.y_spin.value(),
self.width_spin.value(), self.height_spin.value())
使用 QSpinBox 控件让用户能够输入窗口的 X、Y 坐标以及宽度、高度
setGeometry()
方法可以同时设置窗口的位置和大小
4.2 窗口透明度控制
# 透明度控制
self.alpha_slider = QSlider(Qt.Horizontal, self)
self.alpha_slider.setRange(50, 100)
# 更新窗口透明度
def update_window_opacity(self):
alpha = self.alpha_slider.value()
for win in self.windows:
style = style.replace(f"rgba(", f"rgba({{}}, {{}}, {{}}, {alpha})")
win.setStyleSheet(style)
借助 QSlider 实现窗口透明度的调整
利用 CSS 的 rgba 颜色模式设置透明度
4.3 窗口层级控制
# 层级控制按钮
self.raise_btn = QPushButton("置于顶层", self)
self.lower_btn = QPushButton("置于底层", self)
# 将选中窗口置于顶层
def raise_selected_window(self):
self.windows[self.selected_idx].raise_()
# 将选中窗口置于底层
def lower_selected_window(self):
for i, win in enumerate(self.windows):
if i != self.selected_idx:
win.raise_()
raise_()
方法能够把窗口置于最顶层要将窗口置于底层,需要把其他所有窗口都提升到该窗口之上
4.4 窗口选择机制
# 窗口点击事件 - 选中当前窗口
win.mousePressEvent = lambda event, idx=i: self.select_window(idx)
def select_window(self, idx):
self.selected_idx = idx
# 更新控制面板为当前选中窗口的属性
win = self.windows[idx]
self.x_spin.setValue(win.x())
self.y_spin.setValue(win.y())
self.width_spin.setValue(win.width())
self.height_spin.setValue(win.height())
重写了窗口的 mousePressEvent 事件处理函数
点击某个窗口会选中它,并更新控制面板显示该窗口的属性
应用场景说明
多窗口界面设计
- 在设计多文档界面 (MDI) 应用程序时,需要控制子窗口的大小、位置和层级
- 这个示例模拟了类似 Photoshop 的多文档编辑环境
游戏开发
- 游戏中的 HUD (抬头显示) 元素需要精确控制位置和层级
- 可以通过调整透明度来实现淡入淡出效果
数据可视化
- 多个图表窗口可能需要重叠显示,并且用户可以切换查看不同的图表
- 可以根据数据重要性调整窗口层级
对话框管理
- 模态对话框需要始终显示在最顶层
- 非模态对话框可以在用户操作时调整层级
运行这个程序,你可以:
点击不同颜色的窗口来选中它们
通过控制面板调整选中窗口的位置和大小
调整所有窗口的透明度
控制窗口的层级关系(置于顶层或底层)