Tkinter threading for socket receiving data - multithreading

im working on a project for my networking class which is a client to interact with a server which hosts a text based game written by our professor.
I have almost everything figured out but i have one major issue, I don't know python very well and threading has been difficult to implement to continuously receiving data from the server.
RuntimeError: main thread is not in main loop
this is the error that i am getting, i believe it is because tkinter must be in the main thread always and its conflicting with my receiving function. I have seen that a Queue might be the soulution to this issue but i am having trouble understanding how to implement this into my code, any help would be great thanks.
from tkinter import *
import tkinter.simpledialog
from sys import exit
from struct import *
from socket import *
import threading
import tkinter.scrolledtext as tkst
skt = socket(AF_INET, SOCK_STREAM)
skt.connect(("domainname.com", 5191))
root = Tk()
def main():
thread = threading.Thread(target = recieve)
thread.start()
thread.join()
root.mainloop()
def start_func():
m = 6
def create_func():
m = 10
def change_func():
m = 2
print(m)
def fight_func():
m = 3
print(m)
def pvp_func():
m = 4
print(m)
def loot_func():
m = 5
skt.send(m)
print(m)
def leave_func():
m = 12
print(m)
def submit_value():
global userEntry
length = len(userEntry.get())
e1.delete(0, END)
class TestClient(Frame):
def __init__(self, master):
global userEntry
Frame.__init__(self, master)
self.pack()
for n in range(3):
self.grid_rowconfigure(n, weight=1)
for n in range(8):
self.grid_columnconfigure(n, weight=1)
self.Messg_text = tkst.ScrolledText(self,wrap = WORD, width=80)
self.Messg_text.grid(row=0, column=0, columnspan=8)
la1 = Label(self, text="Value entry:")
la1.grid(row=1, column=0)
userEntry = StringVar()
global e1
e1 = Entry(self, width=40, textvariable=userEntry)
e1.grid(row=1, column=1, columnspan=6)
e2 = Button(self, text="Enter", command=submit_value)
e1.delete(0, END)
e2.grid(row=1, column=5, columnspan=10)
b1 = Button(self, text="Start", width=10,padx=10,pady=10, command=start_func)
b1.grid(row=2, column=0)
b0 = Button(self, text="Create Character", width=10,padx=10,pady=10, command=create_func)
b0.grid(row=2, column=1)
b2 = Button(self, text="Change Room", width=10,padx=10,pady=10, command=change_func)
b2.grid(row=2, column=3)
b3 = Button(self, text="FIGHT", width=10,padx=10,pady=10, command=fight_func)
b3.grid(row=2, column=4)
b4 = Button(self, text="PvP FIGHT", width=10,padx=10,pady=10, command=pvp_func)
b4.grid(row=2, column=5)
b5 = Button(self, text="Loot", width=10,padx=10,pady=10, command=loot_func)
b5.grid(row=2, column=6)
b6 = Button(self, text="Leave", width=10,padx=10,pady=10, command=leave_func)
b6.grid(row=2, column=7)
tw = TestClient(root)
def recieve():
while(True):
mesg_type = skt.recv(1)
if(mesg_type == b'\x01'):
msg_Len = skt.recv(2)
msg_int_Len = struct.unpack('h',msg_Len)
Recip_Name = skt.recv(32)
sender_Name = skt.recv(32)
mesg = skt.recv(msg_int_Len)
PostMessage(Recip_Name,sender_Name,mesg)
elif(mesg_type == b'\x0b'):
init_Points = skt.recv(2)
statLim = skt.recv(2)
descriptLen = skt.recv(2)
descriptLen = unpack('h',descriptLen)
gameDiscript = skt.recv(descriptLen[0])
print(gameDiscript.decode("utf-8"))
Post11Message(str(gameDiscript)[0:-2])
def PostMessage(name, senderName, Message):
tw.Messg_text.insert(INSERT,Message)
def Post11Message(gameDiscript):
tw.Messg_text.insert(INSERT,gameDiscript)
main()

