rxts 发表于 2025-1-17 09:51:03

通过调用实例方法的子窗口如何保持可见性

from PySide6.QtWidgets import *

通过调用self.createAnnouncementWindow()函数的方式创建的子窗口,要如何才能保持:在与其他窗口交互时,
createAnnouncementWindow()窗口依旧保持可见性,在保持可见性的同时,下面的123功能不能收到影响

1. 弹出窗口可以跟随主窗口移动,2.在主窗口关闭时也随之关闭,3.不影响与其他窗口的交互
class MainWindowA(QMainWindow):
    def __init__(self, parent=None):
      super().__init__(parent)
      self.init_ui()
      
    def init_ui(self):
      self.setWindowTitle("主窗口 B")
      screen = QApplication.primaryScreen().geometry()
      self.screenWidth = screen.width()
      self.screenHeight = screen.height()
      self.setGeometry(0, 0, self.screenWidth, self.screenHeight)

      self.createAnnouncementWindow()    # 创建公告子窗口

    def resizeEvent(self, event):
      super().resizeEvent(event)
      new_size = event.size()
      self.width = new_size.width()
      self.height = new_size.height()

      self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))# 公告窗口
      self.subWindow.move(0, int(self.height * 0.8))
      if self.subWindow and self.subWindow.isVisible():
            self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))# 公告窗口
            self.subWindow.move(0, int(self.height * 0.8))

    def main_width_height(self):
      if self.width:
            return self.width, self.height

    def createAnnouncementWindow(self):    # 创建公告窗口
      self.announcementWindow = AnnouncementWindow(self.mdi_area)
      self.subWindow = self.mdi_area.addSubWindow(self.announcementWindow)
      self.subWindow.show()
      self.subWindow.destroyed.connect(self.subWindowDestroyed)# 监听子
    def subWindowDestroyed(self):
      # 子窗口被销毁时,将 self.subWindow 设置为 None
      self.subWindow = None
    def toggleSubWindow(self):
      if self.subWindow is None:
            # 如果子窗口已经被关闭,重新创建它
            self.createAnnouncementWindow()
            self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))# 调整子窗口大小
            self.subWindow.move(0, int(self.height * 0.8))
      elif self.subWindow.isVisible():
            self.subWindow.hide()
      else:
            self.subWindow.show()

FishC 发表于 2025-1-17 09:51:18

要实现公告窗口在与其他窗口交互时保持可见性,同时满足以下要求:

1. 弹出窗口可以跟随主窗口移动。
2. 在主窗口关闭时也随之关闭。
3. 不影响与其他窗口的交互。

可以将子窗口设置为 Qt.Tool 窗口类型。这样子窗口不会抢占主窗口的焦点,同时满足其他要求。您可以尝试以下修改:

from PySide6.QtWidgets import QApplication, QMainWindow, QMdiArea, QToolWindow, QWidget, QVBoxLayout, QLabel


class AnnouncementWindow(QWidget):
    def __init__(self, parent=None):
      super().__init__(parent)
      self.setWindowFlags(self.windowFlags() | Qt.Tool)# 设置为Tool窗口
      self.setWindowTitle("公告窗口")
      layout = QVBoxLayout()
      layout.addWidget(QLabel("公告内容"))
      self.setLayout(layout)


class MainWindowA(QMainWindow):
    def __init__(self, parent=None):
      super().__init__(parent)
      self.mdi_area = QMdiArea(self)
      self.setCentralWidget(self.mdi_area)
      self.init_ui()

    def init_ui(self):
      self.setWindowTitle("主窗口 B")
      screen = QApplication.primaryScreen().geometry()
      self.screenWidth = screen.width()
      self.screenHeight = screen.height()
      self.setGeometry(0, 0, self.screenWidth, self.screenHeight)

      self.createAnnouncementWindow()

    def resizeEvent(self, event):
      super().resizeEvent(event)
      new_size = event.size()
      self.width = new_size.width()
      self.height = new_size.height()

      self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))
      self.subWindow.move(0, int(self.height * 0.8))
      if self.subWindow and self.subWindow.isVisible():
            self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))
            self.subWindow.move(0, int(self.height * 0.8))

    def main_width_height(self):
      if self.width:
            return self.width, self.height

    def createAnnouncementWindow(self):
      self.announcementWindow = AnnouncementWindow(self)
      self.subWindow = self.mdi_area.addSubWindow(self.announcementWindow)
      self.subWindow.setWindowFlags(Qt.Tool)# 与主窗口一起移动、关闭
      self.subWindow.show()
      self.subWindow.destroyed.connect(self.subWindowDestroyed)

    def subWindowDestroyed(self):
      self.subWindow = None

    def toggleSubWindow(self):
      if self.subWindow is None:
            self.createAnnouncementWindow()
            self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))
            self.subWindow.move(0, int(self.height * 0.8))
      elif self.subWindow.isVisible():
            self.subWindow.hide()
      else:
            self.subWindow.show()

把公告窗口设置为 Qt.Tool 类型可以保证它不会成为主窗口焦点的一部分,这样即使用户切换到其他应用程序后再返回,公告窗口也能保持在前台。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

rxts 发表于 2025-1-17 10:42:09

FishC 发表于 2025-1-17 09:51
要实现公告窗口在与其他窗口交互时保持可见性,同时满足以下要求:

1. 弹出窗口可以跟随主窗口移动。


我试了,当只有一个子窗口createAnnouncementWindow时,没有问题,但是有多个子窗口时,我与其他子窗口互动时,createAnnouncementWindow会被隐藏

FishC 发表于 2025-1-17 10:42:40

rxts 发表于 2025-01-17 10:42
FishC 发表于 2025-1-17 09:51
要实现公告窗口在与其 ...

