鱼C论坛

 找回密码
 立即注册
查看: 655|回复: 5

[已解决]如何让独立的子窗口跟随主窗口一起关闭

[复制链接]
发表于 2025-1-23 09:52:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
如何让MinuteK跟随主窗口一起关闭,不使用Qt.Tool
'
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import sys

def create_painter(qp, color, width):
    qp.save()
    pen = QPen(QColor(color), width)
    qp.setPen(pen)
    return qp

class CustomSubWindow(QMdiSubWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("子窗口")
        self.a = 0

        self.initUI()

    def initUI(self):
        self.label = QLabel("双击子窗口中的任意位置", self)
        layout = QVBoxLayout()
        layout.addWidget(self.label)
        container = QWidget()
        container.setLayout(layout)
        self.setWidget(container)


    def mouseDoubleClickEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            self.a += 1
            print("子窗口被双击了", self.a)
            self.label.setText("双击事件已捕获")
            # 创建并显示 MinuteK 窗口
            self.minute_k_window = MinuteK()
            self.minute_k_window.setWindowFlags(Qt.WindowStaysOnTopHint)
            self.minute_k_window.show()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("主窗口")
        self.setGeometry(100, 100, 800, 600)

        self.mdi_area = QMdiArea()
        self.setCentralWidget(self.mdi_area)

        self.createSubWindow()

    def createSubWindow(self):
        self.sub_window = CustomSubWindow()
        self.mdi_area.addSubWindow(self.sub_window)
        self.sub_window.show()

class MinuteK(QWidget):
    def __init__(self, parent=None):
        super(MinuteK, self).__init__(parent)
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("MinuteK 窗口")
        self.setGeometry(100, 100, 400, 400)
        # 可以在这里添加更多的 UI 元素
    def paintEvent(self, event):
        qp = QPainter(self)
        create_painter(qp, Qt.red, 2).drawLine(50, 50, 100, 50)
        qp.restore()

if __name__ == "__main__":

    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec())
'
最佳答案
2025-1-23 10:21:45


如果你希望 `MinuteK` 窗口保持独立显示,并跟随主窗口一起关闭,推荐的办法是通过显式地设置子窗口和独立窗口的生命周期管理关系。以下提供一个可靠的解决方案,保证 `MinuteK` 窗口跟随主窗口或子窗口关闭。

请使用以下代码:

  1. from PySide6.QtCore import *
  2. from PySide6.QtGui import *
  3. from PySide6.QtWidgets import *
  4. import sys

  5. def create_painter(qp, color, width):
  6.     qp.save()
  7.     pen = QPen(QColor(color), width)
  8.     qp.setPen(pen)
  9.     return qp

  10. class CustomSubWindow(QMdiSubWindow):
  11.     def __init__(self, parent=None):
  12.         super().__init__(parent)
  13.         self.setWindowTitle("子窗口")
  14.         self.a = 0
  15.         self.minute_k_window = None  # 用于保存 MinuteK 窗口的引用
  16.         self.initUI()

  17.     def initUI(self):
  18.         self.label = QLabel("双击子窗口中的任意位置", self)
  19.         layout = QVBoxLayout()
  20.         layout.addWidget(self.label)
  21.         container = QWidget()
  22.         container.setLayout(layout)
  23.         self.setWidget(container)

  24.     def mouseDoubleClickEvent(self, event: QMouseEvent):
  25.         if event.button() == Qt.LeftButton:
  26.             self.a += 1
  27.             print("子窗口被双击了", self.a)
  28.             self.label.setText("双击事件已捕获")
  29.             if not self.minute_k_window:
  30.                 # 创建并显示 MinuteK 窗口
  31.                 self.minute_k_window = MinuteK()
  32.                 self.minute_k_window.setAttribute(Qt.WA_DeleteOnClose)  # 让窗口在关闭时自动销毁
  33.             self.minute_k_window.show()

  34.     def closeEvent(self, event):
  35.         # 子窗口关闭时,关闭 MinuteK 窗口(如果存在)
  36.         if self.minute_k_window:
  37.             self.minute_k_window.close()
  38.         super().closeEvent(event)

  39. class MainWindow(QMainWindow):
  40.     def __init__(self):
  41.         super().__init__()
  42.         self.setWindowTitle("主窗口")
  43.         self.setGeometry(100, 100, 800, 600)

  44.         self.mdi_area = QMdiArea()
  45.         self.setCentralWidget(self.mdi_area)

  46.         self.createSubWindow()

  47.     def createSubWindow(self):
  48.         self.sub_window = CustomSubWindow()
  49.         self.mdi_area.addSubWindow(self.sub_window)
  50.         self.sub_window.show()

  51.     def closeEvent(self, event):
  52.         # 确保所有子窗口(包括子窗口的附属窗口)在主窗口关闭时也关闭
  53.         for sub_window in self.mdi_area.subWindowList():
  54.             sub_window.close()
  55.         super().closeEvent(event)

  56. class MinuteK(QWidget):
  57.     def __init__(self, parent=None):
  58.         super(MinuteK, self).__init__(parent)
  59.         self.init_ui()

  60.     def init_ui(self):
  61.         self.setWindowTitle("MinuteK 窗口")
  62.         self.setGeometry(200, 200, 400, 400)

  63.     def paintEvent(self, event):
  64.         qp = QPainter(self)
  65.         create_painter(qp, "red", 2).drawLine(50, 50, 100, 50)
  66.         qp.restore()

  67. if __name__ == "__main__":
  68.     app = QApplication(sys.argv)
  69.     mainWin = MainWindow()
  70.     mainWin.show()
  71.     sys.exit(app.exec())
