Python Forum
[PyQt] call a function in another class
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] call a function in another class
#1
Hi
I got a problem with calling a funtion from another class. I have searched a bit but i can't find a good solution to my problem. Can any one help me? All my code need to do is call prot function in class Form from the while loop in myClassA.



import sys
import time
from PySide2.QtSql import QSqlQueryModel,QSqlDatabase,QSqlQuery 
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QPushButton, QLineEdit, QTableView, QTableWidget
from PySide2.QtCore import QFile, QObject
from threading import Thread

class Form(QObject):
 
    def __init__(self, ui_file, parent=None):
        super(Form, self).__init__(parent)
        ui_file = QFile(ui_file)
        ui_file.open(QFile.ReadOnly)
 
        loader = QUiLoader()
        self.window = loader.load(ui_file)
        ui_file.close()
 
        self.line = self.window.findChild(QLineEdit, 'lineEdit')
        btn = self.window.findChild(QPushButton, 'pushButton')
        btn2 = self.window.findChild(QPushButton, 'pushButton_2')
        self.tableView = self.window.findChild(QTableView, 'tableView')
        self.tableWidget = self.window.findChild(QTableWidget, 'tableWidget')

        self.db = QSqlDatabase.addDatabase("QSQLITE")
        self.db.setDatabaseName("database.db")
        self.db.open()

        self.projectModel = QSqlQueryModel()
        self.projectModel.setQuery("select * from tider",self.db)

        self.tableView.setModel(self.projectModel)


        btn.clicked.connect(self.ok_handler)
        btn2.clicked.connect(self.prot)
        self.window.show()
        myClassA()
        
    def ok_handler(self):
        language = 'None' if not self.line.text() else self.line.text()
        print('Favorite language: {}'.format(language))
        
    def prot(self):
        self.projectModel = QSqlQueryModel()
        self.projectModel.setQuery("select * from tider",self.db)

        self.tableView.setModel(self.projectModel)
        
class myClassA(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.daemon = True
        self.start()
    def run(self):
        while True:
            print ('A')
            time.sleep(1)
            
if __name__ == '__main__':
    app = QApplication(sys.argv)
    form = Form('mainwindow.ui')
    sys.exit(app.exec_())
Reply
#2
The right way to do it is to use QThread with the signal/slot mechanism.
Example:

#!/usr/bin/python3
# Threading example with QThread and moveToThread (PyQt5)
import sys
import time
from PyQt5 import QtWidgets, QtCore

class WorkerThread(QtCore.QObject):
    signalExample = QtCore.pyqtSignal(str, int)

    def __init__(self):
        super().__init__()

    @QtCore.pyqtSlot()
    def run(self):
        while True:
            # Long running task ...
            self.signalExample.emit("leet", 1337)
            time.sleep(5)

class Main(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.worker = WorkerThread()
        self.workerThread = QtCore.QThread()
        self.workerThread.started.connect(self.worker.run)  # Init worker run() at startup (optional)
        self.worker.signalExample.connect(self.signalExample)  # Connect your signals/slots
        self.worker.moveToThread(self.workerThread)  # Move the Worker object to the Thread object
        self.workerThread.start()

    def signalExample(self, text, number):
        print(text)
        print(number)

if __name__== '__main__':
    app = QtWidgets.QApplication(sys.argv)
    gui = Main()
    sys.exit(app.exec_())
Reply
#3
Thank you for your answer. But its not what i wanted. I can use your example to explain it. I want the while loop in the class WorkerThread to call def signalExample in class Main.
Reply
#4
(Jun-20-2019, 05:22 PM)darktitan Wrote: I want the while loop in the class WorkerThread to call def signalExample in class Main.

This is exactly what the example is doing; the while loop emit a signal, and once the class Main receive it, the connected method is called. You can also do it the other way around (call a function in worker thread from main) with QMetaObject.

arg = QtCore.Q_ARG(str, "leet")
QtCore.QMetaObject.invokeMethod(self.worker, "methodName", QtCore.Qt.QueuedConnection, arg)
Reply
#5
(Jun-21-2019, 03:26 AM)Alfalfa Wrote:
(Jun-20-2019, 05:22 PM)darktitan Wrote: I want the while loop in the class WorkerThread to call def signalExample in class Main.

This is exactly what the example is doing; the while loop emit a signal, and once the class Main receive it, the connected method is called. You can also do it the other way around (call a function in worker thread from main) with QMetaObject.

arg = QtCore.Q_ARG(str, "leet")
QtCore.QMetaObject.invokeMethod(self.worker, "methodName", QtCore.Qt.QueuedConnection, arg)

I understand what you mean. But this returns a str and int from WorkerThread. I want only to call the function def signalExample in class Main from the while loop so what ever code i got there will activate.

Lets say for example the while loop call def signalExample in class Main.
    def signalExample(self):
        print("Hi friend!")
And then it prints Hi friend!.
Reply
#6
Simply remove the arguments;

#!/usr/bin/python3
import sys
import time
from PyQt5 import QtWidgets, QtCore

class WorkerThread(QtCore.QObject):
    signalExample = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()

    @QtCore.pyqtSlot()
    def run(self):
        while True:
            # Long running task ...
            self.signalExample.emit()
            time.sleep(5)

class Main(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.worker = WorkerThread()
        self.workerThread = QtCore.QThread()
        self.workerThread.started.connect(self.worker.run)  # Init worker run() at startup (optional)
        self.worker.signalExample.connect(self.signalMethodExample)  # Connect your signals/slots
        self.worker.moveToThread(self.workerThread)  # Move the Worker object to the Thread object
        self.workerThread.start()

    def signalMethodExample(self):
        print("Hello friend")

if __name__== '__main__':
    app = QtWidgets.QApplication(sys.argv)
    gui = Main()
    sys.exit(app.exec_())
Reply
#7
Thank you. Works like a charm.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  GUI Problem / call another function / fill QListwidget flash77 5 836 Jul-30-2023, 04:29 PM
Last Post: flash77
  simple tkinter question function call not opening image gr3yali3n 5 3,304 Aug-02-2022, 09:13 PM
Last Post: woooee
  [PyQt] Call a function in FormA from FormB panoss 3 1,861 Jan-30-2022, 07:45 PM
Last Post: panoss
  Call local variable of previous function from another function with Python3 & tkinter Hannibal 5 4,359 Oct-12-2020, 09:16 PM
Last Post: deanhystad
  Class function does not create command button Heyjoe 2 2,227 Aug-22-2020, 08:06 PM
Last Post: Heyjoe
  [Tkinter] Use function from other class (Tkinter) zarize 8 4,692 Aug-17-2020, 09:47 AM
Last Post: zarize
  [PyQt] call a function with parametrs from another class atlass218 3 4,716 Feb-29-2020, 11:00 AM
Last Post: atlass218
  [Tkinter] Call a class method from another (Tk GUI) class? Marbelous 3 6,135 Jan-15-2020, 06:55 PM
Last Post: Marbelous
  [Tkinter] Call a function when switching layouts 4096 0 3,505 Sep-22-2019, 07:39 PM
Last Post: 4096
  [Tkinter] Bringing function out of class into main loop zukochew 1 2,652 Jul-30-2018, 06:43 PM
Last Post: Axel_Erfurt

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020