2

我想在我paintEvent()的鼠标上画一个十字。我通过pyqt使用python。

我正在使用下面的代码,但结果并不好。

from __future__ import division
import sys
import platform

# Qt4 bindings for core Qt functionalities (non-GUI)
import PyQt4.QtCore as  QtCore

# Python Qt4 bindings for GUI objects
import PyQt4.QtGui as QtGui
from PyQt4.QtGui import *
from PyQt4.QtCore import *
# import the Qt4Agg FigureCanvas object, that binds Figure to
# Qt4Agg backend. It also inherits from QWidget
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
# Matplotlib Figure object
from matplotlib.figure import Figure

class C_MplCanvas(FigureCanvas):
    def __init__(self):      
        # setup Matplotlib Figure and Axis
        self.fig = Figure()
        #self.cursor = Cursor()
        self.fig.set_facecolor('black')
        self.fig.set_edgecolor('black')
        #self.ax = self.fig.add_subplot(111)
        #self.ax.patch.set_facecolor('black')
        # initialization of the canvas
        FigureCanvas.__init__(self, self.fig)
        #super(FigureCanvas, self).__init__(self.fig)


        # we define the widget as expandable
        FigureCanvas.setSizePolicy(self,
                                   QtGui.QSizePolicy.Expanding,
                                   QtGui.QSizePolicy.Expanding)
        # notify the system of updated policy
        FigureCanvas.updateGeometry(self)

        self.xx=0
        self.yy=0
        self.justDoubleClicked=False

    def contextMenuEvent(self, event):
        menu = QMenu(self)
        oneAction = menu.addAction("&One")
        twoAction = menu.addAction("&Two")
        self.connect(oneAction, SIGNAL("triggered()"), self.one)
        self.connect(twoAction, SIGNAL("triggered()"), self.two)
        '''
        if not self.message:
            menu.addSeparator()
            threeAction = menu.addAction("Thre&e")
            self.connect(threeAction, SIGNAL("triggered()"),
                         self.three)
        '''
        menu.exec_(event.globalPos())


    def one(self):
        self.message = QString("Menu option One")
        self.update()


    def two(self):
        self.message = QString("Menu option Two")
        self.update()


    def three(self):
        self.message = QString("Menu option Three")
        self.update()


    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.TextAntialiasing)
        #painter.drawText(self.rect(), Qt.AlignCenter, text)
        #

        #painter.setPen('red')

        pen=painter.pen()
        painter.setPen(QColor(255, 0, 0))

        painter.drawLine(self.xx-100,self.yy,self.xx+100,self.yy)
        painter.drawLine(self.xx,self.yy-100,self.xx,self.yy+100)
        self.update()

    def mouseReleaseEvent(self, event):
        if self.justDoubleClicked:
            self.justDoubleClicked = False
        else:
            self.setMouseTracking(not self.hasMouseTracking())
            self.update()


    def mouseMoveEvent(self, event):      
        self.xx=event.pos().x()
        self.yy=event.pos().y()
        self.update()




class C_MPL(QWidget):

    def __init__(self, parent = None):
        # initialization of Qt MainWindow widget
        super(C_MPL, self).__init__(parent)
        #QtGui.QWidget.__init__(self, parent)

        # instantiate a widget, it will be the main one
        #self.main_widget = QtGui.QWidget(self)
        #vbl = QtGui.QVBoxLayout(self.main_widget)
        # set the canvas to the Matplotlib widget
        self.canvas = C_MplCanvas()

        # create a vertical box layout
        self.vbl = QtGui.QVBoxLayout()
        # add mpl widget to vertical box
        self.vbl.addWidget(self.canvas)
        # set the layout to th vertical box
        self.setLayout(self.vbl)




if __name__ == "__main__":
    import sys

    '''
    def valueChanged(a, b):
        print a, b
    '''
    app = QApplication(sys.argv)
    form = C_MPL()
    #form.connect(form, SIGNAL("valueChanged"), valueChanged)
    form.setWindowTitle("C_MPL")
    #form.move(0, 0)
    form.show()
    #form.resize(400, 400)
    app.exec_()

@bmu:太好了,就像我想要的那样。现在还有另一个问题:

    cid0=self.mpl_connect('axes_enter_event', self.enter_axes)
    cid1=self.mpl_connect('button_press_event', self.onpick)
    cid2=self.mpl_connect('motion_notify_event', self.onmove)
    cid3=self.mpl_connect('draw_event', self.clear)
    cid4=self.mpl_connect('key_press_event',self.press)

奇怪的是“key_press_event”不能被触发,但所有其他事件都可以。有 ra 案例:macosx 后端忽略了多个 mpl_connect() 调用 https://github.com/matplotlib/matplotlib/pull/585,但我认为这与我不同。我得到了 cid0,1,2,3,4 彼此不同

那么,有什么想法可以分享吗?我现在非常疯狂......以下是我的代码,如果你有同样的问题,你可以测试它:

import sys
import platform

from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4 import NavigationToolbar2QT as NavigationToolbar
import time
from PyQt4.QtCore import *
from PyQt4.QtGui import *




#Just a test 

