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

在FigureCanvasQTAgg子类中添加RectangleSelector失效问题求助

解决Matplotlib RectangleSelector在FigureCanvasQTAgg子类中失效的问题

问题代码

from PySide6 import QtWidgets, QtCore
import PySide6.QtGui
import copy 
import numpy as np
import matplotlib #Library for creating static, animated, and interactive visualizations in Python
import matplotlib.pyplot as plt
from matplotlib.backend_tools import ToolBase, ToolToggleBase
from matplotlib.backend_bases import MouseButton #intEnum BACK = 8, FORWARD = 9, LEFT = 1, MIDDLE = 2, RIGHT = 3
from matplotlib.widgets import RectangleSelector 

matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg 

class ImageDisplayer(FigureCanvasQTAgg):
    
    def __init__(self,DisplayData=None):
        self.DisplayData=DisplayData
        self.Figure, self.Axis=plt.subplots(1, 1, constrained_layout=True)
        self.Figure.patch.set_facecolor([1,1,1,0.5])
        self.Axis.set_facecolor([1,1,1,0.1])

        super(ImageDisplayer, self).__init__(self.Figure) 

        self.RecSelector=RectangleSelector(self.Axis, self.onselect, interactive=True, state_modifier_keys=dict(move=' ', clear='escape', square='shift', center='ctrl'))
        self.Figure.canvas.mpl_connect("key_press_event", self.toggle_selector)

        plt.show() 
        
    def onselect(eclick, erelease):
        print(f'Starting position: ({eclick.xdata}, {eclick.ydata})')
        print(f'End position: ({erelease.xdata}, {erelease.ydata})')

    def toggle_selector(self,event):
        if event.key in ['Q', 'q'] and self.RecSelector.active:
            print("Rectangle selector deactivated")
            self.RecSelector.set_active(False)
        if event.key in ['A', 'a'] and not self.RecSelector.active:
            print('Rectangle selector activated')
            self.RecSelector.set_active(True)

ImageDisplayer()

问题分析与修复方案

以下是导致RectangleSelector失效的核心问题及修复方式:

  • 后端版本不匹配:PySide6对应Qt6版本,应指定Qt6Agg后端而非Qt5Agg,否则会出现兼容问题。
  • 混用plt.subplots与Qt画布:plt.subplots会创建独立画布,与继承的FigureCanvasQTAgg冲突,需直接创建Figure和Axes实例。
  • 缺少Qt应用入口:Qt程序必须通过QApplication启动,仅用plt.show()无法正常传递交互事件。
  • 类方法未绑定self:onselect作为类成员方法,必须将self作为第一个参数,否则无法被正确调用。

修复后的完整代码

from PySide6 import QtWidgets, QtCore
import numpy as np
import matplotlib
from matplotlib.figure import Figure
from matplotlib.axes import Axes
from matplotlib.widgets import RectangleSelector 

# 指定匹配PySide6的后端
matplotlib.use("Qt6Agg")
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg 

class ImageDisplayer(FigureCanvasQTAgg):
    def __init__(self, DisplayData=None):
        self.DisplayData = DisplayData
        
        # 直接创建Figure和Axes,避免与plt.subplots冲突
        self.Figure = Figure(constrained_layout=True)
        self.Axis: Axes = self.Figure.add_subplot(111)
        self.Figure.patch.set_facecolor([1,1,1,0.5])
        self.Axis.set_facecolor([1,1,1,0.1])
        
        # 绘制示例图像(方便测试选择功能)
        if self.DisplayData is None:
            self.DisplayData = np.random.rand(100, 100)
        self.Axis.imshow(self.DisplayData)

        super().__init__(self.Figure) 

        # 初始化RectangleSelector
        self.RecSelector = RectangleSelector(
            self.Axis, 
            self.onselect, 
            interactive=True, 
            state_modifier_keys=dict(move=' ', clear='escape', square='shift', center='ctrl')
        )
        self.Figure.canvas.mpl_connect("key_press_event", self.toggle_selector)

    # 添加self参数,绑定类实例
    def onselect(self, eclick, erelease):
        print(f'Starting position: ({eclick.xdata:.2f}, {eclick.ydata:.2f})')
        print(f'End position: ({erelease.xdata:.2f}, {erelease.ydata:.2f})')

    def toggle_selector(self, event):
        if event.key in ['Q', 'q'] and self.RecSelector.active:
            print("Rectangle selector deactivated")
            self.RecSelector.set_active(False)
        if event.key in ['A', 'a'] and not self.RecSelector.active:
            print('Rectangle selector activated')
            self.RecSelector.set_active(True)

if __name__ == "__main__":
    # 启动Qt应用程序
    app = QtWidgets.QApplication([])
    viewer = ImageDisplayer()
    viewer.show()
    app.exec()

关键修复说明

  1. 后端调整:切换为Qt6Agg后端,适配PySide6的Qt6环境。
  2. 画布创建:用Figure()和add_subplot()替代plt.subplots,确保画布与FigureCanvasQTAgg正确绑定。
  3. Qt应用入口:添加QApplication启动代码,保证交互事件正常流转。
  4. 方法绑定:给onselect方法添加self参数,使其成为合法的类成员方法。
  5. 测试图像:默认生成随机数组作为显示内容,方便直接验证选择功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:56:10