复制代码


### 修改点总结:

1. **`MinuteK` 的生命周期管理:**
   - 如果 `MinuteK` 是独立窗口,我们通过设置 `Qt.WA_DeleteOnClose` 属性,确保在窗口关闭后系统释放。

2. **主窗口的关闭管理:**
   - 在 `MainWindow` 的 `closeEvent` 方法中,遍历所有子窗口并显式关闭,这样与主窗口关联的窗口都会自动销毁。

3. **子窗口的关闭管理:**
   - 在 `CustomSubWindow` 的 `closeEvent` 中,检查并关闭 `MinuteK` 窗口,确保不留残留窗口。

### 运行结果:
- 双击子窗口会打开独立的 `MinuteK` 窗口。
- 关闭子窗口时,`MinuteK` 会自动关闭。
- 关闭主窗口时,所有子窗口与 `MinuteK` 也会自动关闭。

这个设计简洁并且稳定,确保所有窗口之间的对象关系和生命周期管理无缝衔接。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2025-1-23 09:52:28 | 显示全部楼层
要实现 `MinuteK` 窗口跟随主窗口关闭,你可以将 `MinuteK` 窗口设置为主窗口或子窗口的子对象。通过这种方式,当主窗口或子窗口被销毁时,`MinuteK` 窗口也会自动销毁。

以下是修改后的代码,你可以参考:


  1. from PySide6.QtCore import *
  2. from PySide6.QtGui import *
  3. from PySide6.QtWidgets import *
  4. import sys

  5. def create_painter(qp, color, width):
  6.     qp.save()
  7.     pen = QPen(QColor(color), width)
  8.     qp.setPen(pen)
  9.     return qp

  10. class CustomSubWindow(QMdiSubWindow):
  11.     def __init__(self, parent=None):
  12.         super().__init__(parent)
  13.         self.setWindowTitle("子窗口")
  14.         self.a = 0

  15.         self.initUI()

  16.     def initUI(self):
  17.         self.label = QLabel("双击子窗口中的任意位置", self)
  18.         layout = QVBoxLayout()
  19.         layout.addWidget(self.label)
  20.         container = QWidget()
  21.         container.setLayout(layout)
  22.         self.setWidget(container)

  23.     def mouseDoubleClickEvent(self, event: QMouseEvent):
  24.         if event.button() == Qt.LeftButton:
  25.             self.a += 1
  26.             print("子窗口被双击了", self.a)
  27.             self.label.setText("双击事件已捕获")
  28.             # 创建并显示 MinuteK 窗口,并将其设置为子窗口的子对象
  29.             self.minute_k_window = MinuteK(parent=self)
  30.             self.minute_k_window.show()

  31. class MainWindow(QMainWindow):
  32.     def __init__(self):
  33.         super().__init__()
  34.         self.setWindowTitle("主窗口")
  35.         self.setGeometry(100, 100, 800, 600)

  36.         self.mdi_area = QMdiArea()
  37.         self.setCentralWidget(self.mdi_area)

  38.         self.createSubWindow()

  39.     def createSubWindow(self):
  40.         self.sub_window = CustomSubWindow(parent=self)
  41.         self.mdi_area.addSubWindow(self.sub_window)
  42.         self.sub_window.show()

  43. class MinuteK(QWidget):
  44.     def __init__(self, parent=None):
  45.         super(MinuteK, self).__init__(parent)
  46.         self.init_ui()

  47.     def init_ui(self):
  48.         self.setWindowTitle("MinuteK 窗口")
  49.         self.setGeometry(100, 100, 400, 400)

  50.     def paintEvent(self, event):
  51.         qp = QPainter(self)
  52.         create_painter(qp, Qt.red, 2).drawLine(50, 50, 100, 50)
  53.         qp.restore()

  54. if __name__ == "__main__":
  55.     app = QApplication(sys.argv)
  56.     mainWin = MainWindow()
  57.     mainWin.show()
  58.     sys.exit(app.exec())
