2012-08-10 193 views
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:那太好了,就像我現在want.And還有另一個問題:

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」不能triggerd但所有其他事件可以。出現這種情況:macosx後端會忽略多個mpl_connect()調用 https://github.com/matplotlib/matplotlib/pull/585, 但我認爲這與我不一樣。 我得到cid0,1,2,3,4這是不同的彼此

那麼,任何想法可以分享?我一個很瘋狂,現在..... 以下是我的代碼,U可以測試它如果u有同樣的問題:

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明確地SETFOCUS,也許如果不是:) 細節ü可以檢查https://github.com/matplotlib/matplotlib/issues/707

+1

你QT直接需要什麼?我認爲使用matplotlib [事件處理](http://matplotlib.sourceforge.net/users/event_handling.html#event-handling-and-picking)會更簡單,尤其是'motion_notify_event'。 – bmu 2012-08-10 13:52:27

+0

mpl_connect聽起來不錯,我會試試看。 – tianli 2012-08-11 13:49:12

+0

嗨,sjwarner 我可以使用圖上的mpl_connect從matplotlib.backends.backend_qt4agg,如果是的話,可以給我一個例子。我編寫了一個腳本,但它沒有工作:( – tianli 2012-08-12 08:18:28

回答

0

的問題...你想改變光標在你的小部件上的樣子?如果是的話,最簡單的辦法就是做完全刪除了的paintEvent的,並添加到的setCursor您的init方法:

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

這會告訴Qt來使用十字光標只要鼠標移到特定的部件。這實際上會取代箭頭(可能或不可能是你想要的)。如果這不是你想要的,我會建議你做一些你創建一個你想要的PNG圖像的東西,創建一個子QLabel,並在你的mouseMoveEvent中移動子控件。

如果您需要更多的幫助,請幫助我知道。

+0

TKS。事實上,我想實現這個功能:cursor = Cursor(ax,useblit = True,color ='red',linewidth = 2) – tianli 2012-08-11 03:11:02

2

這裏是一個使用matplotlib event handling的示例(但是我想知道是否真的有用第二個遊標)。

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() 

screenshot

相關問題