在 Matplotlib 画布上正确放置 Qmenu

Posted

技术标签:

【中文标题】在 Matplotlib 画布上正确放置 Qmenu【英文标题】:Correctly placing Qmenu on Matplotlib Canvas 【发布时间】:2015-02-06 06:43:08 【问题描述】:

当用户通过“button_press_event”点击画布时,我正在使用 QMenu 创建上下文菜单。但是,我在弄清楚如何将按钮按下事件的 x/y 坐标转换为正确的格式以便正确放置 Qmenu 时遇到了一些麻烦。

下面的代码可以工作,但是确定菜单位置的部分看起来有点难看,我想知道是否有更好的方法来放置 Qmenu。特别是我必须从画布高度中减去 Y 坐标的地方。这可以在某处用反转方法代替吗?

确定位置:

canvasSize = event.canvas.geometry()
Qpoint_click = event.canvas.mapToGlobal(QtCore.QPoint(event.x,canvasSize.height()-event.y))

完整代码:

import sys
from PyQt4 import QtGui, QtCore
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar

class menuTest(QtGui.QMainWindow):    
    def __init__(self):
        super(menuTest, self).__init__()        
        self.mplFig = MplGrapher() #Matplotlib plot
        self.mplFig.canvas.mpl_connect('button_press_event', self.on_press)       
        self.setCentralWidget(self.mplFig) 
        self.show()

    def on_press(self,event):
        canvasSize = event.canvas.geometry()
        Qpoint_click = event.canvas.mapToGlobal(QtCore.QPoint(event.x,canvasSize.height()-event.y))
        self.lineMenu= QtGui.QMenu()
        self.lineMenu.addAction("Test Menu")
        self.lineMenu.move(Qpoint_click)
        self.lineMenu.show()

class MplGrapher(QtGui.QWidget):
    def __init__(self,parent=None):
        super(MplGrapher, self).__init__(parent)
        self.initFigure()

    def initFigure(self):
        self.figure = Figure()
        self.canvas = FigureCanvas(self.figure)
        self.axL = self.figure.add_subplot(111)
        self.axL.grid(True)
        self.navbar = NavigationToolbar(self.canvas, self)
        self.layout = QtGui.QVBoxLayout()
        self.layout.addWidget(self.navbar)
        self.layout.addWidget(self.canvas)
        self.setLayout(self.layout)        

def main():    
    app = QtGui.QApplication(sys.argv)
    ex = menuTest()    
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

【问题讨论】:

【参考方案1】:

请参阅出色的 matplotlib 转换教程 http://matplotlib.org/users/transforms_tutorial.html 了解转换的说明。像这样的东西对我来说很好:

import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas

class menuTest(QtGui.QMainWindow):  

    def __init__(self):
        #....
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.canvasMenu = QtGui.QMenu(self)
        ca = QtGui.QAction('Menu item', self)
        ca.triggered.connect(self.menu_item_clicked)
        self.canvasMenu.addAction(ca)
        self.last_point = None

        self.canvas.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.canvas.customContextMenuRequested.connect(self.exec_canvas_menu)

    def exec_canvas_menu(self):
        self.last_point = point
        self.canvasMenu.exec_(self.canvas.mapToGlobal(point))

    def menu_item_clicked(self):
        if self.last_point is None: return
        ax = self.figure.gca()
        print ("Clicked at:", ax.transData.inverted().transform((self.last_point.x(), self.last_point.y())))

【讨论】:

以上是关于在 Matplotlib 画布上正确放置 Qmenu的主要内容,如果未能解决你的问题,请参考以下文章

我想用matplotlib在一个画布上写一些图表,使用pyqt5

matplotlib pyqt5画布上两个可拖动点之间的线

HTML5:在带有控件的视频上放置画布

在 Swift 中将 NSImage 放置在透明画布上

pyqt 中的多个嵌入式 matplotlib 画布在鼠标悬停时改变大小

Matplotlib 画布作为 numpy 数组伪影