如果希望在有多个子窗口的情况下,`createAnnouncementWindow` 依然保持可见,你可以考虑使用 `Qt.WindowStaysOnTopHint` 使其始终位于其他子窗口之上。这将确保公告窗口始终可见,而不会干扰其他窗口的交互。

可以按照以下方式进行设置:

from PySide6.QtWidgets import QMainWindow, QMdiArea, QWidget, QVBoxLayout, QLabel, QApplication
from PySide6.QtCore import Qt

class AnnouncementWindow(QWidget):
    def __init__(self, parent=None):
      super().__init__(parent)
      self.setWindowFlags(Qt.Tool | Qt.WindowStaysOnTopHint)# 保持在前
      self.setWindowTitle("公告窗口")
      layout = QVBoxLayout()
      layout.addWidget(QLabel("公告内容"))
      self.setLayout(layout)

class MainWindowA(QMainWindow):
    def __init__(self, parent=None):
      super().__init__(parent)
      self.mdi_area = QMdiArea(self)
      self.setCentralWidget(self.mdi_area)
      self.init_ui()

    def init_ui(self):
      self.setWindowTitle("主窗口 B")
      screen = QApplication.primaryScreen().geometry()
      self.screenWidth = screen.width()
      self.screenHeight = screen.height()
      self.setGeometry(0, 0, self.screenWidth, self.screenHeight)

      self.createAnnouncementWindow()

    def resizeEvent(self, event):
      super().resizeEvent(event)
      new_size = event.size()
      self.width = new_size.width()
      self.height = new_size.height()

      self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))
      self.subWindow.move(0, int(self.height * 0.8))
      if self.subWindow and self.subWindow.isVisible():
            self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))
            self.subWindow.move(0, int(self.height * 0.8))

    def createAnnouncementWindow(self):
      self.announcementWindow = AnnouncementWindow(self)
      self.subWindow = self.mdi_area.addSubWindow(self.announcementWindow)
      self.subWindow.setWindowFlags(Qt.Tool | Qt.WindowStaysOnTopHint)
      self.subWindow.show()
      self.subWindow.destroyed.connect(self.subWindowDestroyed)

    def subWindowDestroyed(self):
      self.subWindow = None

    def toggleSubWindow(self):
      if self.subWindow is None:
            self.createAnnouncementWindow()
            self.subWindow.resize(int(self.width * 0.75), int(self.height * 0.169))
            self.subWindow.move(0, int(self.height * 0.8))
      elif self.subWindow.isVisible():
            self.subWindow.hide()
      else:
            self.subWindow.show()

if __name__ == '__main__':
    app = QApplication([])
    window = MainWindowA()
    window.show()
    app.exec()

这个代码使用了 `...` 标签来包裹代码段,在 Discuz! 论坛上可以清晰地展现代码块。通过加上 `Qt.WindowStaysOnTopHint`,公告窗口可以始终保持在其他子窗口的前面。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

rxts 发表于 2025-1-17 11:07:53

FishC 发表于 2025-1-17 10:42
如果希望在有多个子窗口的情况下,`createAnnouncementWindow` 依然保持可见,你可以考虑使用 `Qt.Wind ...

'
    def createAnnouncementWindow(self):    # 创建公告窗口
      self.announcementWindow = AnnouncementWindow(self.mdi_area)
      self.subWindow = self.mdi_area.addSubWindow(self.announcementWindow)
      self.subWindow.setWindowFlags(Qt.Tool | Qt.WindowStaysOnTopHint)
      self.subWindow.show()
      self.subWindow.destroyed.connect(self.subWindowDestroyed)# 监听子
'
可以了,但是我有一点不明白,在createAnnouncementWindow函数中设置一次self.subWindow.setWindowFlags(Qt.Tool | Qt.WindowStaysOnTopHint)就有效果,为什么要在AnnouncementWindow类中在设置一次,这样有什么好处吗?

FishC 发表于 2025-1-17 11:08:22

rxts 发表于 2025-01-17 11:07
FishC 发表于 2025-1-17 10:42
如果希望在有多个子窗 ...

在 `createAnnouncementWindow` 函数中,您已经通过 `self.subWindow.setWindowFlags(Qt.Tool | Qt.WindowStaysOnTopHint)` 设置了子窗口的窗口标志,这是为了确保子窗口在创建时具有指定的属性。

在 `AnnouncementWindow` 类中再次设置窗口标志通常是为了在特殊情况下应用此类标志。例如,假设 `AnnouncementWindow` 类可能在其他上下文中使用,并且在某些情况下需要保持在顶部,那么直接在类中设置 `Qt.Tool | Qt.WindowStaysOnTopHint` 就很方便。

但是,如果 `AnnouncementWindow` 仅在当前场景中使用,并且其行为完全由 `createAnnouncementWindow` 函数控制,您可以只在 `createAnnouncementWindow` 中设置标志。在此情况下,直接在 `AnnouncementWindow` 类中设置标志并无特别必要。这只是一种冗余的保险。

总结来说:


[*]在 `createAnnouncementWindow` 中设置一次通常已经足够。
[*]在 `AnnouncementWindow` 中设置用于多次复用该类且需要相同窗口标志的场景。


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

rxts 发表于 2025-1-17 11:44:56

FishC 发表于 2025-1-17 11:08
在 `createAnnouncementWindow` 函数中,您已经通过 `self.subWindow.setWindowFlags(Qt.Tool | Qt.Win ...

明白了,多谢

FishC 发表于 2025-1-17 11:45:15

rxts 发表于 2025-01-17 11:44
FishC 发表于 2025-1-17 11:08
在 `createAnnounceme ...

不客气!如果您还有其他问题或需要进一步的帮助,请随时提问。随时乐意为您提供支持!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 通过调用实例方法的子窗口如何保持可见性