I'm fairly sure the reason why you are having an issue is because thread.join waits until the thread is finished before doing whatever is next. So, in your case, you are never actually calling root.mainloop(). The solution would just be to take out the thread.join line in main.
Also, in your case, a queue is necessary because you can't change a Tkinter widget in another thread.
Without too much editing, here's what your code would look like.
from tkinter import *
import tkinter.simpledialog
from sys import exit
from struct import *
from socket import *
import Queue
import threading
import tkinter.scrolledtext as tkst
skt = socket(AF_INET, SOCK_STREAM)
skt.connect(("domainname.com", 5191))
root = Tk()
def main():
thread = threading.Thread(target = recieve)
thread.start()
root.mainloop()
def start_func():
m = 6
def create_func():
m = 10
def change_func():
m = 2
print(m)
def fight_func():
m = 3
print(m)
def pvp_func():
m = 4
print(m)
def loot_func():
m = 5
skt.send(m)
print(m)
def leave_func():
m = 12
print(m)
def submit_value():
global userEntry
length = len(userEntry.get())
e1.delete(0, END)
class TestClient(Frame):
def __init__(self, master):
global userEntry
Frame.__init__(self, master)
self.pack()
for n in range(3):
self.grid_rowconfigure(n, weight=1)
for n in range(8):
self.grid_columnconfigure(n, weight=1)
self.Messg_text = tkst.ScrolledText(self,wrap = WORD, width=80)
self.Messg_text.grid(row=0, column=0, columnspan=8)
la1 = Label(self, text="Value entry:")
la1.grid(row=1, column=0)
userEntry = StringVar()
global e1
e1 = Entry(self, width=40, textvariable=userEntry)
e1.grid(row=1, column=1, columnspan=6)
e2 = Button(self, text="Enter", command=submit_value)
e1.delete(0, END)
e2.grid(row=1, column=5, columnspan=10)
b1 = Button(self, text="Start", width=10,padx=10,pady=10, command=start_func)
b1.grid(row=2, column=0)
b0 = Button(self, text="Create Character", width=10,padx=10,pady=10, command=create_func)
b0.grid(row=2, column=1)
b2 = Button(self, text="Change Room", width=10,padx=10,pady=10, command=change_func)
b2.grid(row=2, column=3)
b3 = Button(self, text="FIGHT", width=10,padx=10,pady=10, command=fight_func)
b3.grid(row=2, column=4)
b4 = Button(self, text="PvP FIGHT", width=10,padx=10,pady=10, command=pvp_func)
b4.grid(row=2, column=5)
b5 = Button(self, text="Loot", width=10,padx=10,pady=10, command=loot_func)
b5.grid(row=2, column=6)
b6 = Button(self, text="Leave", width=10,padx=10,pady=10, command=leave_func)
b6.grid(row=2, column=7)
#Data Queue
self.queue = Queue.Queue()
self.queue_check()
def queue_check(self):
try:
#Inserts Data
text = self.queue.get_nowait(0)
self.Messg_text.insert(INSERT, text)
#If Nothing In Queue
except Queue.Empty:
#Repeats Itself After 100 ms
self.after(100, self.queue_check)
tw = TestClient(root)
def recieve():
while(True):
mesg_type = skt.recv(1)
if(mesg_type == b'\x01'):
msg_Len = skt.recv(2)
msg_int_Len = struct.unpack('h',msg_Len)
Recip_Name = skt.recv(32)
sender_Name = skt.recv(32)
mesg = skt.recv(msg_int_Len)
PostMessage(Recip_Name,sender_Name,mesg)
elif(mesg_type == b'\x0b'):
init_Points = skt.recv(2)
statLim = skt.recv(2)
descriptLen = skt.recv(2)
descriptLen = unpack('h',descriptLen)
gameDiscript = skt.recv(descriptLen[0])
print(gameDiscript.decode("utf-8"))
Post11Message(str(gameDiscript)[0:-2])
def PostMessage(name, senderName, Message):
#Adds Message To Queue
tw.queue.put(Message)
def Post11Message(gameDiscript):
#Adds gameDiscript to Queue
tw.queue.put(gameDiscript)
main()

Related

Python ttk.Frame be change by gird()

