how to remove Recursion-Error in python tkinter? - python-3.x

i am trying to build a calculator (initial stages) using tkinter-python
when calling the run function of object its giving an [RecursionError: maximum recursion depth exceeded]enable to find why and where it is calling the run function repeatedly
import tkinter as gui
from tkinter import ttk
class box(gui.Tk):
def __init__(self):
#op = operators()
root = gui.Tk()
root.title("Calculator")
self.frame=ttk.Frame(root).grid()
self.display=ttk.Entry(text='0',font=('Comic Sans MS',20))
self.display.grid(row=0, columnspan=6)
self.buttons()
def buttons(self):
#printing numbers
self.seven=ttk.Button(text="7",command=lambda:self.getdata(7))
self.seven.grid(row=1,column=0)
self.eighth=ttk.Button(text="8",command=lambda:self.getdata(8))
self.eighth.grid(row=1,column=1)
self.nine=ttk.Button(text="9",command=lambda:self.getdata(9))
self.nine.grid(row=1,column=2)
self.four=ttk.Button(text="4",command=lambda:self.getdata(4))
self.four.grid(row=2,column=0)
self.five=ttk.Button(text="5",command=lambda:self.getdata(5))
self.five.grid(row=2,column=1)
self.six=ttk.Button(text="6",command=lambda:self.getdata(6))
self.six.grid(row=2,column=2)
self.one=ttk.Button(text="1",command=lambda:self.getdata(1))
self.one.grid(row=3,column=0)
self.two=ttk.Button(text="2",command=lambda:self.getdata(2))
self.two.grid(row=3,column=1)
self.three=ttk.Button(text="3",command=lambda:self.getdata(3))
self.three.grid(row=3,column=2)
def getdata(self,x):
self.num=x
def operate(self,y):
#add code for operators
self.getdata('op')
def run(self):
self.mainloop()
app=box()
app.run()

Related

Error in tkinter GUI --invalid command name "2025099205632update_values" while executing