class MplCanvas(FigureCanvas):

    def __init__(self):

        # initialization of the canvas
        self.fig=Figure()
        FigureCanvas.__init__(self,self.fig )



        self.ax = self.fig.add_axes([.15, .15, .75, .75])
        self.canvas = self.ax.figure.canvas     



        #my added
        #self.ax = self.fig.add_axes([.15, .15, .75, .75])
        #cursor = C_Cursor(self.LvsT, useblit=True, color='red', linewidth=2 )



        x=np.arange(0,20,0.1)

        self.ax.plot(x,x*x,'o')
        self.ax.set_xlim(-2,2)
        self.ax.set_ylim(-2,2) 

        self.visible = True
        self.horizOn = True
        self.vertOn = True
        self.useblit = True

        #if self.useblit:
            #lineprops['animated'] = True


        self.lineh = self.ax.axhline(self.ax.get_ybound()[0], visible=False)
        self.linev = self.ax.axvline(self.ax.get_xbound()[0], visible=False)

        self.background = None
        self.needclear = False

        self.count = 0

        cid0=self.mpl_connect('axes_enter_event', self.enter_axes)
        cid1=self.mpl_connect('button_press_event', self.onpick)
        cid2=self.mpl_connect('motion_notify_event', self.onmove)
        cid3=self.mpl_connect('draw_event', self.clear)
        cid4=self.mpl_connect('key_press_event',self.press)

        self.draw()

    def clear(self, event):
        'clear the cursor'
        if self.useblit:
            self.background = self.canvas.copy_from_bbox(self.ax.bbox)
        self.linev.set_visible(False)
        self.lineh.set_visible(False)

    def onmove(self, event):
        'on mouse motion draw the cursor if visible'
        print("move")
        if event.inaxes != self.ax:
            self.linev.set_visible(False)
            self.lineh.set_visible(False)

            if self.needclear:
                self.canvas.draw()
                self.needclear = False
            return
        self.needclear = True
        if not self.visible: return
        self.linev.set_xdata((event.xdata, event.xdata))

        self.lineh.set_ydata((event.ydata, event.ydata))
        self.linev.set_visible(self.visible and self.vertOn)
        self.lineh.set_visible(self.visible and self.horizOn)


        self._update()




    def _update(self):

        if self.useblit:
            if self.background is not None:
                self.canvas.restore_region(self.background)
            self.ax.draw_artist(self.linev)
            self.ax.draw_artist(self.lineh)
            self.canvas.blit(self.ax.bbox)
        else:

            self.canvas.draw_idle()

        return False

        #



    def enter_axes(self,event):

        print "Enter"

    def onpick(self,event):
        print "click"
        print 'you pressed', event.canvas

        a = np.arange(10)
        print a
        print self.count

        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.plot(a)    
        fig.show()

    def press(self,event):
        print ('press', event.key)
        self.fig.canvas.draw()




class MplWidget(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)        

        self.vbl = QtGui.QVBoxLayout()
        self.canvas = MplCanvas()
        self.vbl.addWidget(self.canvas)
        self.setLayout(self.vbl)




if __name__ == "__main__":

    app = QApplication(sys.argv)
    form = MplWidget()
    form.show()
    #form.resize(400, 400)
    app.exec_()

@all:谢谢。添加后我解决了这个问题:

self.canvas.setFocusPolicy( Qt.ClickFocus )
self.canvas.setFocus()

也许这是一个小错误 bcs 我需要明确地集中在 cavans 上,也许如果不是:) 细节你可以检查https://github.com/matplotlib/matplotlib/issues/707

4

2 回答 2

2

这是一个使用 matplotlib事件处理的示例(但是我想知道,拥有第二个光标之类的东西是否真的有用)。

import numpy as np
import matplotlib.pyplot as plt 


class MouseCross(object):

    def __init__(self, ax, **kwargs):
        self.ax = ax
        self.line, = self.ax.plot([0], [0], visible=False, **kwargs)

    def show_cross(self, event):
        if event.inaxes == self.ax:
            self.line.set_data([event.xdata], [event.ydata])
            self.line.set_visible(True)
        else:
            self.line.set_visible(False)
        plt.draw()

if __name__ == '__main__':
    fig, ax = plt.subplots()
    ax.plot(np.random.random(100) * 10.0)
    # note that not every "normal" matplotlib marker will work
    # math symbols work fine
    cross = MouseCross(ax, marker=r'$\bigoplus$', markersize=30,
                       color='red',)
    fig.canvas.mpl_connect('motion_notify_event', cross.show_cross)
    plt.tight_layout()
    plt.show()

截屏

于 2012-08-12T09:41:39.380 回答
1

问题...您是否尝试更改光标在您的小部件上的外观?如果是这样,最简单的方法是完全摆脱 paintEvent,并将 setCursor 添加到您的 init 方法中:

class C_MplCanvas(FigureCanva):
    def __init__( self ):
        # setup code
        ...
        self.setCursor(Qt.CrossCursor)

这将告诉 Qt 在鼠标悬停在特定小部件上时使用交叉光标。这实际上将替换箭头(可能是也可能不是您想要的)。如果这不是你想要的,我建议你创建一个你想要的PNG图像,创建一个子QLabel,然后在你的mouseMoveEvent中移动子小部件。

如果您需要更多帮助,请让我知道。

于 2012-08-10T20:47:46.897 回答