set figure size (mpl) is not influence canvas and layout - python

I'm trying to adjust widget size to figure size. For some reason the size of the canvas and the widget is not changing. I tried to set SizePolicy of the container widget and the canvas, same result.
import sys
import matplotlib.pyplot as plt
from PyQt4 import QtGui
class CanvasOnWidget(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self._layout = QtGui.QVBoxLayout(self)
self._fig = plt.figure()
self._layout.addWidget(self._fig.canvas)
plt.plot(range(10),range(10))
self._fig.canvas.mpl_connect('button_press_event', self._resize)
def _resize(self, event):
w,h = self._fig.get_size_inches()
if event.button == 1: # left click
h-=1
elif event.button == 3: # right click
h+=1
self._fig.set_size_inches(w, h, forward=True)
self._fig.canvas.draw()
self._fig.canvas.flush_events()
print self.size()
print self._fig.canvas.size()
print self._fig.get_size_inches()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = CanvasOnWidget()
main.show()
sys.exit(app.exec_())

I guess you need to inform the widget about your desire to change its size.
This can be done using .resize. Due to there being a border around the canvas you need to take this border into account when setting the new widget size.
import sys
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from PyQt4 import QtGui
class CanvasOnWidget(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self._layout = QtGui.QVBoxLayout(self)
self.setLayout(self._layout)
self._fig = Figure()
self.canv = FigureCanvas(self._fig)
self._layout.addWidget(self.canv)
ax = self._fig.add_subplot(111)
ax.plot(range(10),range(10))
self._fig.canvas.mpl_connect('button_press_event', self._resize)
def _resize(self, event):
w,h = self._fig.get_size_inches()
dw = self.size().width()-w*self._fig.dpi
dh = self.size().height()-h*self._fig.dpi
if event.button == 1: # left click
h-=1
elif event.button == 3: # right click
h+=1
self._fig.set_size_inches(w, h, forward=True)
self._fig.canvas.draw_idle()
self.resize(w*100+dw,h*100+dh)
print self.size()
print self._fig.canvas.size()
print self._fig.get_size_inches()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
main = CanvasOnWidget()
main.show()
sys.exit(app.exec_())
Note that I have changed to code in order to place a Figure into a FigureCanvasQT. Using pyplot inside a Qt GUI will lead to problems.
However, if you want to use pyplot, the whole code can be simplified a lot.
import matplotlib.pyplot as plt
class Plot():
def __init__(self):
self._fig = plt.figure()
ax = self._fig.add_subplot(111)
ax.plot(range(10),range(10))
self._fig.canvas.mpl_connect('button_press_event', self._resize)
def _resize(self, event):
w,h = self._fig.get_size_inches()
if event.button == 1: # left click
h-=1
elif event.button == 3: # right click
h+=1
self._fig.set_size_inches(w, h, forward=True)
self._fig.canvas.draw_idle()
print self._fig.get_size_inches()
if __name__ == '__main__':
app = Plot()
plt.show()

Related

How to add a LabelItem to PlotItem

I want to make the label item of a plot clickable, that is, I can click the bottom or left label of a plot to call a menu.
My attempt:
The most obvious way is to rewrite the LabelItem class and overwrite the mousePressEvent() function, however, I did not see any methods in docs to add a LabelItem to a PlotItem at correct position. Code:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import pyqtgraph as pg
import sys
class ClickableLabelItem(pg.LabelItem):
def __init__(self, text='No Data'):
super(ClickableLabelItem, self).__init__()
self.setText(text, justify='left')
def mousePressEvent(self, ev):
print('clicked')
class AbstractPlot(pg.GraphicsLayoutWidget):
def __init__(self):
super(AbstractPlot, self).__init__()
self.pl = pg.PlotItem()
self.addItem(self.pl)
left_label = ClickableLabelItem()
self.pl.addItem(left_label)
# "Clicked" is printed but the label
# appears at wrong position
if __name__ == "__main__":
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication([])
win = QMainWindow()
plot = AbstractPlot()
win.setCentralWidget(plot)
win.show()
if (sys.flags.interactive != 1) or not hasattr(Qt.QtCore, 'PYQT_VERSION'):
QApplication.instance().exec_()
Label appears at wrong position
If you want to detect in the label associated with the axis then you can override the mousePressEvent method of GraphicsLayoutWidget and compare the item associated with the point pressed by the mouse.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow
import pyqtgraph as pg
class AbstractPlot(pg.GraphicsLayoutWidget):
def __init__(self):
super(AbstractPlot, self).__init__()
self.p1 = self.addPlot(title="Plot 1")
self.p1.setLabel("left", "Value", units="V")
self.p1.setLabel("bottom", "Time", units="s")
def mousePressEvent(self, event):
super().mousePressEvent(event)
item = self.itemAt(event.pos())
if item is self.p1.getAxis("left").label:
print("clicked left")
elif item is self.p1.getAxis("bottom").label:
print("clicked bottom")
if __name__ == "__main__":
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication([])
win = QMainWindow()
plot = AbstractPlot()
win.setCentralWidget(plot)
win.show()
if (sys.flags.interactive != 1) or not hasattr(Qt.QtCore, "PYQT_VERSION"):
QApplication.instance().exec_()

Adding Qframes and Matplotlib In python PyQt5

I am trying to run a program with Python PyQt5 where I take ip's of 2 camera's and stream them live on my screen, but the stream is coming like so (check the 1st picture) like the one in the given picture both the steams are coming in the first half but What I really want them is to come in separate halves(check 2nd picture for better understanding) of the top layout of the code which is in horizontal layout, not together in just the 1st Half of the screen (also i am getting these black borders which I am not able to remove if anyone knows how it can be removed please do tell)
And after the video streams are in the top layout in the bottom layout I am trying to get a Graph and an empty widget which I could edit for later use.
Thanks in Advance
Click here to see my desired output(what i am actually trying to get)
#this is my main window code#
import sys
import vlc
import subprocess
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5 import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import*
from PyQt5.QtWebEngineWidgets import*
from PyQt5.QtPrintSupport import*
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Final App")
self.setGeometry(350,150,400,400)
self.UI()
#calling the UI fucntion which contains the layouts
def UI(self):
self.mainLayout=QVBoxLayout()#main layout is in Vertical Layout
self.topLayout=QHBoxLayout()#top layout is in Horizontal layout
self.bottomLayout=QHBoxLayout()#btm layout is in also in horizontal layout
self.topLayout.setContentsMargins(0, 0, 0, 0)
#self.topLayout.setSpacing(0)
#adding the top and bottom layout inside main layout
self.mainLayout.addLayout(self.topLayout)
self.mainLayout.addLayout(self.bottomLayout)
#assigning variables to different widgets that can be added later
self.videoFrame1 = QFrame()
self.videoFrame2 = QFrame()
#code here to add graph#
#graphcode=graph#
self.text=QLabel("A widget that I can Edit LATER ")
########################################################video player 1###################################################################################
self.videoFrame1 = QFrame()
#QWidget.setGeometry (self,100, 200, 1000, 500)
self.videoFrame1.setGeometry(QtCore.QRect(100, 100, 100, 200))
self.topLayout.addWidget(self.videoFrame1)
self.vlcInstance = vlc.Instance(['--video-on-top'])
self.videoPlayer = self.vlcInstance.media_player_new()
self.videoPlayer = self.vlcInstance.media_player_new()
self.videoPlayer.video_set_mouse_input(False)
self.videoPlayer.video_set_key_input(False)
#self.videoPlayer.set_mrl("rtsp://admin:admin123#192.168.1.250:554/cam/realmonitor?channel=1&subtype=0", "network-caching=300")
self.videoPlayer.set_mrl("rtsp://admin:admin123#192.168.1.251:554/cam/realmonitor?channel=1&subtype=0", "network-caching=200")
self.videoPlayer.audio_set_mute(True)
if sys.platform.startswith('linux'): # for Linux using the X Server
self.videoPlayer.set_xwindow(self.videoFrame1.winId())
elif sys.platform == "win32": # for Windows
self.videoPlayer.set_hwnd(self.videoFrame1.winId())
elif sys.platform == "darwin": # for MacOS
self.videoPlayer.set_nsobject(int(self.videoFrame1.winId()))
self.videoPlayer.play()
#########################################video player 2############################################################################################
#frame2
self.videoFrame2 = QFrame()
self.topLayout.addWidget(self.videoFrame2)
self.vlcInstance1 = vlc.Instance(['--video-on-top'])
self.videoPlayer1 = self.vlcInstance1.media_player_new()
self.videoPlayer1 = self.vlcInstance1.media_player_new()
self.videoPlayer1.video_set_mouse_input(False)
self.videoPlayer1.video_set_key_input(False)
#self.videoPlayer1.set_mrl("rtsp://admin:admin123#192.168.1.251:554/cam/realmonitor?channel=1&subtype=0", "network-caching=300")
self.videoPlayer1.set_mrl("rtsp://admin:admin123#192.168.1.250:554/cam/realmonitor?channel=1&subtype=0", "network-caching=200")
self.videoPlayer1.audio_set_mute(True)
if sys.platform.startswith('linux'): # for Linux using the X Server
self.videoPlayer1.set_xwindow(self.videoFrame2.winId())
elif sys.platform == "win32": # for Windows
self.videoPlayer1.set_hwnd(self.videoFrame2.winId())
elif sys.platform == "darwin": # for MacOS
self.videoPlayer1.set_nsobject(int(self.videoFrame2.winId()))
self.videoPlayer1.play()
###########################################################################################################
#calling top layout
self.toplayout()
#calling bottom layout
self.bottomlayout()
#setting main layout
self.setLayout(self.mainLayout)
self.show()
def toplayout(self):
self.topLayout.setContentsMargins(10,10,20,20)
self.topLayout.addWidget(self.
videoFrame1)
self.topLayout.addWidget(self.videoFrame2)
def bottomlayout(self):
self.bottomLayout.setContentsMargins(150,40,100,80)
self.bottomLayout.addWidget(self.raddar)
self.bottomLayout.addWidget(self.button2)
def main():
App= QApplication(sys.argv)
window=Window()
sys.exit(App.exec())
if __name__ == '__main__':
main()
this is my other folder having a matplotlib code:---
#this is another folder having my garph which i want to call in my main window#
import matplotlib.pyplot as plt
def UI():
plt.figure()
# Set x-axis range
plt.xlim((-4,4))
# Set y-axis range
plt.ylim((0,8))
#setting background color
ax = plt.axes()
ax.set_facecolor('black')
# Draw lines to split quadrants
plt.plot([0,0],[0,8], linewidth=3, color='blue' )
plt.plot([-4,4],[4,4], linewidth=3, color='blue' )
plt.title('Quadrant plot')
plt.show()
UI()
hey so I was able to work something out with the code that I already had so I am going to stream the videos on pyqt only and use subprocess to call the .exe file which I made using MATLAB so here you go do have a look.(here I haven't called the Subprocess right now)
import sys
import vlc
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtPrintSupport import *
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
#this sets the size Maximum for the main Q Frame
self.setWindowState(QtCore.Qt.WindowMaximized)
#this removes the title bar of the window
self.setWindowFlag(Qt.FramelessWindowHint)
self.move(0,0)
#Main Q frame defined where the HBox layout is defined
self.mainFrame = QFrame()
#means defining it in central widget
self.setCentralWidget(self.mainFrame)
#HBox Layout
t_lay_parent = QHBoxLayout()
#used to move the frames inside to go more up down, right,left
t_lay_parent.setContentsMargins(0, 0, 0, 315)
#removes the spacing between the frames and makes it looks like that its just 1 stream
t_lay_parent.setSpacing(0)
#########################################################Camera Frame 1###################################################################
self.videoFrame = QFrame()
QWidget.setGeometry (self, 100, 200, 1500, 1500)
t_lay_parent.addWidget(self.videoFrame)
self.vlcInstance = vlc.Instance(['--video-on-top'])
self.videoPlayer = self.vlcInstance.media_player_new()
self.videoPlayer = self.vlcInstance.media_player_new()
self.videoPlayer.video_set_mouse_input(False)
self.videoPlayer.video_set_key_input(False)
#self.videoPlayer.set_mrl("rtsp://admin:admin123#192.168.1.250:554/cam/realmonitor?channel=1&subtype=0", "network-caching=300")
self.videoPlayer.set_mrl("rtsp://admin:admin123#192.168.1.251:554/cam/realmonitor?channel=1&subtype=0", "network-caching=200")
self.videoPlayer.audio_set_mute(True)
if sys.platform.startswith('linux'): # for Linux using the X Server
self.videoPlayer.set_xwindow(self.videoFrame.winId())
elif sys.platform == "win32": # for Windows
self.videoPlayer.set_hwnd(self.videoFrame.winId())
elif sys.platform == "darwin": # for MacOS
self.videoPlayer.set_nsobject(int(self.videoFrame.winId()))
self.videoPlayer.play()
##########################################################Camera Frame 2#################################################################
#frame2
self.videoFrame1 = QFrame()
t_lay_parent.addWidget(self.videoFrame1)
self.vlcInstance1 = vlc.Instance(['--video-on-top'])
self.videoPlayer1 = self.vlcInstance1.media_player_new()
self.videoPlayer1 = self.vlcInstance1.media_player_new()
self.videoPlayer1.video_set_mouse_input(False)
self.videoPlayer1.video_set_key_input(False)
#self.videoPlayer1.set_mrl("rtsp://admin:admin123#192.168.1.251:554/cam/realmonitor?channel=1&subtype=0", "network-caching=300")
self.videoPlayer1.set_mrl("rtsp://admin:admin123#192.168.1.250:554/cam/realmonitor?channel=1&subtype=0", "network-caching=200")
self.videoPlayer1.audio_set_mute(True)
if sys.platform.startswith('linux'): # for Linux using the X Server
self.videoPlayer1.set_xwindow(self.videoFrame1.winId())
elif sys.platform == "win32": # for Windows
self.videoPlayer1.set_hwnd(self.videoFrame1.winId())
elif sys.platform == "darwin": # for MacOS
self.videoPlayer1.set_nsobject(int(self.videoFrame1.winId()))
self.videoPlayer1.play()
##########################################################################################################################################
#adding layout inside Main Frame
self.mainFrame.setLayout(t_lay_parent)
#shows the Pyqt frame
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setApplicationName("VLC Test")
window = MainWindow()
window.show()
app.exec_()

How to make a line move with mouse inside a plot in a PyQt application

I want to show a given plot inside a PyQt application and show a line that moves along with the mouse cursor. However, the line shows up on the left of the plot and doesn't move at all when moving the cursor. I don't know why this is happening. Here's the code:
import numpy as np
from matplotlib.backends.qt_compat import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
class SnaptoCursor(object):
def __init__(self, ax, x):
self.ax = ax
self.ly = ax.axvline(color='k')
self.x = x
self.txt = ax.text(0.7, 0.9, '', transform=ax.transAxes)
def mouse_move(self, event):
if event.inaxes:
indx = np.searchsorted(self.x, [event.xdata])[0]
x = self.x[indx]
self.ly.set_xdata(x)
self.txt.set_text('x=%1.2f' % x)
self.ax.figure.canvas.draw()
else:
pass
class App(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(App, self).__init__(parent)
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
self.figure = Figure(figsize=(10, 6.9))
self.canvas = FigureCanvas(self.figure)
self.canvas_ax = self.canvas.figure.subplots()
x = np.arange(0,40)
self.canvas_ax.plot(x, np.random.rand(40))
# Layout
layout = QtWidgets.QVBoxLayout(self._main)
layout.addWidget(self.canvas)
self.showMaximized()
##############################################
########## This doesnt seem to work ##########
##############################################
cursor = SnaptoCursor(self.canvas_ax, x)
plt.connect('motion_notify_event', cursor.mouse_move)
##############################################
##############################################
##############################################
if __name__ == '__main__':
app = QtWidgets.QApplication([])
ex = App()
ex.show()
app.exec_()
The two lines in question should be
self.cursor = SnaptoCursor(self.canvas_ax, x)
self.cid = self.canvas.mpl_connect('motion_notify_event', self.cursor.mouse_move)
because else the cursor as well as the callback registration do not exist in memory at the point you would expect them to be used. And also you shouldn't be using pyplot/plt when your figure isn't even created with pyplot.

matplotlib and Qt: mouse scroll event key is always None

This has been fixed for now!
I am trying to make a GUI using PyQt4 with an embedded matplotlib canvas. When I scroll with the cursor over the canvas I would like to be able to control the behaviour based on an additional key press (control in this case). However, the key attribute of the mouseEvent linked to the 'scroll_event' is always None. I tested that my code correctly registers the key for a mouseEvent generated by 'button_press_event'.
In the example below the on_press method correctly prints the key that was pressed at the same time. Whereas on_scoll always prints None.
How can I get access the key that was pressed during the mouse scroll event?
Thanks in advance!
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import matplotlib
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
class GraphicTool(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.create_menu()
def on_press(self, event):
print event.key
def on_scroll(self, event):
print event.key
if event.key == 'ctrl':
# do something
pass
else:
# do something else
pass
def create_main_frame(self):
self.main_frame = QWidget()
# Create the mpl Figure and FigCanvas objects.
# 10x8 inches, 100 dots-per-inch
self.dpi = 100
self.fig = Figure((10.0, 8.0), dpi=self.dpi)
self.canvas = FigureCanvas(self.fig)
self.canvas.setParent(self.main_frame)
self.canvas.setFocusPolicy(Qt.ClickFocus)
self.canvas.setFocus()
self.axes = self.fig.add_subplot(111)
self.canvas.mpl_connect('scroll_event', self.on_scroll)
self.canvas.mpl_connect('button_press_event', self.on_press)
# Create the navigation toolbar, tied to the canvas
self.mpl_toolbar = NavigationToolbar(self.canvas,
self.main_frame)
vbox = QVBoxLayout()
vbox.addWidget(self.canvas)
vbox.addWidget(self.mpl_toolbar)
self.main_frame.setLayout(vbox)
self.setCentralWidget(self.main_frame)
def main():
app = QApplication(sys.argv)
viewer = GraphicTool()
viewer.show()
viewer.raise_()
app.exec_()
if __name__ == "__main__":
main()
The short example above actually does work as expected. However, when I incorporate it into a bigger project it fails. I will keep debugging to see if any other events are disturbing the scroll event.
I have checked your code. This is working as expected.
def on_scroll(self, event):
print event.xdata
print event.ydata
print event.key
if event.key == 'ctrl':
# do something
pass
else:
# do something else
pass
This is the output of your code. I have just added xdata and ydata to your code.
0.480977867785
0.57896567718
control
0.480977867785
0.57896567718
shift
0.480977867785
0.57896567718
shift

How can I draw a cross which follows my mouse cursor?

I want draw a cross in my paintEvent() which moves with the mouse. I'm using python via pyqt.
I'm using the code below, but the result isn't good.
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: That's great,just like I want.And now there another question:
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)
the strange thing is the 'key_press_event' can't be triggerd but all other events can. there r a case: macosx backend ignores multiple mpl_connect() calls
https://github.com/matplotlib/matplotlib/pull/585,
but i think it's differnt with me.
i got cid0,1,2,3,4 which is different each other
So , any idea can share? I an very crazy now.....
Following is my code,u can test it if u have the same problem:
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:Tks all. I resolved this problem after added:
self.canvas.setFocusPolicy( Qt.ClickFocus )
self.canvas.setFocus()
maybe this a little bug bcs i need explicity setfocus on cavans,maybe if not:)
details u can check https://github.com/matplotlib/matplotlib/issues/707
Here is an example using matplotlib event handling (however I am wondering, if it is really useful to have something like a second cursor).
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()
Question...are you trying to change what the cursor looks like over your widget? If so, the easiest thing is to do get rid of the paintEvent entirely, and add setCursor to your init method:
class C_MplCanvas(FigureCanva):
def __init__( self ):
# setup code
...
self.setCursor(Qt.CrossCursor)
This will tell Qt to use the Cross Cursor whenever the mouse is over that particular widget. This will actually replace the arrow (which may or may not be what you want). If that isn't what you want, I would recommend doing something where you create a PNG image of what you do want, create a child QLabel, and move the child widget around in your mouseMoveEvent.
If you need more help on that lemme know.

Categories

Resources