I am getting the error "invalid command name "2025099205632update_values"
while executing" in tkinter GUI code. I attached my code.I am using Spyder 4 and Python 3.6.
Please help me to solve this error.
This is my code. This display the random number on tkinter frame. at the interval of 1000 mill second.
main.py call the class object to start GUI
panel_meter.py create label frame and call the class "r_phase_parameter" in r_phase.py
In class r_phase_parameter global variable updated at 1000 ms. These are the random numbers.
"""
This is main.py file.
"""
from panel_meter import *
meter_Window = meter()
meter_Window.start()
#########This is panel_meter.py file######################################
from tkinter import *
from r_phase import *
vol_r=100
class meter:
def __init__(self):
self.r_list = [] #This is not used
self.vol_r=vol_r
self.col=0
self.root=Tk()
self.root.title('Meter')
self.root.config(relief="sunken", borderwidth = 3,background="#FFFFF0")
self.r_frame=LabelFrame(self.root,text="R Phase") #,width=220,height=70
self.r_frame.grid(row=0,column=1,padx=10,pady=10)
self.r_frame.configure(foreground="red")
self.r_frame.config(background="#FFFFF0")
self.r_phase_read=r_phase_parameter(self.root,self.r_frame,self.vol_r,self.r_list)
def start(self):
self.root.mainloop()
###########################r_phase.py#############################
from tkinter import *
import meter_globel
import random
class r_phase_parameter:
def __init__(self,root,frame,r_vol,r_list):
self.root=root
self.frame=frame
#self.frame.grid_propagate(0)
self.l1=Label(self.frame,text='Voltage=' + str(meter_globel.r_globel_voltage)+'V',width=meter_globel.global_label_width)
self.l1.grid(row=0,column=0,padx=10,pady=10)
self.l1.config(background="#FFFFF0")
self.l1.after(meter_globel.update_time,self.update_values)
self.l2=Label(self.frame,text='Current=' + str(meter_globel.r_globel_current)+'A',width=meter_globel.global_label_width)
self.l2.grid(row=0,column=1,padx=10,pady=10)
self.l2.config(background="#FFFFF0")
self.l3=Label(self.frame,text='Frequency=' + str(meter_globel.r_globel_frequency)+'Hz',width=meter_globel.global_label_width)
self.l3.grid(row=0,column=2,padx=10,pady=10)
self.l3.config(background="#FFFFF0")
def __del__(self):
self.after_cancel(self.after_id)
def update_values(self):
meter_globel.r_globel_voltage=random.randrange(120,290)
meter_globel.r_globel_current=random.randrange(1,14)
meter_globel.r_globel_frequency=random.randrange(1,55)
if meter_globel.r_globel_voltage > 250:
bgc_rv='red'
else :
bgc_rv="Blue"
if meter_globel.r_globel_current > 10:
bgc_rc='red'
else :
bgc_rc="Blue"
if meter_globel.r_globel_frequency > 50:
bgc_rf='red'
else :
bgc_rf="Blue"
self.l1.configure(text='Voltage=' + str(meter_globel.r_globel_voltage)+'V',fg=bgc_rv,width=meter_globel.global_label_width)
self.l2.configure(text='Current=' + str(meter_globel.r_globel_current)+'A',fg=bgc_rc,width=meter_globel.global_label_width)
self.l3.configure(text='Frequency=' + str(meter_globel.r_globel_frequency)+'Hz',fg=bgc_rf,width=meter_globel.global_label_width)
self.l1.after(meter_globel.update_time,self.update_values)
##################This meter_global.py############################
r_globel_voltage=000
r_globel_current=00
r_globel_frequency=0
global_label_width= 12
update_time =1000 # This is in mill second
First of all, you must give your code clearer, I cannot reproduce your error, it works fine for me. However there were some attributeErrors but I fixed it.
I just brought up all together your code into single script.
from tkinter import *
import random
#GLOBAL VARIABLES
vol_r=100
r_globel_voltage=000
r_globel_current=00
r_globel_frequency=0
global_label_width= 12
update_time =1000 # This is in mill second
class r_phase_parameter:
def __init__(self,root,frame,r_vol,r_list):
self.root=root
self.frame=frame
#self.frame.grid_propagate(0)
self.l1=Label(self.frame,text='Voltage=' + str(r_globel_voltage)+'V',width=global_label_width)
self.l1.grid(row=0,column=0,padx=10,pady=10)
self.l1.config(background="#FFFFF0")
self.l1.after(update_time,self.update_values)
self.l2=Label(self.frame,text='Current=' + str(r_globel_current)+'A',width=global_label_width)
self.l2.grid(row=0,column=1,padx=10,pady=10)
self.l2.config(background="#FFFFF0")
self.l3=Label(self.frame,text='Frequency=' + str(r_globel_frequency)+'Hz',width=global_label_width)
self.l3.grid(row=0,column=2,padx=10,pady=10)
self.l3.config(background="#FFFFF0")
def __del__(self):
#################################
#I have changed here, itself of of this class is not inherited any tkinter
# widget so it cannot use self.after_cancel
#################################
self.root.after_cancel(self.update_values)
def update_values(self):
r_globel_voltage=random.randrange(120,290)
r_globel_current=random.randrange(1,14)
r_globel_frequency=random.randrange(1,55)
if r_globel_voltage > 250:
bgc_rv='red'
else :
bgc_rv="Blue"
if r_globel_current > 10:
bgc_rc='red'
else :
bgc_rc="Blue"
if r_globel_frequency > 50:
bgc_rf='red'
else :
bgc_rf="Blue"
self.l1.configure(text='Voltage=' + str(r_globel_voltage)+'V',fg=bgc_rv,width=global_label_width)
self.l2.configure(text='Current=' + str(r_globel_current)+'A',fg=bgc_rc,width=global_label_width)
self.l3.configure(text='Frequency=' + str(r_globel_frequency)+'Hz',fg=bgc_rf,width=global_label_width)
self.l1.after(update_time,self.update_values)
class meter:
def __init__(self):
self.r_list = [] #This is not used
self.vol_r=vol_r
self.col=0
self.root=Tk()
print("x")
self.root.title('Meter')
self.root.config(relief="sunken", borderwidth = 3,background="#FFFFF0")
self.r_frame=LabelFrame(self.root,text="R Phase") #,width=220,height=70
self.r_frame.grid(row=0,column=1,padx=10,pady=10)
self.r_frame.configure(foreground="red")
self.r_frame.config(background="#FFFFF0")
self.r_phase_read=r_phase_parameter(self.root,self.r_frame,self.vol_r,self.r_list)
def start(self):
self.root.mainloop()
meter_Window = meter()
meter_Window.start()
However, when I run this code, it shows this window, no errors and it changes dynamically so I assume it works fine.

