PySide6 GUI 编程(31):多个 QWidget 窗口展示

2024-08-21 23:44:15 浏览数 (1)

QWidget对象作为临时变量进行展示

示例代码

代码语言:python代码运行次数:0复制
from __future__ import annotations

import sys
from datetime import datetime

from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat()


def init_new_window() -> QMainWindow:
    new_window = QMainWindow()
    label = QLabel("这是新窗口,编号:{}".format(get_time_str()), new_window)
    v_layout = QVBoxLayout()
    v_layout.addWidget(label)
    container = QWidget()
    container.setLayout(v_layout)
    new_window.setCentralWidget(container)
    print("new_window 窗口初始化完成")
    return new_window


def button_clicked():
    print("按钮被点击了,开始初始化 new_window 窗口")
    tmp_window = init_new_window()
    # tmp_window是临时变量, .show()不会阻塞,因此在.show()之后,tmp_window 变量可以被回收
    # 因此看不到 tmp_window 窗口被显示出来
    tmp_window.show()
    print('new_window.show()执行完成')


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        button = QPushButton("显示第二个 QWidget 窗口", self)
        button.clicked.connect(button_clicked)
        label = QLabel("这是主窗口,编号: {}".format(get_time_str()), parent = self)
        v_layout = QVBoxLayout()
        v_layout.addWidget(button)
        v_layout.addWidget(label)
        container = QWidget()
        container.setLayout(v_layout)
        self.setCentralWidget(container)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    # 验证下 init_new_window 函数返回的窗口可以正常运行
    # 但是值得注意的是
    # 使用 init_new_window().show() 时,
    # 窗口可能会在 .show() 方法返回后被立即销毁,
    # 因为没有变量引用它,Python 的垃圾回收器可能会在稍后的某个时间点回收这个对象
    # 这样会导致窗口无法正常显示
    # 将 init_new_window() 的返回值分配给一个变量(如 ret)时,
    # 将确保该窗口对象在应用程序的生命周期内处于活跃状态,
    # 因此窗口将继续显示,直到应用程序退出或变量超出作用域,
    ret = init_new_window()
    ret.show()
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec())

这段代码在处理临时 QWidget 对象时,考虑了两种场景:

  • 函数中作为临时变量 函数中的临时变量函数中的临时变量
  • 无变量引用的场景 无变量引用的场景无变量引用的场景

运行效果

实时展示临时的 QWidget 对象实时展示临时的 QWidget 对象

进程在刚启动时会初始化出两个窗口,这可以证明 init_new_window() 返回的对象是可以正常展示的

进程启动时初始化出两个窗口进程启动时初始化出两个窗口

在点击按钮显示第二个 QWidget 窗口后,并没有第三个窗口展示出来,Console 也只打印了:

只打印日志但是没有窗口展示出来只打印日志但是没有窗口展示出来
点击按钮时触发临时对象的初始化点击按钮时触发临时对象的初始化

让QWidget对象的生命周期延长

示例代码

代码语言:python代码运行次数:0复制
from __future__ import annotations

import sys
from datetime import datetime

from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat()


def init_new_window() -> QMainWindow:
    new_window = QMainWindow()
    label = QLabel("这是新窗口,编号:{}".format(get_time_str()), new_window)
    v_layout = QVBoxLayout()
    v_layout.addWidget(label)
    container = QWidget()
    container.setLayout(v_layout)
    new_window.setCentralWidget(container)
    print("new_window 窗口初始化完成")
    return new_window


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.tmp_window = QMainWindow()  # 初始化一个窗口
        button = QPushButton("显示第二个 QWidget 窗口", self)
        button.clicked.connect(self.button_clicked)
        label = QLabel("这是主窗口,编号: {}".format(get_time_str()), parent = self)
        v_layout = QVBoxLayout()
        v_layout.addWidget(button)
        v_layout.addWidget(label)
        container = QWidget()
        container.setLayout(v_layout)
        self.setCentralWidget(container)

    def button_clicked(self):
        print("按钮被点击了,开始初始化 new_window 窗口")
        # 重新初始化一个窗口
        # 此时 self.tmp_window 将跟随 MyMainWindow 对象的生命周期生存
        # 同时,每次点击按钮时,都会刷新 self.tmp_window 窗口
        # 因此每次都会新生成一个窗口对象覆盖 self.tmp_window
        self.tmp_window = init_new_window()
        self.tmp_window.show()
        print('new_window.show()执行完成')

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    sys.exit(app.exec())
生命周期与主界面对象的生命周期一致生命周期与主界面对象的生命周期一致