复制代码


主要改动点:
  • 在 `mouseDoubleClickEvent` 中,创建 `MinuteK` 窗口时,增加了 `parent=self` 参数,将 `MinuteK` 窗口设置为当前子窗口的子对象。
  • 通过设置父子关系,保证当主窗口或子窗口被销毁时,`MinuteK` 窗口会自动销毁。


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-23 10:03:31 | 显示全部楼层
MinuteK` 窗口设置为当前子窗口的子对象,将不显示MinuteK窗口
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-23 10:03:50 | 显示全部楼层
rxts 发表于 2025-01-23 10:03
MinuteK` 窗口设置为当前子窗口的子对象,将不显示Min ...


你说得对,在设置 `MinuteK` 为子窗口的子对象时,`MinuteK` 将嵌套在子窗口的范围内,导致 `MinuteK` 不再独立显示。如果你希望 `MinuteK` 保持为独立窗口,但仍然跟随主窗口(或子窗口)一起销毁,可以通过监控主窗口或子窗口的关闭事件,并在主窗口或子窗口关闭后主动关闭 `MinuteK`。

下面是修改后的代码,其中使用信号连接的方式,使 `MinuteK` 窗口独立显示,但跟随主窗口或子窗口销毁:

  1. from PySide6.QtCore import *
  2. from PySide6.QtGui import *
  3. from PySide6.QtWidgets import *
  4. import sys

  5. def create_painter(qp, color, width):
  6.     qp.save()
  7.     pen = QPen(QColor(color), width)
  8.     qp.setPen(pen)
  9.     return qp

  10. class CustomSubWindow(QMdiSubWindow):
  11.     def __init__(self, parent=None):
  12.         super().__init__(parent)
  13.         self.setWindowTitle("子窗口")
  14.         self.a = 0
  15.         self.minute_k_window = None  # 用于保存 MinuteK 窗口的引用
  16.         self.initUI()

  17.     def initUI(self):
  18.         self.label = QLabel("双击子窗口中的任意位置", self)
  19.         layout = QVBoxLayout()
  20.         layout.addWidget(self.label)
  21.         container = QWidget()
  22.         container.setLayout(layout)
  23.         self.setWidget(container)

  24.     def mouseDoubleClickEvent(self, event: QMouseEvent):
  25.         if event.button() == Qt.LeftButton:
  26.             self.a += 1
  27.             print("子窗口被双击了", self.a)
  28.             self.label.setText("双击事件已捕获")
  29.             # 创建并显示 MinuteK 窗口
  30.             if self.minute_k_window is None:
  31.                 self.minute_k_window = MinuteK()
  32.                 self.minute_k_window.show()

  33.     def closeEvent(self, event):
  34.         # 当子窗口关闭时,检查并关闭 MinuteK 窗口
  35.         if self.minute_k_window and self.minute_k_window.isVisible():
  36.             self.minute_k_window.close()
  37.         super().closeEvent(event)

  38. class MainWindow(QMainWindow):
  39.     def __init__(self):
  40.         super().__init__()
  41.         self.setWindowTitle("主窗口")
  42.         self.setGeometry(100, 100, 800, 600)

  43.         self.mdi_area = QMdiArea()
  44.         self.setCentralWidget(self.mdi_area)

  45.         self.createSubWindow()

  46.     def createSubWindow(self):
  47.         self.sub_window = CustomSubWindow()
  48.         self.mdi_area.addSubWindow(self.sub_window)
  49.         self.sub_window.show()

  50. class MinuteK(QWidget):
  51.     def __init__(self, parent=None):
  52.         super(MinuteK, self).__init__(parent)
  53.         self.init_ui()

  54.     def init_ui(self):
  55.         self.setWindowTitle("MinuteK 窗口")
  56.         self.setGeometry(100, 100, 400, 400)

  57.     def paintEvent(self, event):
  58.         qp = QPainter(self)
  59.         create_painter(qp, Qt.red, 2).drawLine(50, 50, 100, 50)
  60.         qp.restore()

  61. if __name__ == "__main__":
  62.     app = QApplication(sys.argv)
  63.     mainWin = MainWindow()
  64.     mainWin.show()
  65.     sys.exit(app.exec())
复制代码


### 修改点和实现方式:

1. **保持 `MinuteK` 窗口为独立窗口:**
   `MinuteK` 不再作为 `CustomSubWindow` 的子对象,而是独立显示。

2. **通过 `closeEvent` 信号管理窗口销毁:**
   在 `CustomSubWindow` 的 `closeEvent` 方法中,检查 `MinuteK` 是否存在且可见,如果存在则主动关闭它。

这样,`MinuteK` 窗口在 `CustomSubWindow` 或 `MainWindow` 被关闭时,会自动关闭,且 `MinuteK` 保持为独立窗口显示。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-1-23 10:20:33 | 显示全部楼层
还是不行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2025-1-23 10:21:45 | 显示全部楼层    本楼为最佳答案   