I want to put another Frame in ttk.Notebook(), I use ttk.Frame() to do that.
Because tk.Frame() can't put multiple frame in ttk.Notebook().
Code:
import tkinter as tk
import tkinter.ttk as ttk
def Notebook(root: tk.Tk) -> tk.Frame:
notebook=ttk.Notebook(root)
f1 = tk.Frame()
f2 = tk.Frame()
notebook.add(f1, text="First")
notebook.add(f2, text="Second")
notebook.pack(padx=10, pady=10, fill='both', expand=True)
return f1
def ttkFrame(frame: tk.Frame) -> ttk.Frame:
f = ttk.Frame(frame, width=200, height=100)
ttk.Style().configure('TFrame', background='#DCB5FF')
f.grid(row=0, column=0)
return f
if __name__ == "__main__":
root = tk.Tk()
root.configure(bg="#7AFEC6")
root.geometry('400x600')
f1 = Notebook(root)
ttk_f1 = ttkFrame(f1)
root.mainloop()
Then put an entry or something element in ttk.Frame by grid(), that will be change ttk.Frame() size.
def use_entry(farme: ttk.Frame) -> None:
entry = tk.Entry(farme, width=20)
entry.insert(0, "Hello World")
entry.grid(row=0, column=0)
if __name__ == "__main__":
root = tk.Tk()
root.configure(bg="#7AFEC6")
root.geometry('400x600')
f1 = Notebook(root)
ttk_f1 = ttkFrame(f1)
use_entry(ttk_f1)
root.mainloop()
I know can use grid_rowconfigure(some args) and grid_columnconfigure(some args) to maintain size.
But I want to know why happend that?

Is it possible to grab input from the topview tkinter window and retrieve saved entry field value from within master tk window

