HexxNine
HexxNine

Reputation: 456

Bind canvas to window when canvas is dragged in pyqt

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

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

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

Related Questions