1

I am trying to make a visualization of the backtracking algorithm using pyqt5 and I made a class to emit signals whenever an update is to be made in the GUI, yet whenever I try to invoke the method that emits the signals I get an error, and that's because I use QtCore.QMetaObject.invokeMethod to invoke the method and from what I found out that this method only invokes slots and methods known to qt and from that question I found that I can use Q_INVOKABLE to solve this but I still dunno how to do that in python, here's the class that emits the signals:

class signal_emitter(QtCore.QObject):
    answer_signal = QtCore.pyqtSignal(int, int, str)

    def solve(self, grid, row, column):
        row, column = find_empty_cell(grid, row)

        if (row, column) == (None,None):
            return True

        for num in range(1, 10):
            if valid_row(grid[row], num
                ) and valid_column(grid, column, num
                ) and valid_box(grid, row, column, num):

                grid[row][column] = num     
                self.answer_signal.emit(row, column, str(num))

                if self.solve(grid, row, column):
                    return True
 
                grid[row][column] = 0
                self.answer_signal.emit(row, column, "0")

        return False

sofar everything in the code is fine except that I can't invoke the method called (solve) in the code snippet, so I would need a way to use Q_INVOKABLE or a modification to the class so that I can invoke a slot method that would call solve Thanks in advance

eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

1

In the case of pyqt5 you must use the pyqtSlot decorator:

import random
from PyQt5 import QtCore


class signal_emitter(QtCore.QObject):
    answer_signal = QtCore.pyqtSignal(int, int, str)

    @QtCore.pyqtSlot(list, int, int, result=bool)
    def solve(self, grid, row, column):
        print("solve", grid, row, column)

        self.answer_signal.emit(1, 1, "foo")

        return random.choice([True, False])


obj = signal_emitter()
grid = [[1, 2], [3, 4]]
row = 0
column = 0

result = QtCore.QMetaObject.invokeMethod(
    obj,
    "solve",
    QtCore.Qt.DirectConnection,
    QtCore.Q_RETURN_ARG(bool),
    QtCore.Q_ARG(list, grid),
    QtCore.Q_ARG(int, row),
    QtCore.Q_ARG(int, column),
)

print(result)

Output:

solve [[1, 2], [3, 4]] 0 0
True
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • so the method can be a slot and emit custom signals? well I didn't know that, thanks – Ahmad Hamdy Apr 17 '21 at 06:12
  • @AhmadHamdy If answer helped you then do not forget to mark as correct, if you do not know how to do it then check the https://stackoverflow.com/tour – S. Nick Apr 17 '21 at 07:20