1

I am developing a desktop application which, due to complexity I had to break up in different parts. This code simply prints out wether you double clicked or single clicked on the (matplotlib) figure object. A simplified version is as below:

from PyQt5.QtWidgets import QMainWindow, QApplication
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('Matplotlib event handling')
        self.setGeometry(400, 400, 900, 500)
        canvas = Canvas(self, width=8, height=4)
        canvas.move(0, 0)

class Canvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=5, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        fig.canvas.mpl_connect('button_press_event', self.onclick)
        self.plot()

    def plot(self):
        x = [i for i in range(100)]
        y = [i**2 for i in range(100)]

        ax = self.figure.add_subplot(111)
        ax.plot(x,y, color='red')

    def onclick(self, event):
        if event.dblclick:
            print("You doubled clicked...")
        else:
            print('You single clicked...')


app = QApplication(sys.argv)
window = Window()
window.show()
app.exec()

The program works fine, but if I call the onclick function from another script, following error arises:

TypeError: onclick() missing 1 required positional argument: 'event'

I understand it has something to do with the scope of the function, but can anybody explain to me what am I doing wrong??

Both the scripts are as follows:

# script1.py

from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from script2 import *

class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('Matplotlib event handling')
        self.setGeometry(400, 400, 900, 500)
        canvas = Canvas(self, width=8, height=4)
        canvas.move(0, 0)


class Canvas(FigureCanvas):
    def __init__(self, parent=None, width=5, height=5, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)

        FigureCanvas.__init__(self, fig)
        self.setParent(parent)

        fig.canvas.mpl_connect('button_press_event', onclick(self))
        self.plot()

    def plot(self):
        x = [i for i in range(100)]
        y = [i ** 2 for i in range(100)]

        ax = self.figure.add_subplot(111)
        ax.plot(x, y, color='red')


app = QApplication(sys.argv)
window = Window()
window.show()
app.exec()

And...

# script2.py


def onclick(self, event):
    if event.dblclick:
        print("You doubled clicked...")
    else:
        print('You single clicked...')

1
  • okay you are approaching this to complicated -- just simplify it change this to: fig.canvas.mpl_connect(self.mplClicked) then add that as a slot function @pyqtSlot(object) def mplClicked(self, Event): then within that function make a call to your new function onclick(self, Event) Commented Apr 6, 2020 at 20:56

1 Answer 1

4

onclick is now its own function separate from the class, so remove the self parameter.

def onclick(event):
   ...

And the signal in Canvas becomes

fig.canvas.mpl_connect('button_press_event', onclick)

If you want to pass the instance it makes more sense to keep onclick inside the Canvas class. Regardless, you can connect the signal in the same manner like this:

fig.canvas.mpl_connect('button_press_event', lambda event: onclick(self, event))

And define onclick:

def onclick(instance, event):
    print(instance)
    if event.dblclick:
        print("You doubled clicked...")
    else:
        print('You single clicked...')
Sign up to request clarification or add additional context in comments.

8 Comments

That will do, but in my actual program, I need to pass the instance of that class in which the figure is so I may manipulate some variables in that class. With the solution you proposed, how may I acheive that?
@AsadUllahButt, you can get the Canvas class with event.canvas on your onclick(event) function
Hmm his error is he is missing a parameter and your solution is to remove a parameter ??
@DennisJensen, the OP question was "How to call onclick event from another script in matplotlib?", not how to pass another parameter to the function?. ;)
@DennisJensen Yeah, in the question his onclick function didn't make use of the self parameter, so it's logical to remove it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.