The program is made up of classes and I am trying to use a tkinter topview from within a function so that when it's called it is able to retrieve the entryfield value to the master class
from tkinter import
from PIL import Image, ImageTk
Below is the driver code handling the transitioning from one class to another
class SeaofBTCapp(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (
WelcomePage, Register_new_user): # ,PageThree,PageFour):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(WelcomePage)
# def show_frame(self, cont):
# frame = self.frames[cont]
# frame.tkraise()
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
frame.update()
frame.event_generate("<<show_frame>>")
def get_page(self, cont):
for page in self.frames.values():
if str(page.__class__.__name__) == cont:
return page
return None
class Register_new_user(object):
pass
Below is the entry point of the program and is the first page to be displayed
class WelcomePage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
# self.bind("<<show_frame>>", self.main_prog)
def resize_image(event):
global photo
new_width = event.width
new_height = event.height
image = copy_of_image.resize((new_width, new_height))
photo = ImageTk.PhotoImage(image)
label.config(image=photo)
label.image = photo # avoid garbage collection
def pin_input():
top = Toplevel()
top.geometry("180x100")
top.title("toplevel")
l2 = Label(top, text="This is toplevel window")
global entry_1
global password
password = StringVar
entry_1 = None
def cleartxtfield():
global password
new = "3"
password.set(new)
# ############# Function to parse for only numerical input
def validate(input):
if input.isdigit():
return True
elif input == "":
return True
else:
return False
def enternumber(x):
global entry_1
setval = StringVar()
setval = str(x)
# print(setval)
entry_1.insert(END, setval)
entry_1 = Entry(top, textvariable=password, width=64, show='*')
entry_1.place(x=200, y=100)
entry_1.focus()
reg = top.register(validate)
entry_1.config(validate="key", validatecommand=(reg, '%P'))
def getcreds():
# check if four digit entered and is not empty
global passwd
passwd = password.get()
print(f"The Credentials are {passwd}")
def funcbackspace():
length = len(entry_1.get())
entry_1.delete(length - 1, 'end')
def killwindow():
# when the user quits it should clear all the data input fields filled in in the previous steps. and should display information that it is about to quit in a few seconds
command = top.destroy()
# Label(top,text="Goodbye\n (Closing in 2 seconds)")
top.after(2000, top.quit())
cancel = Button(top, width=8, height=3, text="Cancel", bg="red", fg="black", command=killwindow)
cancel.place(x=220, y=150)
backspace = Button(top, width=8, height=3, text="Backspace", bg="red", fg="black", command=funcbackspace)
backspace.place(x=500, y=150)
# ----number Buttons------
def enternumber(x):
global entry_1
setval = StringVar()
setval = str(x)
# print(setval)
entry_1.insert(END, setval)
btn_numbers = []
for i in range(10):
btn_numbers.append(
Button(top, width=8, height=3, text=str(i), bd=6, command=lambda x=i: enternumber(x)))
btn_text = 1
for i in range(0, 3):
for j in range(0, 3):
btn_numbers[btn_text].place(x=220 + j * 140, y=250 + i * 100)
btn_text += 1
btn_zero = Button(top, width=15, height=2, text='0', bd=5, command=lambda x=0: enternumber(x))
btn_zero.place(x=330, y=550)
clear = Button(top, text="Clear", bg="green", fg="white", width=8, height=3, command=cleartxtfield)
clear.place(x=220, y=550)
okbtn = Button(top, text="Enter", bg="green", fg="black", width=8, height=3, command=getcreds)
okbtn.place(x=500, y=550)
val = getcreds()
print("The value to be returned is %s" % val)
return val
password = pin_input()
print("Gotten password is %s" % password)
copy_of_image = Image.open("image.png")
photoimage = ImageTk.PhotoImage(copy_of_image)
label = Label(self, image=photoimage)
label.place(x=0, y=0, relwidth=1, relheight=1)
label.bind('<Configure>', resize_image)
top_left_frame = Frame(self, relief='groove', borderwidth=2)
top_left_frame.place(relx=1, rely=0.1, anchor=NE)
center_frame = Frame(self, relief='raised', borderwidth=2)
center_frame.place(relx=0.5, rely=0.75, anchor=CENTER)
Button(top_left_frame, text='REGISTER', bg='grey', width=14, height=1,
command=lambda: controller.show_frame(Register_new_user)).pack()
Button(center_frame, text='ENTER', fg='white', bg='green', width=13, height=2,
command=lambda: controller.show_frame(Register_new_user)).pack()
if __name__ == '__main__':
app = SeaofBTCapp()
app.title("Password return on topview window")
width = 1000
height = 700
screenwidth = app.winfo_screenwidth()
screenheight = app.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
app.geometry(alignstr)
# app.resizable(width=False, height=False)
app.resizable(width=True, height=True)
app.mainloop()
If I understand this correctly you want to enter a password in a dialog and then get the password from the dialog when you close it.
Have a look at Dialog Windows at effbot for a discussion about creating dialog windows.
Here is an example of how you can implement a simple dialog:
from tkinter import *
from tkinter import simpledialog
class MyDialog(simpledialog.Dialog):
def body(self, master):
'''create dialog body.
return widget that should have initial focus.
This method should be overridden, and is called
by the __init__ method.'''
Label(master, text='Value:').grid(row=0)
self.e1 = Entry(master)
self.e1.grid(row=0, column=1)
return self.e1 # initial focus
def apply(self):
'''process the data
This method is called automatically to process the data, *after*
the dialog is destroyed. By default, it does nothing.'''
value = self.e1.get()
self.result = value
def validate(self):
'''validate the data
This method is called automatically to validate the data before the
dialog is destroyed. By default, it always validates OK.'''
return 1 # override
def buttonbox(self):
'''add standard button box.
override if you do not want the standard buttons
'''
box = Frame(self)
w = Button(box, text="OK", width=10, command=self.ok, default='active')
w.pack(side='left', padx=5, pady=5)
w = Button(box, text="Cancel", width=10, command=self.cancel)
w.pack(side='left', padx=5, pady=5)
self.bind("<Return>", self.ok)
self.bind("<Escape>", self.cancel)
box.pack()
if __name__ == '__main__':
root = Tk()
root.geometry('200x100+800+50')
def do():
d = MyDialog(root)
print(d.result)
b = Button(root, text='Go!', width=10, command=do)
b.pack(expand=True)
Did that answer your question?

python how to select printer for print receipt

the following code is working successfully, i need to print receipts. i want to select printer to print receipts. in this code how can i add printer function. I need to printer selecting option separately.
i don't know which function using in this code.
i hope you will help for this,
Thanks im advance.
from tkinter import ttk
import tkinter as tk
from tkinter import*
def update():
listBox.insert('','end',value=('APL', t1.get(),t2.get(),t3.get()))
listBox.insert('','end',value=('cPL', t4.get(),t5.get(),t6.get()))
def update():
if t1.get() == '' or t2.get() == '' or t3.get() == '':
pass
else:
listBox.insert('','end',value=('APL', t1.get(),t2.get(),t3.get()))
listBox.insert('','end',value=('cPL', t4.get(),t5.get(),t6.get()))
total = 0.0
try:
for child in listBox.get_children():
total += float(listBox.item(child, 'values')[3])
totText.set(total)
except:
pass
lbl = Label(root,text=total,font=('helvetica',21))
lbl.grid(row=5)
def print():
tott = float(totText.get())
top = Toplevel()
top.geometry("300x300")
top.config(bg="white")
l = Label(top, text='-------RECEIPT-------')
l.pack()
l.config(bg="white")
heading = Label(top, text='\tItem\tPRICE\tQTY\tTotal')
heading.pack()
heading.config(bg="white")
for child in listBox.get_children():
item = (listBox.item(child, 'values')[0])
price = float(listBox.item(child, 'values')[1])
qty = float(listBox.item(child, 'values')[2])
tot = float(listBox.item(child, 'values')[3])
item1 = Label(top, text=f'{item}\t{price}\t{qty}\t{tot}')
item1.config(bg="white")
item1.pack()
tot = Label(top, text=f'Total\t{tott}')
tot.config(bg="white")
tot.pack()
root = tk.Tk()
root.geometry('1000x600')
e8 = tk.Label(root,text="APL").grid(row=1,column=0)
t1 = tk.Entry(root)
t1.grid(row=1,column=1)
t2 = tk.Entry(root)
t2.grid(row=1,column=2)
t3 = tk.Entry(root)
t3.grid(row=1,column=3)
e9 = tk.Label(root,text="cPL").grid(row=2,column=0)
t4 = tk.Entry(root)
t4.grid(row=2,column=1)
t5 = tk.Entry(root)
t5.grid(row=2,column=2)
t6 = tk.Entry(root)
t6.grid(row=2,column=3)
global totText
totText = StringVar()
cols = ('Item', 'PRICE', 'QTY', 'Total')
listBox = ttk.Treeview(root, columns=cols, show='headings')
for col in cols:
listBox.heading(col, text=col)
listBox.grid(row=1, column=0, columnspan=2)
listBox.place(x=10, y=300)
b = tk.Button(root,text='Update Listbox',command=update)
b.grid(row=3)
Button(root, text="print", command=print, height=3, width=13).place(x=850, y=120)
root.mainloop()

Multiprocessing not working with progress bar in tkinter

I'm attempting to get the progress bar to run while a method is running. The problem is when I set the method "generatePi" into the class it won't run simultaneously; however, when I set the method "generatePi" outside of the class it works.
The code with method in class that I can get to work is:
from tkinter import (Tk, BOTH, Text, E, W, S, N, END,
NORMAL, DISABLED, StringVar)
from tkinter.ttk import Frame, Label, Button, Progressbar, Entry
from tkinter import scrolledtext
from multiprocessing import Process, Manager, Queue
from queue import Empty
from decimal import Decimal, getcontext
DELAY1 = 80
DELAY2 = 20
q = Queue()
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent, name="frame")
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Pi computation")
self.pack(fill=BOTH, expand=True)
self.grid_columnconfigure(4, weight=1)
self.grid_rowconfigure(3, weight=1)
lbl1 = Label(self, text="Digits:")
lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10)
self.ent1 = Entry(self, width=10)
self.ent1.insert(END, "4000")
self.ent1.grid(row=0, column=1, sticky=W)
lbl2 = Label(self, text="Accuracy:")
lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10)
self.ent2 = Entry(self, width=10)
self.ent2.insert(END, "100")
self.ent2.grid(row=0, column=3, sticky=W)
self.startBtn = Button(self, text="Start",
command=self.onStart)
self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W)
self.pbar = Progressbar(self, mode='indeterminate')
self.pbar.grid(row=1, column=1, columnspan=3, sticky=W+E)
self.txt = scrolledtext.ScrolledText(self)
self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5,
columnspan=5, sticky=E+W+S+N)
def onStart(self):
self.startBtn.config(state=DISABLED)
self.txt.delete("1.0", END)
digits = int(self.ent1.get())
accuracy = int(self.ent2.get())
self.p1 = Process(target=generatePi(q, digits, accuracy), args=())
self.p1.start()
self.pbar.start(DELAY2)
self.after(DELAY1, self.onGetValue)
def onGetValue(self):
if (self.p1.is_alive()):
self.after(DELAY1, self.onGetValue)
return
else:
try:
self.txt.insert('end', q.get(0))
self.txt.insert('end', "\n")
self.pbar.stop()
self.startBtn.config(state=NORMAL)
except Empty:
print("queue is empty")
def generatePi(q, digs, acc):
getcontext().prec = digs
pi = Decimal(0)
k = 0
n = acc
while k < n:
pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \
(Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \
(Decimal(1)/(8*k+6)))
k += 1
q.put(pi)
def main():
root = Tk()
root.geometry("400x350+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
The code with method outside class that I am unable to get to work:
from tkinter import (Tk, BOTH, Text, E, W, S, N, END,
NORMAL, DISABLED, StringVar)
from tkinter.ttk import Frame, Label, Button, Progressbar, Entry
from tkinter import scrolledtext
from multiprocessing import Process, Manager, Queue
from queue import Empty
from decimal import Decimal, getcontext
DELAY1 = 80
DELAY2 = 20
q = Queue()
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent, name="frame")
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Pi computation")
self.pack(fill=BOTH, expand=True)
self.grid_columnconfigure(4, weight=1)
self.grid_rowconfigure(3, weight=1)
lbl1 = Label(self, text="Digits:")
lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10)
self.ent1 = Entry(self, width=10)
self.ent1.insert(END, "4000")
self.ent1.grid(row=0, column=1, sticky=W)
lbl2 = Label(self, text="Accuracy:")
lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10)
self.ent2 = Entry(self, width=10)
self.ent2.insert(END, "100")
self.ent2.grid(row=0, column=3, sticky=W)
self.startBtn = Button(self, text="Start",
command=self.onStart)
self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W)
self.pbar = Progressbar(self, mode='indeterminate')
self.pbar.grid(row=1, column=1, columnspan=3, sticky=W+E)
self.txt = scrolledtext.ScrolledText(self)
self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5,
columnspan=5, sticky=E+W+S+N)
def onStart(self):
self.startBtn.config(state=DISABLED)
self.txt.delete("1.0", END)
digits = int(self.ent1.get())
accuracy = int(self.ent2.get())
self.p1 = Process(target=self.generatePi(q, digits, accuracy), args=())
self.p1.start()
self.pbar.start(DELAY2)
self.after(DELAY1, self.onGetValue)
def onGetValue(self):
if (self.p1.is_alive()):
self.after(DELAY1, self.onGetValue)
return
else:
try:
self.txt.insert('end', q.get(0))
self.txt.insert('end', "\n")
self.pbar.stop()
self.startBtn.config(state=NORMAL)
except Empty:
print("queue is empty")
def generatePi(self, q, digs, acc):
getcontext().prec = digs
pi = Decimal(0)
k = 0
n = acc
while k < n:
pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \
(Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \
(Decimal(1)/(8*k+6)))
k += 1
q.put(pi)
def main():
root = Tk()
root.geometry("400x350+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
With the change in code being:
self.p1 = Process(target=generatePi(q, digits, accuracy), args=())
To:
self.p1 = Process(target=self.generatePi(q, digits, accuracy), args=())
I got same problem when I try it I find windows system seems react late but in terminal it's actually running

Image/Label not showing with PIL/Python 3.6

I am trying to insert an image into a label widget. If I use the show() function it successfully loads my image. For some reason the image won't display in the GUI though. I've been trying to get it to show for the entire background of the app, but for now it would be acceptable just to show in one frame while I figure out how to get it to the rest of the GUI. The following is a screen shot of the output and code
import sys
from tkinter import *
from PIL import Image,ImageTk
class Game_Client(object):
def __init__(self):
self.tk = Tk()
self.tk.title("Untitled Game")
self.tk.wm_state('zoomed')
# Create the frame holders
top_left = self.create_topleft()
top_mid = self.create_topmid()
top_right = self.create_topright()
btm_left = self.create_btmleft()
btm_mid = self.create_btmmid()
btm_right = self.create_btmright()
border_left = self.create_borderL()
border_right = self.create_borderR()
border_top = self.create_borderT()
border_bottom = self.create_borderB()
self.tk.grid_rowconfigure(0, weight=1)
self.tk.grid_rowconfigure(1, weight=4)
self.tk.grid_rowconfigure(2, weight=4)
self.tk.grid_rowconfigure(3, weight=1)
self.tk.grid_columnconfigure(0, weight=1)
self.tk.grid_columnconfigure(1, weight=4)
self.tk.grid_columnconfigure(2, weight=4)
self.tk.grid_columnconfigure(3, weight=4)
self.tk.grid_columnconfigure(4, weight=1)
background_image = Image.open('client-bg.jpg')
#background_image.show()
background_image = ImageTk.PhotoImage(background_image)
background_label = Label(top_mid, image=background_image)
#background_label.grid(row=0, column=0, rowspan=4, columnspan=5)
background_label.place(x=0,y=0,relheight=1, relwidth=1)
background_label.lift(aboveThis=None)
# Position the frames and set rescale weight
top_left.grid(row=0, column=0, sticky="nsew")
top_mid.grid(row=0, column=1, sticky="nsew")
top_right.grid(row=0, column=2, sticky="nsew")
btm_left.grid(row=1, column=0, sticky="nsew")
btm_mid.grid(row=1, column=1, sticky="nsew")
btm_right.grid(row=1, column=2, sticky="nsew")
border_left.grid(row = 0, column = 0, rowspan = 4, sticky="ns")
border_right.grid(row=0, column=4, rowspan=4, sticky="ns")
border_top.grid(row=0, column=0, columnspan=5, sticky="ew")
border_bottom.grid(row=4, column=0, columnspan=5, sticky="ew")
txtOutFrame = Frame(btm_mid, bg="purple", height=625, width=560)
txtOutFrame.pack(side=TOP, fill=BOTH)
txtOutFrame.pack_propagate(False)
txtOut = Text(txtOutFrame)
txtOut.config(bg='black', fg='green', relief="groove")
txtOut.pack(expand=True, fill=BOTH)
txtChatFrame = Frame(btm_mid, bg="pink", height=150, width=560)
txtChatFrame.pack(side=BOTTOM, fill=X)
txtChatFrame.pack_propagate(False)
txtChat = Text(txtChatFrame)
txtChat.config(bg='white', fg = 'black', relief="groove")
txtChat.pack(expand=True, fill=X)
self.state = False
self.tk.bind("<F11>", self.toggle_fullscreen)
self.tk.bind("<Escape>", self.end_fullscreen)
def toggle_fullscreen(self, event=None):
self.state = not self.state # Just toggling the boolean
self.tk.attributes("-fullscreen", self.state)
return "break"
def end_fullscreen(self, event=None):
self.state = False
self.tk.attributes("-fullscreen", False)
return "break"
def create_topleft(layout):
f = Frame(layout.tk, bg='red', width=430, height=295)
return f
def create_topmid(layout):
f = Frame(layout.tk, bg='orange', width=1050, height=295)
return f
def create_topright(layout):
f = Frame(layout.tk, bg='purple', width=430, height=295)
return f
def create_btmleft(layout):
f = Frame(layout.tk, bg='blue', width=430, height=775)
return f
def create_btmmid(layout):
f = Frame(layout.tk, bg='yellow', width=1050, height=775)
return f
def create_btmright(layout):
f = Frame(layout.tk, bg='green', width=430, height=775)
return f
def create_borderL(layout):
f = Frame(layout.tk, bg='black', width=5, height=1080)
return f
def create_borderR(layout):
f = Frame(layout.tk, bg='black', width=5, height=1080)
return f
def create_borderT(layout):
f = Frame(layout.tk, bg='black', width=1920, height=5)
return f
def create_borderB(layout):
f = Frame(layout.tk, bg='black', width=1920, height=5)
return f
if __name__ == '__main__':
w = Game_Client()
w.tk.mainloop()
This is a very common problem. You need to keep a reference to the PhotoImage object.
background_image = Image.open('client-bg.jpg')
background_image = ImageTk.PhotoImage(background_image)
background_label = Label(top_mid, image=background_image)
background_label.image_ref = background_image # keep the reference!
Otherwise the image gets garbage collected.

Resources