Home > Enterprise >  SAP, Python and PySide6 - GUI freezes when i execute another class with a long long process
SAP, Python and PySide6 - GUI freezes when i execute another class with a long long process

Time:11-23

this is the ui_main from my python script:

import ui_nova
from PySide6.QtCore import (QCoreApplication, Signal, QThread, QObject, QRunnable, Slot, QThreadPool)
from PySide6 import QtCore
from PySide6.QtGui import *
from PySide6 import QtWidgets
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget)
from threading import Thread
import conexoes
import threading
import sys
import traceback


class Sinais(QObject):
    
    finished = Signal()
    progress = Signal(int)


class Executora(QThread):

    funcao = None

    def __init__(self):
        super(Executora, self).__init__()
        self.sinais = Sinais()
        self.funcaoaExecutar = None
        self.finished = self.sinais.finished
        self.progress = self.sinais.progress
    
    def nomeDaFuncao(self, funcao):
        self.funcaoaExecutar = funcao

    @Slot()
    def runner(self, funcao):
        
        processo = conexoes.Conexoes()
        aExecutar = funcao
        execute = eval(f'processo.{aExecutar}')

        try:
            execute()
        except:
            traceback.print_exc()
            exctype, value = sys.exc_info()[:2]
            self.signals.error.emit((exctype, value, traceback.format_exc()))
        else:
            print("rodou")
        finally:
            self.finished.emit()


class UIMainConexao(QMainWindow, ui_nova.Ui_MainWindow):

    def __init__(self):
        super(UIMainConexao, self).__init__()
        self.setupUi(self)
        self.MainWW.setWindowFlags(ui_nova.QtCore.Qt.FramelessWindowHint)
        self.MainWW.setAttribute(ui_nova.Qt.WA_TranslucentBackground)
        self.buttonFechar.clicked.connect(self.close)
        self.buttonMinimizar.clicked.connect(self.showMinimized)
        self.threadpool = QThreadPool()
        self.offset = None
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
        
        # install the event filter on the infoBar widget
        self.frameToolBar.installEventFilter(self)
        self.buttonHome.clicked.connect(lambda: self.stackedWidget.setCurrentWidget(self.pageInicial))
        self.buttonUserConfig.clicked.connect(lambda: self.stackedWidget.setCurrentWidget(self.pageUser))
        self.buttonEmpresas.clicked.connect(lambda: self.execute("boletoBancoX"))
        

    def eventFilter(self, source, event):
        if source == self.frameToolBar:
            if event.type() == ui_nova.QtCore.QEvent.MouseButtonPress:
                self.offset = event.pos()
            elif event.type() == ui_nova.QtCore.QEvent.MouseMove and self.offset is not None:
                # no need for complex computations: just use the offset to compute
                # "delta" position, and add that to the current one
                self.move(self.pos() - self.offset   event.pos())
                # return True to tell Qt that the event has been accepted and
                # should not be processed any further
                return True
            elif event.type() == ui_nova.QtCore.QEvent.MouseButtonRelease:
                self.offset = None
        # let Qt process any other event
        return super().eventFilter(source, event)


    @Slot()
    def execute(self, funcao):
        aExecutar = funcao
        self.thread = QThread()
        self.worker = Executora()
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(lambda: print("Iniciou"))
        self.thread.started.connect(lambda: self.worker.runner(aExecutar))
        self.worker.finished.connect(lambda: print("É PRA FINALIZAR"))
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)

        self.thread.start()
    

This Python project has a long structure with a lot of py files. The exe will contain about 70-100 pages with different process that will be executed ONE AT A TIME.

In "Conexoes" has the conections to the all files and processes that will be executed, so i created a method to link every button(i will add all the buttons connections) to their respective method in conexoes giving just the name using the def execute.

When i start the process, will work and the GUI freezes during the process, but if i use Daemon Threads, the script will run the first steps of the proper function (gui dont freezes), but will crash because him couldnt get the SAPEngineScript.

I already tried read many sites how to use Threads in python and put in code, but all didnt work properly. I really dont know what i do.

CodePudding user response:

So, after much more search, i found the solution, which i think can be very usefully for everyone who use QT with SAP. Basicly, when you start a sap function using threading, you will receive an error about the Object SAPGUI, so the solution for this is just import pythoncom for your code and insert "pythoncom.CoInitialize()" before the line getObject("SAPGUI"). Now im using Daemon Thread to execute the function without freezes de GUI.

Ex:

import win32com.client
import pythoncom


def processoSAP(self):
        try:
            pythoncom.CoInitialize()
            self.SapGuiAuto = win32com.client.GetObject("SAPGUI")
            if not type(self.SapGuiAuto) == win32com.client.CDispatch:
                return
            self.application = self.SapGuiAuto.GetScriptingEngine
        except NameError:
            print(NameError)

Where i found: https://django.fun/en/qa/44126/

  • Related