You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5 QMdiArea多子窗口批量选中与指针获取技术问询

实现QMdiArea多子窗口Ctrl选中功能

嘿,要实现按住Ctrl键选中多个子窗口的需求,我们可以通过给QMdiArea添加事件过滤来跟踪鼠标点击事件,结合Ctrl键的状态维护一个选中窗口列表。下面是修改后的完整代码,关键部分我都加了注释:

from PyQt5.QtWidgets import QApplication, QMainWindow, QMdiArea, QAction, QMdiSubWindow, QTextEdit
from PyQt5.QtCore import Qt, QEvent
import sys

class MDIWindow(QMainWindow):
    count = 0
    def __init__(self):
        super().__init__()
        self.mdi = QMdiArea()
        self.setCentralWidget(self.mdi)
        # 维护选中的子窗口列表
        self.selected_windows = []
        # 给QMdiArea安装事件过滤器,用来捕捉点击事件
        self.mdi.installEventFilter(self)
        
        bar = self.menuBar()
        file = bar.addMenu("File")
        file.addAction("New")
        file.addAction("cascade")
        file.addAction("Tiled")
        file.addAction("selected_subwindows")
        file.triggered[QAction].connect(self.WindowTrig)
        self.setWindowTitle("MDI Application")

    def eventFilter(self, obj, event):
        # 只处理QMdiArea的鼠标左键点击事件
        if obj == self.mdi and event.type() == QEvent.MouseButtonPress and event.button() == Qt.LeftButton:
            # 获取点击位置对应的子窗口
            clicked_window = self.mdi.subWindowAt(event.pos())
            if not clicked_window:
                return super().eventFilter(obj, event)
            
            # 检查是否按住了Ctrl键
            ctrl_pressed = QApplication.keyboardModifiers() & Qt.ControlModifier
            
            if ctrl_pressed:
                # 如果按住Ctrl,切换该窗口的选中状态
                if clicked_window in self.selected_windows:
                    self.selected_windows.remove(clicked_window)
                    # 取消选中的视觉反馈:恢复默认样式
                    clicked_window.setStyleSheet("")
                else:
                    self.selected_windows.append(clicked_window)
                    # 选中的视觉反馈:添加蓝色边框
                    clicked_window.setStyleSheet("QMdiSubWindow { border: 2px solid blue; }")
            else:
                # 没有按住Ctrl,清空之前的选中,只保留当前窗口
                for win in self.selected_windows:
                    win.setStyleSheet("")
                self.selected_windows = [clicked_window]
                clicked_window.setStyleSheet("QMdiSubWindow { border: 2px solid blue; }")
            # 将点击的窗口设为活跃窗口(可选,根据你的需求调整)
            self.mdi.setActiveSubWindow(clicked_window)
        return super().eventFilter(obj, event)

    def WindowTrig(self, p):
        if p.text() == "New":
            MDIWindow.count = MDIWindow.count + 1
            sub = QMdiSubWindow()
            sub.setWidget(QTextEdit())
            sub.setWindowTitle("Sub Window" + str(MDIWindow.count))
            self.mdi.addSubWindow(sub)
            sub.show()
        if p.text() == "cascade":
            self.mdi.cascadeSubWindows()
        if p.text() == "Tiled":
            self.mdi.tileSubWindows()
        if p.text()=="selected_subwindows":
            # 打印选中窗口的指针
            print("选中的窗口指针列表:")
            for idx, win in enumerate(self.selected_windows):
                print(f"窗口 {idx+1}: {win}")
                # 获取窗口内的QTextEdit部件
                text_edit = win.widget()
                if isinstance(text_edit, QTextEdit):
                    print(f"  窗口内文本内容预览: {text_edit.toPlainText()[:50]}...")  # 只显示前50个字符

app = QApplication(sys.argv)
mdi =MDIWindow()
mdi.show()
app.exec_()

关键功能说明:

  • 选中状态管理:用self.selected_windows列表保存所有选中的子窗口,按住Ctrl点击时切换窗口的选中状态,不按Ctrl时自动清空之前的选中记录,只保留当前点击的窗口。
  • 视觉反馈:给选中的窗口添加蓝色边框,取消选中时恢复默认样式,让用户能直观看到哪些窗口处于选中状态。
  • 子窗口部件访问:通过win.widget()可以直接获取子窗口内的QTextEdit组件,后续你可以用它来做文本对比、内容同步等操作。
  • 事件过滤机制:给QMdiArea安装事件过滤器后,我们能精准捕捉到区域内的鼠标点击事件,从而判断用户点击的目标窗口,以及是否按住了Ctrl键。

这样修改后,你就可以按住Ctrl键点击多个子窗口,然后通过selected_subwindows菜单选项查看选中的窗口指针和对应的文本内容啦。

内容的提问来源于stack exchange,提问作者zezo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 17:52:38