QThread closes whenever QFileDialog Called After Migrating from PyQt5 to Pyside2

First of all, I'm currently migrating my source code from PyQt5 to PySide2 which requires me to change some of the syntaxes. As this site said that it only needs 3 things to do migrate from PyQt to Pyside2.
1.app.exec_. exec_ was used as exec is a Python2 keyword. Under Python3, PyQt5 allows the use of exec but not PySide2.
2.Under PyQt5 it’s QtCore.pyqtSignal and QtCore.pyqtSlot and under PySide2 it’s QtCore.Signal and QtCore.Slot .
3.loading Ui files.
But anyway later on when I tried to run my code it gave me this following error:
QThread: Destroyed while thread is still running
I had more than 2000 lines of code and I cannot determine which is the cause of this other than my last action which is trying to call QFileDialog which shouldn't be a problem (I've tested this with PyQt import and there's no problem and no warning at all). But in PySide2 it definitely might be the cause of it. I look up into this, he doesn't have the same problem as mine exactly. I'm not trying to call QFileDialog from different thread.
this is the minimal reproducible example of my working code in PyQt5:
import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QWidget, QDialog
import random
class MyWidget(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.path = os.path.abspath(os.path.dirname(sys.argv[0]))
self.button = QtWidgets.QPushButton("Open File")
self.labelFile = QtWidgets.QLabel("empty")
self.labelData = QtWidgets.QLabel("None")
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.button)
self.layout.addWidget(self.labelFile)
self.layout.addWidget(self.labelData)
self.setLayout(self.layout)
self.button.clicked.connect(self.open_file)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_data_value)
timer.start(1000)
def open_file(self):
x = QFileDialog.getOpenFileName(self,"Pilih File CSV yang Ingin Diproses",self.path,"CSV Files (*.csv)")
self.labelFile.setText(x[0])
def update_data_value(self):
self.DataProcess = DataProcess()
self.DataProcess.progress.connect(self.update_data_label)
self.DataProcess.start()
def update_data_label(self,x):
self.labelData.setText(str(x[0]))
class DataProcess(QtCore.QThread):
progress = QtCore.pyqtSignal(object)
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
x = random.randint(1,100)
self.progress.emit([str(x)+ " from thread"])
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
and this is the non-working one in PySide2 after renaming import accordingly to PySide2 also renaming 'pyqtsignal' to 'Signal'
import sys
import os
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QWidget, QDialog
import random
class MyWidget(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.path = os.path.abspath(os.path.dirname(sys.argv[0]))
self.button = QtWidgets.QPushButton("Open File")
self.labelFile = QtWidgets.QLabel("empty")
self.labelData = QtWidgets.QLabel("None")
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.button)
self.layout.addWidget(self.labelFile)
self.layout.addWidget(self.labelData)
self.setLayout(self.layout)
self.button.clicked.connect(self.open_file)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.update_data_value)
timer.start(1000)
def open_file(self):
x = QFileDialog.getOpenFileName(self,"Pilih File CSV yang Ingin Diproses",self.path,"CSV Files (*.csv)")
self.labelFile.setText(x[0])
def update_data_value(self):
self.DataProcess = DataProcess()
self.DataProcess.progress.connect(self.update_data_label)
self.DataProcess.start()
def update_data_label(self,x):
self.labelData.setText(str(x[0]))
class DataProcess(QtCore.QThread):
progress = QtCore.Signal(object)
def __init__(self):
QtCore.QThread.__init__(self)
def run(self):
x = random.randint(1,100)
self.progress.emit([str(x)+ " from thread"])
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
so after creating this minimal example, I realized that PySide QFileDialog makes the QThread stop while PyQt QFileDialog doesn't freeze the main thread. Is there anything I could do to handle this in similar syntax architecture? (e.g not using "movetothread" or "QObject")
The problem is that you're overwriting self.DataProcess every time a new thread is created, which may cause the previous object to be garbage-collected by Python before Qt has a chance to delete it. This can result in a core-dump if Qt tries to delete an object which is no longer there. Problems of this kind are quite common in both PyQt and PySide, and are usually caused by not keeping proper references to dependant objects. The normal solution is to ensure that the affected objects are given a parent and, if necessary, explicitly delete them at an appropriate time.
Here is one way to fix your example:
class MyWidget(QtWidgets.QWidget):
...
def update_data_value(self):
# ensure the thread object has a parent
process = DataProcess(self)
process.progress.connect(self.update_data_label)
process.start()
def update_data_label(self,x):
self.labelData.setText(str(x[0]))
class DataProcess(QtCore.QThread):
progress = QtCore.Signal(object)
def __init__(self, parent):
# ensure the thread object has a parent
QtCore.QThread.__init__(self, parent)
def run(self):
x = random.randint(1,100)
self.progress.emit([str(x)+ " from thread"])
# explicitly schedule for deletion
self.deleteLater()
It's hard to say exactly why PySide behaves differently to PyQt in this particular case. It usually just comes down to low-level differences between the two implementations. Probably there are equivalent cases that affect PyQt but not PySide. However, if you manage object references and cleanup carefully, such differences can usually be eliminated.

