0

mouseClickEvent is in ViewBoxCustom.py and is correctly triggered when you click the scene. compute_spc_map is in SPCanalyse.py and ViewBoxCustom.py doesn't import it as that would make a cyclic import. I know it can be done, but I want to avoid it.

snippet from ViewBoxCustom

from SPCanalyse import MainWindow #This import should not exist
def mouseClickEvent(self, ev):
    elif ev.button() == QtCore.Qt.LeftButton:
        ev.accept()
        # The following line does not work because MainWindow is **NOT** imported 
        MainWindow.compute_spc_map(ev.pos().x(), ev.pos().y())

snippet from SPCanalyse. SPCanalyse imports ViewBoxCustom so as to access functions and generate app functionality

from ViewBoxCustom import MultiRoiViewBox # MultiRoiViewBox contains mouseClickEvent
def compute_spc_map(self, x, y):
    if not self.preprocessed_frames == None:
        self.image = fj.get_correlation_map(y, x, self.preprocessed_frames)

I cant just place compute_spc_map in ViewBoxCustom because preprocessed_frames is a variable generated and used in SPCanalyse

I thought it might work to connect the mouseClickEvent in ViewBoxCustom with compute_spc_map in SPCanalyse doing the following in SPCanalyse

from ViewBoxCustom import MultiRoiViewBox
self.vb = MultiRoiViewBox(lockAspect=True,enableMenu=True)
self.vb.mouseClickEvent.connect(self.compute_spc_map)

sadly mouseClickEvent has no attribute 'connect'

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Frikster
  • 2,755
  • 5
  • 37
  • 71
  • Is `ViewBoxCustom` a child widget of the `MainWIndow`? It's a little confusing because the `ViewBoxCustom` code calls `compute_spc_map` like it's a classmethod, but in the `SPCanalyse` code (where `MainWindow` is defined) it's shown as a regular instance method. I'm assuming `MainWindow` is a class and not a global variable instance of the real MainWindow class. – Brendan Abel Mar 23 '16 at 22:48
  • Yes and MainWindow is indeed a class – Frikster Mar 23 '16 at 23:12

1 Answers1

1

It looks like you're trying to call a method on a parent widget from a child widget (ie. ViewBoxCustom is a child of MainWindow). You generally don't want to do this as it limits the flexibility of the child widget and can lead to circular dependencies like you have here when there's no reason the child should have to depend on the parent.

A good design pattern to use here is for the child to emit a Signal, which the parent connects to, and uses it to trigger the calling of a function (as opposed to the child widget calling the function directly).

In your case:

class ViewBoxCustom(...)
    clicked = QtCore.pyqtSignal(int, int)

    def mouseClickEvent(self, ev):
        if ev.button() == QtCore.Qt.LeftButton:
            ev.accept()
            self.clicked.emit(ev.pos().x(), ev.pos().y())


class MainWindow(QtGui.QMainWindow):

    def __init__(...)
        ...
        self.vbc = ViewBoxCustom(...)
        self.vbc.clicked.connect(self.on_vbc_clicked)

    @QtCore.pyqtSlot(int, int)
    def on_vbc_clicked(self, x, y):
        self.compute_spec_map(x, y)

There's no reason for ViewBoxCustom to ever import or know anything about MainWindow.

Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • So I have actually tried this. I get AttributeError: 'ViewBoxCustom' object has no attribute 'clicked.' However your "clicked = QtCore.pyqtSignal(int, int) " made me see the light and now not only does it work, I now more thoroughly understand how to set up my own signals (the tutorials I read on how to do this often went over my head) – Frikster Mar 23 '16 at 23:40