层级关系和窗口操作-笔记

第二章 控件学习


目录

第二章 控件学习

一、层级关系

1.1  自定义 Label 类

1.2 应用程序初始化

1.3 主窗口和控件设置

1.4  创建两个标签控件

1.5  层级控制相关代码(被注释部分)

1.6 显示窗口并进入消息循环

二、窗口的操作

2.1  导入必要的模块

2.2  创建应用程序和窗口

2.3  窗口标题和大小设置

2.4 窗口位置控制

2.5  窗口尺寸限制

2.6 窗口外观设置

2.7  窗口图标设置 (需要准备图标文件)

2.8 窗口标志设置 (控制窗口行为)

2.9 显示窗口并进入事件循环

三、QWidget-API

3.1 模块导入

3.2 应用程序和窗口初始化

3.3 创建标签控件

3.4 定义按钮点击事件处理函数

3.5  创建按钮控件

3.6 窗口显示和应用程序进入消息循环

四、综合性案例

案例1:

案例2:

4.1 窗口大小和位置控制

4.2 窗口透明度控制

4.3 窗口层级控制

4.4 窗口选择机制



一、层级关系

使用 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 () 确保应用程序正确退出

关键知识点说明

  1. 信号与槽机制

    • PyQt5 的核心机制之一,用于对象间的通信
    • 这里按钮的 clicked 信号连接到 changeCao 槽函数
  2. 控件大小调整

    • adjustSize()方法会根据控件内容自动调整大小
    • 注释掉的label.resize(label.width() + 100, label.height())是手动调整大小的方式
  3. 坐标系统

    • 窗口有自己的坐标系,左上角为 (0,0)
    • move(x,y)方法设置控件在父窗口中的位置
  4. 样式设置

    • 使用 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

拖动功能框架:这三个方法是实现窗口拖动的核心接口

缺失逻辑

  1. mousePressEvent需记录初始位置:self.oldPos = event.globalPos()
  2. mouseMoveEvent需计算偏移量:delta = event.globalPos() - self.oldPos,并调用move(self.pos() + delta)
  3. 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 流程

  1. 创建应用程序实例
  2. 实例化自定义窗口
  3. 显示窗口
  4. 进入事件循环

扩展应用场景

  1. 顶层窗口设计:通过setWindowFlags(Qt.WindowStaysOnTopHint)可设置窗口始终置顶
  2. 美观优化:添加按钮图标、悬停效果(setStyleSheet),或使用 QSS 美化界面
  3. 触摸支持:扩展鼠标事件以支持触摸屏拖动
  4. 多显示器适配:在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 事件处理函数

点击某个窗口会选中它,并更新控制面板显示该窗口的属性

应用场景说明

  1. 多窗口界面设计

    • 在设计多文档界面 (MDI) 应用程序时,需要控制子窗口的大小、位置和层级
    • 这个示例模拟了类似 Photoshop 的多文档编辑环境
  2. 游戏开发

    • 游戏中的 HUD (抬头显示) 元素需要精确控制位置和层级
    • 可以通过调整透明度来实现淡入淡出效果
  3. 数据可视化

    • 多个图表窗口可能需要重叠显示,并且用户可以切换查看不同的图表
    • 可以根据数据重要性调整窗口层级
  4. 对话框管理

    • 模态对话框需要始终显示在最顶层
    • 非模态对话框可以在用户操作时调整层级

运行这个程序,你可以:

点击不同颜色的窗口来选中它们

通过控制面板调整选中窗口的位置和大小

调整所有窗口的透明度

控制窗口的层级关系(置于顶层或底层)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寄思~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值