如果你希望 `MinuteK` 窗口保持独立显示,并跟随主窗口一起关闭,推荐的办法是通过显式地设置子窗口和独立窗口的生命周期管理关系。以下提供一个可靠的解决方案,保证 `MinuteK` 窗口跟随主窗口或子窗口关闭。

请使用以下代码:

  1. from PySide6.QtCore import *
  2. from PySide6.QtGui import *
  3. from PySide6.QtWidgets import *
  4. import sys

  5. def create_painter(qp, color, width):
  6.     qp.save()
  7.     pen = QPen(QColor(color), width)
  8.     qp.setPen(pen)
  9.     return qp

  10. class CustomSubWindow(QMdiSubWindow):
  11.     def __init__(self, parent=None):
  12.         super().__init__(parent)
  13.         self.setWindowTitle("子窗口")
  14.         self.a = 0
  15.         self.minute_k_window = None  # 用于保存 MinuteK 窗口的引用
  16.         self.initUI()

  17.     def initUI(self):
  18.         self.label = QLabel("双击子窗口中的任意位置", self)
  19.         layout = QVBoxLayout()
  20.         layout.addWidget(self.label)
  21.         container = QWidget()
  22.         container.setLayout(layout)
  23.         self.setWidget(container)

  24.     def mouseDoubleClickEvent(self, event: QMouseEvent):
  25.         if event.button() == Qt.LeftButton:
  26.             self.a += 1
  27.             print("子窗口被双击了", self.a)
  28.             self.label.setText("双击事件已捕获")
  29.             if not self.minute_k_window:
  30.                 # 创建并显示 MinuteK 窗口
  31.                 self.minute_k_window = MinuteK()
  32.                 self.minute_k_window.setAttribute(Qt.WA_DeleteOnClose)  # 让窗口在关闭时自动销毁
  33.             self.minute_k_window.show()

  34.     def closeEvent(self, event):
  35.         # 子窗口关闭时,关闭 MinuteK 窗口(如果存在)
  36.         if self.minute_k_window:
  37.             self.minute_k_window.close()
  38.         super().closeEvent(event)

  39. class MainWindow(QMainWindow):
  40.     def __init__(self):
  41.         super().__init__()
  42.         self.setWindowTitle("主窗口")
  43.         self.setGeometry(100, 100, 800, 600)

  44.         self.mdi_area = QMdiArea()
  45.         self.setCentralWidget(self.mdi_area)

  46.         self.createSubWindow()

  47.     def createSubWindow(self):
  48.         self.sub_window = CustomSubWindow()
  49.         self.mdi_area.addSubWindow(self.sub_window)
  50.         self.sub_window.show()

  51.     def closeEvent(self, event):
  52.         # 确保所有子窗口(包括子窗口的附属窗口)在主窗口关闭时也关闭
  53.         for sub_window in self.mdi_area.subWindowList():
  54.             sub_window.close()
  55.         super().closeEvent(event)

  56. class MinuteK(QWidget):
  57.     def __init__(self, parent=None):
  58.         super(MinuteK, self).__init__(parent)
  59.         self.init_ui()

  60.     def init_ui(self):
  61.         self.setWindowTitle("MinuteK 窗口")
  62.         self.setGeometry(200, 200, 400, 400)

  63.     def paintEvent(self, event):
  64.         qp = QPainter(self)
  65.         create_painter(qp, "red", 2).drawLine(50, 50, 100, 50)
  66.         qp.restore()

  67. if __name__ == "__main__":
  68.     app = QApplication(sys.argv)
  69.     mainWin = MainWindow()
  70.     mainWin.show()
  71.     sys.exit(app.exec())
复制代码


### 修改点总结:

1. **`MinuteK` 的生命周期管理:**
   - 如果 `MinuteK` 是独立窗口,我们通过设置 `Qt.WA_DeleteOnClose` 属性,确保在窗口关闭后系统释放。

2. **主窗口的关闭管理:**
   - 在 `MainWindow` 的 `closeEvent` 方法中,遍历所有子窗口并显式关闭,这样与主窗口关联的窗口都会自动销毁。

3. **子窗口的关闭管理:**
   - 在 `CustomSubWindow` 的 `closeEvent` 中,检查并关闭 `MinuteK` 窗口,确保不留残留窗口。

### 运行结果:
- 双击子窗口会打开独立的 `MinuteK` 窗口。
- 关闭子窗口时,`MinuteK` 会自动关闭。
- 关闭主窗口时,所有子窗口与 `MinuteK` 也会自动关闭。

这个设计简洁并且稳定,确保所有窗口之间的对象关系和生命周期管理无缝衔接。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-6 05:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表