Image/Label not showing with PIL/Python 3.6 - python-3.x

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.

Related

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?

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

Change Entry widget value from other function

I am quite new in programming with tkinter , especially with classes. How can I make a button that runs function from the same class and changes entry widget. In my code i want to change entry1 whenever button1 is clicked and filepath function runs.
thank you for your help.
Class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def filepath():
filename = fd.askopenfilename()
entry1.delete(0,END)
entry1.insert(0,filename)
def initUI(self):
self.master.title("EFEKTYWNOŚĆ APP")
self.pack(fill=BOTH, expand=True)
cd = (os.getcwd())
frame1 = Frame(self)
frame1.pack(side = LEFT)
lbl1 = Label(frame1,
text="...",
wraplength = 250 )
lbl1.pack(side=LEFT, padx=5, pady=5)
path = os.path.join(cd, 'ico', '...')
photo = PhotoImage(file = path)
cphoto = photo.subsample(4,4)
button1 = Button(frame1,
text='WYBIERZ PLIK',
image = cphoto,
compound = LEFT,
command = Example.filepath)
button1.image = cphoto
button1.pack(side=LEFT, fill = Y, padx=5, pady=5)
entry1 = Entry(frame1)
entry1.pack(side=LEFT, fill = Y, padx=5, pady=5)
There are some minor things needed to be fixed in your code. I have added a working sample with comments below.
from tkinter import *
from tkinter import filedialog as fd
import os
class Example(Frame):
def __init__(self, master,**kwargs): #have your Frame accept parameters like how a normal frame should
super().__init__(master,**kwargs)
self.master = master #set master as an attribute so you can access it later
self.initUI()
def filepath(self): #add self to make the method an instance method
filename = fd.askopenfilename()
self.entry1.delete(0, END) #use self when referring to an instance attribute
self.entry1.insert(0, filename)
def initUI(self):
self.master.title("EFEKTYWNOŚĆ APP")
self.pack(fill=BOTH, expand=True)
cd = (os.getcwd())
frame1 = Frame(self)
frame1.pack(side=LEFT)
lbl1 = Label(frame1,
text="...",
wraplength=250)
lbl1.pack(side=LEFT, padx=5, pady=5)
path = os.path.join(cd, 'ico', '...')
photo = PhotoImage(file=path)
cphoto = photo.subsample(4, 4)
button1 = Button(frame1,
text='WYBIERZ PLIK',
image=cphoto,
compound=LEFT,
command=self.filepath) #refer to instance methods by self.your_method
button1.pack(side=LEFT, fill=Y, padx=5, pady=5)
self.entry1 = Entry(frame1) #add self to make it an instance attribute
self.entry1.pack(side=LEFT, fill=Y, padx=5, pady=5) #you will then need to use self.entry1 within your class instance
root = Tk()
Example(root)
root.mainloop()

Why can I not get the value of tkinter variables?

I am trying to add a configuration window in my coupled oscillator simulation. But when I want to get the value of tkinter variables to set up the system, I only get ''.
I tried to change the type from tk.DoubleVar() to tk.StringVar() but nothing seems to works...
Here the code for the configuration frame for one object. Then I create two of them and add them to the configuration frame.
import tkinter as tk
class MassConfig(tk.Frame):
def __init__(self, root, **kwargs):
tk.Frame.__init__(self, root, kwargs)
self.grid()
# Variables :
self.weight = tk.StringVar()
self.vitesse = tk.StringVar()
self.position = tk.StringVar()
self.lbl_weight = tk.Label(self, text='Masse :')
self.lbl_weight.grid(row=0, column=0)
self.entry_weight = tk.Entry(self, textvariable=self.weight, width=5)
self.entry_weight.grid(row=0, column=1)
self.lbl_vit = tk.Label(self, text='Vitesse :')
self.lbl_vit.grid(row=1, column=0, pady=5)
self.entry_vit = tk.Entry(self, textvariable=self.vitesse, width=5)
self.entry_vit.grid(row=1, column=1)
self.lbl_pos = tk.Label(self, text='Position :')
self.lbl_pos.grid(row=2, column=0)
self.entry_pos = tk.Entry(self, textvariable=self.position, width=5)
self.entry_pos.grid(row=2, column=1)
Here the code of the configuration frame, which has two 'MassConfig' frame inside.
import tkinter as tk
from gui.masse_config import MassConfig
class Configuration(tk.Frame):
def __init__(self, root, **kwargs):
tk.Frame.__init__(self, root, **kwargs)
self.root = root
self.grid()
self.update()
self.is_alive = True
self.data = {}
self.m1_frame = tk.LabelFrame(self, text='Masse 1', width=200, height=200)
self.m1_frame.grid(column=0, row=0, padx=(10, 5), pady=(10, 10))
self.m2_frame = tk.LabelFrame(self, text='Masse 2', width=200, height=200)
self.m2_frame.grid(column=1, row=0, padx=(5, 10), pady=(10, 10))
self.config_1 = MassConfig(self.m1_frame)
self.config_2 = MassConfig(self.m2_frame)
self.config_1.grid(padx=10, pady=10)
self.config_2.grid(padx=10, pady=10)
self.btn_validation = tk.Button(self, text='Valider', command=self.validation)
self.btn_validation.grid(row=3, column=1, padx=10, pady=(0, 10), sticky=tk.E)
self.update()
def validation(self):
print(":", self.config_1.position.get())
self.data['Mass 1'] = {}
self.data['Mass 1']['Position'] = self.config_1.position.get()
self.data['Mass 1']['Vitesse'] = self.config_1.vitesse.get()
self.data['Mass 1']['Masse'] = self.config_1.weight.get()
self.data['Mass 2'] = {}
self.data['Mass 2']['Position'] = self.config_2.position.get()
self.data['Mass 2']['Vitesse'] = self.config_2.vitesse.get()
self.data['Mass 2']['Masse'] = self.config_2.weight.get()
self.is_alive = False
self.root.destroy()
I want to have the value of the tkinter variables self.weight, self.vitesse and self.position from the MassConfig class in a dictionary (self.data from Configuration class). But nothing come out, except ''.

Tkinter threading for socket receiving data

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()

Resources