问题
The following code is runnable, you can just copy/paste:
from tkinter import *
import multiprocessing
startingWin = Tk()
def createClientsWin():
def startProcess():
clientsWin = Tk()
label = Label(clientsWin, text="Nothing to show")
label.grid()
clientsWin.mainloop()
if __name__ == "__main__":
p = multiprocessing.Process(target=startProcess)
p.start()
button = Button(startingWin, text="create clients", command=lambda: createClientsWin())
button.grid()
startingWin.mainloop()
So I simply want to create a completely separated Tk()
window using multiprocessing. When I click on the create button, I just get the original window (not the intended one) and it gives me this error:
AttributeError: Can't pickle local object 'createClientsWin.<locals>.startProcess'
*Could someone explain how to start a separate new Tk() window using multiprocessing? *
Update: Not A Duplicate
Even if I follow the solution provided in the possible duplicate question, that doesn't help solving my question. Simply because, Tkinter is being used in my case. The modified code:
def createClientsWin():
clientsWin = Tk()
label = Label(clientsWin, text="Nothing to show")
label.grid()
clientsWin.mainloop()
def createClientsWinProcess():
if __name__ == "__main__":
p = multiprocessing.Process(target=createClientsWin)
p.start()
startingWin = Tk()
button = Button(startingWin, text="create clients", command=lambda: createClientsWinProcess())
button.grid()
startingWin.mainloop()
回答1:
Function in global scope should be used for multiprocess target function, so the startProcess()
should be moved into global scope.
Also the checking of if __name__ == "__main__"
inside startProcess()
will cause the code inside the if block not being executed.
Finally the creation of startingWin
should be put inside if __name__ == "__main__"
block, otherwise every process started will create the startingWin
.
Below is the proposed changes to solve the above issues:
from tkinter import *
import multiprocessing
def startProcess():
clientsWin = Tk()
label = Label(clientsWin, text="Nothing to show")
label.grid()
clientsWin.mainloop()
def createClientsWin():
p = multiprocessing.Process(target=startProcess)
p.start()
if __name__ == '__main__':
startingWin = Tk()
button = Button(startingWin, text="create clients", command=createClientsWin)
button.grid()
startingWin.mainloop()
回答2:
It is easier to use classes when using multiprocessing with tkinter. Try the following code:
import tkinter as Tk
import multiprocessing as mp
class A:
def __init__(self, master):
self.master = master
label = Tk.Label(self.master, text = 'A')
label.pack()
root_b = Tk.Toplevel()
GUI_B = B(root_b)
mp.Process(target = GUI_B.mainloop())
def mainloop(self):
self.master.mainloop()
class B:
def __init__(self, master):
self.master = master
label = Tk.Label(self.master, text = 'B')
label.pack()
def mainloop(self):
self.master.mainloop()
if __name__=='__main__':
root = Tk.Tk()
GUI_A = A(root)
mp.Process(target = GUI_A.mainloop())
来源:https://stackoverflow.com/questions/55177983/how-to-start-a-separate-new-tk-window-using-multiprocessing