Type Error: unsupported operand type(s) for /: 'Nonetype' and 'int'

from pytube import YouTube
from tkinter import filedialog
from tkinter import ttk
from tkinter import*
import threading
import re
class Application:
def __init__(self,root):
self.root=root
self.root.grid_rowconfigure(0,weight=2)
self.root.grid_columnconfigure(0,weight=1)
self.root.config(bg="#ffdddd")
top_label=Label(self.root,text="YouTube download manager",fg="blue",font=("ALGERIAN",70))
top_label.grid(pady=(0,10))
link_label=Label(self.root,text="Please paste your YouTube video link",bg="black",fg="red",font=("Agency FB",30))
link_label.grid(pady=(0,20))
self.YoutubeEntryVar=StringVar()
self.YoutubeEntry=Entry(self.root,width=70,textvariable=self.YoutubeEntryVar,font=("Lucida Console",25),fg="blue")
self.YoutubeEntry.grid(pady=(0,20),ipady=5)
self.YoutubeEntryError=Label(self.root,text="",font=("Colonna MT",20),fg="green")
self.YoutubeEntryError.grid(pady=(0,8))
self.YoutubeFileSave=Label(self.root,text="Choose Directory",font=("Agency FB",20),fg="black")
self.YoutubeFileSave.grid(pady=(0,8))
self.YoutubeButton=Button(self.root,text="Directory",font=("Colonna MT",20),command=self.FileDirectory)
self.YoutubeButton.grid(pady=(10,3),ipady=5)
self.FileLocation=Label(self.root,text="",font=("Harlow Solid Italic",20))
self.FileLocation.grid()
self.DownloadSelect=Label(self.root,text="Choose the format to download",font=("Century Gothic",20))
self.DownloadSelect.grid()
self.DownloadChoice=[("Audio MP3",1),("Video MP4",2)]
self.Choice=StringVar()
self.Choice.set(1)
for text,mode in self.DownloadChoice:
self.YoutubeChoice=Radiobutton(self.root,text=text,font=("Candara",10),variable=self.Choice,value=mode)
self.YoutubeChoice.grid()
self.DownloadButton=Button(self.root,text="Download",font=("Lucida Console",10),command=self.checkLink)
self.DownloadButton.grid(pady=(5,5))
def checkLink(self):
self.youtubeMatch=re.match("https://www.youtube.com/",self.YoutubeEntryVar.get())
if(not self.youtubeMatch):
self.YoutubeEntryError.config(text="Please choose a valid YouTube link !!")
elif(not self.FolderName):
self.FileLocation.config(text="Please choose a directory !!",fg="red")
elif(self.youtubeMatch and self.FolderName):
self.downloadFile()
def downloadFile(self):
self.newWindow=Toplevel(self.root)
self.root.withdraw()
self.newWindow.state("zoomed")
self.newWindow.grid_rowconfigure(0,weight=2)
self.newWindow.grid_columnconfigure(0,weight=1)
self.app=Second(self.newWindow,self.YoutubeEntryVar.get(),self.FolderName,self.Choice.get())
def FileDirectory(self):
self.FolderName=filedialog.askdirectory()
if(len(self.FolderName)>0):
self.FileLocation.config(text=self.FolderName,fg="green")
return True
else:
self.FileLocation.config(text="Please choose a directory !!",fg="red")
class Second:
def __init__(self,downloadWindow,youtubeLink,foldername,FileChoice):
self.downloadWindow=downloadWindow
self.youtubeLink=youtubeLink
self.foldername=foldername
self.FileChoice=FileChoice
self.yt=YouTube(self.youtubeLink)
if(FileChoice=='1'):
self.videoType=self.yt.streams.filter(only_audio=True).first()
self.MaxfileSize=self.videoType.filesize
if(FileChoice=='2'):
self.videoType=self.yt.streams.first()
self.MaxfileSize=self.videoType.filesize
self.Loading=Label(self.downloadWindow,text="Download in Progress.........",font=("Agency FB",40))
self.Loading.grid()
self.percent=Label(self.downloadWindow,text="0",font=("Agency FB",20))
self.percent.grid()
self.progressBar=ttk.Progressbar(self.downloadWindow,length=500,orient='horizontal',mode='indeterminate')
self.progressBar.grid(pady=(50,0))
self.progressBar.start()
threading.Thread(target=self.yt.register_on_progress_callback(self.show_Pregress)).start()
threading.Thread(target=self.downloadfile).start()
def downloadfile(self):
if(self.FileChoice=='1'):
self.yt.streams.filter(only_audio=True).first().download(self.foldername)
if(self.FileChoice=='2'):
self.yt.streams.filter().first().download(self.foldername)
def show_Pregress(self,streams=None,Chunks=None,filehandle=None,bytes_remaining=None):
percentCount = float("%0.2f"% (100 - (100*(bytes_remaining/self.MaxfileSize))))
if(percentCount<100):
self.percent.config(text=str(percentCount))
else:
self.progressBar.stop()
self.Loading.forget()
self.progressBar.forget()
self.downloadfinished=Label(self.downloadWindow,text="Download Finished",font=("ALGERIAN",20))
self.downloadfinished.grid(pady(150,0))
self.downloadfile=Label(self.downloadWindow,text=self.yt.title,font=("ALGERIAN",20))
self.downloadfile.grid(pady(50,0))
if __name__=="__main__":
window=Tk()
window.title("YouTube Download Manager")
window.state("zoomed")
app=Application(window)
mainloop()
Most probably your function:
def show_Pregress(self,streams=None,Chunks=None,filehandle=None,bytes_remaining=None):
percentCount = float("%0.2f"% (100 - (100*(bytes_remaining/self.MaxfileSize))))
Is called without passing a value for bytes_remaining which ends up in doing a division of None by self.MaxfileSize
See here for how to register a progress_bar callback with pytube:
How to add progress bar?