运行效果

每次生成新的窗口每次生成新的窗口

可以看到每次点击按钮时,都会生成新的窗口:

覆盖变量的逻辑覆盖变量的逻辑

控制另一个窗口的展示或隐藏

示例代码

代码语言:python代码运行次数:0复制
from __future__ import annotations

import sys
from datetime import datetime

from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat()


def init_new_window() -> QMainWindow:
    new_window = QMainWindow()
    label = QLabel("这是新窗口,编号:{}".format(get_time_str()), new_window)
    v_layout = QVBoxLayout()
    v_layout.addWidget(label)
    container = QWidget()
    container.setLayout(v_layout)
    new_window.setCentralWidget(container)
    print("new_window 窗口初始化完成")
    return new_window


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.tmp_window = None
        button = QPushButton("显示第二个 QWidget 窗口", self)
        button.clicked.connect(self.button_clicked)
        label = QLabel("这是主窗口,编号: {}".format(get_time_str()), parent = self)
        v_layout = QVBoxLayout()
        v_layout.addWidget(button)
        v_layout.addWidget(label)
        container = QWidget()
        container.setLayout(v_layout)
        self.setCentralWidget(container)

    def button_clicked(self):
        if self.tmp_window is not None:
            print('窗口已经完成初始化了')
            if self.tmp_window.isVisible():
                self.tmp_window.hide()
            else:
                self.tmp_window.show()
            return
        print("按钮被点击了,开始初始化 new_window 窗口")
        # 重新初始化一个窗口
        # 此时 self.tmp_window 将跟随 MyMainWindow 对象的生命周期生存
        # 同时,每次点击按钮时,都会刷新 self.tmp_window 窗口
        # 因此每次都会新生成一个窗口对象覆盖 self.tmp_window
        self.tmp_window = init_new_window()
        self.tmp_window.show()
        print('new_window.show()执行完成')


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

运行效果

通过按钮控制窗口的展示与隐藏通过按钮控制窗口的展示与隐藏

通过判断对象状态实现对窗口行为的控制:

核心逻辑核心逻辑

通过信号与槽实现两个窗口展示的联动

示例代码

代码语言:python代码运行次数:0复制
from __future__ import annotations

import hashlib
import sys
from datetime import datetime

from PySide6.QtWidgets import QApplication, QLabel, QLineEdit, QMainWindow, QVBoxLayout, QWidget


def get_time_str() -> str:
    return datetime.now().isoformat()


def init_new_window(label_object: QLabel) -> QMainWindow:
    new_window = QMainWindow()
    v_layout = QVBoxLayout()
    v_layout.addWidget(label_object)
    container = QWidget()
    container.setLayout(v_layout)
    new_window.setCentralWidget(container)
    print("new_window 窗口初始化完成")
    return new_window


class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.tmp_window = None
        self.setWindowTitle("使用信号连接两个窗口")
        label = QLabel("这是主窗口,编号: {}".format(get_time_str()), parent = self)
        self.another_window_label = QLabel('这是展示在第二个窗口上的 Label')
        self.line_edit = QLineEdit('请输入数据', self)
        self.line_edit.setMaxLength(128)
        self.line_edit.returnPressed.connect(self.line_edit_return_pressed)
        v_layout = QVBoxLayout()
        v_layout.addWidget(label)
        container = QWidget()
        container.setLayout(v_layout)
        self.setCentralWidget(container)

    def line_edit_return_pressed(self):
        text = self.line_edit.text()
        hash_obj = hashlib.sha3_256()
        hash_obj.update(text.encode('utf-8'))
        hash_value = hash_obj.hexdigest()
        self.another_window_label.setText('输入的数据是:{}n哈希算法是:{}n哈希值是:{}'.format(
            text, hash_obj.name, hash_value))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyMainWindow()
    window.show()
    another_window = init_new_window(window.another_window_label)
    another_window.show()
    sys.exit(app.exec())

运行效果

窗口联动窗口联动

0 人点赞