Reputation: 456
I have an app that sets a matplotlib graph to a FigurCanvas and then adds the FigurCanvas to my AppWindow, I have it set up so the graph is draggable. However when I drag the graph the window it is contained in stays where it is so the graph get dragged off the window. Is there a way to bind the two together so when the graph is moved the window stays with it? Here is the code.
from PyQt4 import QtCore
from PyQt4 import QtGui
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class GraphCanvas(FigureCanvas):
def __init__(self):
# The window
self.fig = Figure(figsize=(5, 5), dpi=100)
self.ax1 = self.fig.add_subplot(111)
self.ax1.plot([1,2,3], [1,2,3], linewidth=2, color="#c6463d", label="line1")
FigureCanvas.__init__(self, self.fig)
# drag properties
self.draggable = True
self.dragging_threshold = 5
self.__mousePressPos = None
self.__mouseMovePos = None
def mousePressEvent(self, event):
if self.draggable and event.button() == QtCore.Qt.LeftButton:
self.__mousePressPos = event.globalPos() # global
self.__mouseMovePos = event.globalPos() - self.pos() # local
super(GraphCanvas, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.draggable and event.buttons() & QtCore.Qt.LeftButton:
globalPos = event.globalPos()
moved = globalPos - self.__mousePressPos
if moved.manhattanLength() > self.dragging_threshold:
# move when user drag window more than dragging_threshould
diff = globalPos - self.__mouseMovePos
self.move(diff)
self.__mouseMovePos = globalPos - self.pos()
super(GraphCanvas, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
if self.__mousePressPos is not None:
if event.button() == QtCore.Qt.LeftButton:
moved = event.globalPos() - self.__mousePressPos
if moved.manhattanLength() > self.dragging_threshold:
# do not call click event or so on
event.ignore()
self.__mousePressPos = None
super(GraphCanvas, self).mouseReleaseEvent(event)
''' End Class '''
class AppWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(AppWindow, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
layout = QtGui.QVBoxLayout(self)
cpu_canvas = GraphCanvas()
layout.addWidget(cpu_canvas)
''' End Class'''
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
main = AppWindow()
main.show()
sys.exit(app.exec_())
Upvotes: 1
Views: 1215
Reputation: 339580
If you want to drag the AppWindow you should register the dragging in this class, instead of the Figure canvas. Inside figure canvas you can then route the drag events to the AppWindow.
The following should work for you, where I did not change much of the code, just rearanged it, added the parent argument to GraphCanvas
and let the dragging functions call their parent's functions.
from PyQt4 import QtCore
from PyQt4 import QtGui
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class GraphCanvas(FigureCanvas):
def __init__(self, parent = None):
self.parent = parent
# The window
self.fig = Figure(figsize=(5, 5), dpi=100)
self.ax1 = self.fig.add_subplot(111)
self.ax1.plot([1,2,3], [1,2,3], linewidth=2, color="#c6463d", label="line1")
FigureCanvas.__init__(self, self.fig)
def mousePressEvent(self, event):
self.parent.mousePressEvent(event)
def mouseMoveEvent(self,event):
self.parent.mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
self.parent.mouseReleaseEvent(event)
''' End Class '''
class AppWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(AppWindow, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
layout = QtGui.QVBoxLayout(self)
cpu_canvas = GraphCanvas(self)
layout.addWidget(cpu_canvas)
self.draggable = True
self.dragging_threshold = 5
self.__mousePressPos = None
self.__mouseMovePos = None
def mousePressEvent(self, event):
if self.draggable and event.button() == QtCore.Qt.LeftButton:
self.__mousePressPos = event.globalPos() # global
self.__mouseMovePos = event.globalPos() - self.pos() # local
super(AppWindow, self).mousePressEvent(event)
def mouseMoveEvent(self, event):
if self.draggable and event.buttons() & QtCore.Qt.LeftButton:
globalPos = event.globalPos()
moved = globalPos - self.__mousePressPos
if moved.manhattanLength() > self.dragging_threshold:
# move when user drag window more than dragging_threshould
diff = globalPos - self.__mouseMovePos
self.move(diff)
self.__mouseMovePos = globalPos - self.pos()
super(AppWindow, self).mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
if self.__mousePressPos is not None:
if event.button() == QtCore.Qt.LeftButton:
moved = event.globalPos() - self.__mousePressPos
if moved.manhattanLength() > self.dragging_threshold:
# do not call click event or so on
event.ignore()
self.__mousePressPos = None
super(AppWindow, self).mouseReleaseEvent(event)
''' End Class'''
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
main = AppWindow()
main.show()
sys.exit(app.exec_())
Upvotes: 1