How to insert text in tkinter GUI while code is running

Hi I am try to create an Python GUI using tkinter package. Everything working perfectly but I want to insert or print some text while code is running. My code is little length process, I did not include all the code, to execute i need some update information on the Text area, so that user know coding is running and getting some information from internet.
Could you please kindly check this code. In this code number will insert in the Tkinter GUI and will be increase continuously. But i want to inset text form the given list. How can I insert text form the list. Please kindly help.
from tkinter import *
import threading
import queue
from time import sleep
import random
import tkinter as tk
list1 = ['Text 1', 'Text 2','Text 3','Text 4','Text 5','Text 6','Text 7',
'Text 8','Text 9','Text 10','Text 11']
class Thread_0(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
count = 0
while True:
count+=1
hmi.thread_0_update(count)
sleep(random.random()/100)
class HMI:
def __init__(self):
self.master= tk.Tk()
self.master.geometry('200x200+1+1')
f=tk.Frame(self.master)
f.pack()
self.l0=tk.Label(f)
self.l0.pack()
self.q0=queue.Queue()
self.master.bind("<<Thread_0_Label_Update>>",self.thread_0_update_e)
def start(self):
self.master.mainloop()
self.master.destroy()
def thread_0_update(self,val):
self.q0.put(val)
self.master.event_generate('<<Thread_0_Label_Update>>',when='tail')
def thread_0_update_e(self,e):
while self.q0.qsize():
try:
val=self.q0.get()
self.l0.config(text=str(val))
# self.l0.config(text=val)
except queue.Empty:
pass
##########################
if __name__=='__main__':
hmi=HMI()
t0=Thread_0()
t0.start()
hmi.start()

PyQt MainWindow using multiprocessing on Windows

I try to create a PyQt application. In order to run process in background and keep the PyQt5 application available for new instruction, I want to use multiprocessing.
On the Windows OS, when I call a function from the Qt MainWindow class with multiprocessing.process, I have an error about pickling this class. But it is running find on Linux.
Here is an example:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import multiprocessing
#
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Frame_main(QMainWindow):
def __init__(self, parent = None):
super(Frame_main, self).__init__(parent)
self.thrd_list=[]
self.initUI()
def initUI(self):
# Button
btn_run = QPushButton('Run', self)
btn_run.clicked.connect(lambda: self.ThdSomething(self.DoRun) ) #
btn_stop = QPushButton('Stop', self)
btn_stop.clicked.connect(self.DoStop)
### TEXT Edit
self.textEdit_term = QTextEdit("terminal: \n ")
self.textEdit_term.append("")
self.textEdit_term.setStyleSheet("color: rgb(255, 255, 255); background-color: black;")
self.textEdit_term.setLineWrapMode(QTextEdit.NoWrap)
self.textEdit_term.setToolTip(' terminal message ')
self.textEdit_term.setStatusTip('textEdit1')
### LAYOUT
Wid_main = QWidget() #
grid_major = QGridLayout() #
grid_major.addWidget( btn_run, 1, 5)
grid_major.addWidget( btn_stop, 2, 5)
Wid_main.setLayout(grid_major)
self.setCentralWidget(Wid_main)
### Affichage
self.show() #
#
def DoRun(self):
print('g starts')
time_start=time.time()
time_stop=time.time()
name='bob'
n=0
while time_stop-time_start <2 :
n+=1
time_stop=time.time()
time.sleep(0.8)
print ('hola', name,n, flush=True)
print('g stops')
def DoStop(self):
''' subourtine kill all the thread '''
print('stop action detected')
while len(self.thrd_list) > 0 :
print("Terminating the job: {}".format(self.thrd[-1].pid) )
os.kill(self.thrd[-1].pid, signal.SIGTERM)
self.thrd_list[-1].terminate()
self.thrd_list.pop()
def ThdSomething(self, job):
''' subourtine to create a new thread to do the job subroutine '''
arg=''
p=multiprocessing.Process(target=job, args=(arg))
self.thrd_list.append( p )
p.start()
print("Start the job GUI: {} with PID: {}".format(str(job) ,self.thrd[-1].pid), file=sys.stdout )
def closeEvent(self, event):
''' subroutine to define what happen when closing the main frame'''
self.statusBar().showMessage('waiting for a respond')
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
# Main
if __name__ == '__main__':
# Create QApplication and Main Frame
Qapp = QApplication(sys.argv) # creation de lappli Qt
Qapp.setStyle("fusion") #
frame1 = Frame_main() #
sys.exit(Qapp.exec_()) #
EDIT:
I found several similar case, like :
Python: multiprocessing in pyqt application
but none of them helped. I think this might be linked to fact that my case is using function and attributes of the MainWindow class.
You are correct that this is due to the attempt to fork on a method within the GUI class. Unfortunately windows doesn't really have the ability to fork processes the way linux does, which is why your code works on linux and not on windows. The Python 3 documentation for the multiprocessing library has some useful information on the differences and what the default method for starting a new process is under different platforms.
To answer your question: because your target is a method associated with a GUI object, it has to send the object state to the new process but fails to pickle it because a PyQt GUI object is far too complex to pickle.
If you rewrite your code so that the target function (and args specified) are picklable, your code will work.

Resources