Multiprocessing not working with progress bar in tkinter - python-3.x

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

Related

Web shortcut not doing what i want it to do

So before you question the code, im just trying to learn tkinter a bit more so i though this be best way haha.
I am currently stuck on the web input, everytime i input a website it comes as "https://%21browser.%21text!" and i dont know why. Random web works but it doesnt work as inputting it.
import webbrowser as wb
from tkinter import *
from tkinter import ttk
import tkinter as tk
import ctypes, random, time
class Browser(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.start()
def start(self):
global webinput
self.title = Label(self, text="Web Shortcut", fg="purple", font="Kokila 20 bold")
self.title.pack(fill=BOTH)
self.webinput = Text(self, height=1, width=57)
self.webinput.pack(side=TOP, fill=BOTH, pady=30, padx=30)
self.openweb = Button(self, height=2, width=20, text="Open Web", bg="gray", fg="lightgreen", command=self.web)
self.openweb.pack(side=LEFT, padx=10)
self.random = Button(self, height=2, width=20, text="Random Web", bg="gray", fg="lightgreen", command=self.randomweb)
self.random.pack(side=LEFT, padx=5)
self.exit = Button(self, height=2, width=20, text="Exit", bg="gray", fg="lightgreen", command=exit)
self.exit.pack(side=LEFT, padx=5)
def web(self):
try:
self.sites = "https://{}".format(self.webinput)
if self.sites:
wb.open(self.sites)
except Exception as e:
ctypes.windll.user32.MessageBoxW(0, str(e), "CRASHED", 0)
def randomweb(self):
self.websites = [
"www.facebook.com",
"www.google.com",
"www.youtube.com",
"www.amazon.co.uk"
]
self.sites = random.choice(self.websites)
self.visit = "https://{}".format(self.sites)
wb.open(self.visit)
if __name__ == "__main__":
root = Tk()
root.title("Web Shortcut")
root.resizable(False, False)
root.geometry("500x200")
app = Browser(master=root)
app.mainloop()
root.destroy()
I have made some change, now it works very well
import webbrowser as wb
from tkinter import *
from tkinter import ttk
import tkinter as tk
import ctypes, random, time
class Browser(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.start()
def start(self):
global webinput
self.title = Label(self, text="Web Shortcut", fg="purple", font="Kokila 20 bold")
self.title.pack(fill=BOTH)
self.webinput = Entry(self)
self.webinput.pack(side=TOP, fill=BOTH, pady=30, padx=30)
self.openweb = Button(self, height=2, width=20, text="Open Web", bg="gray", fg="lightgreen", command=self.web)
self.openweb.pack(side=LEFT, padx=10)
self.random = Button(self, height=2, width=20, text="Random Web", bg="gray", fg="lightgreen", command=self.randomweb)
self.random.pack(side=LEFT, padx=5)
self.exit = Button(self, height=2, width=20, text="Exit", bg="gray", fg="lightgreen", command=exit)
self.exit.pack(side=LEFT, padx=5)
def web(self):
try:
self.sites = f"https://{self.webinput.get()}"
if self.sites:
wb.open(self.sites)
except Exception as e:
ctypes.windll.user32.MessageBoxW(0, str(e), "CRASHED", 0)
def randomweb(self):
self.websites = [
"www.facebook.com",
"www.google.com",
"www.youtube.com",
"www.amazon.co.uk"
]
self.sites = random.choice(self.websites)
self.visit = "https://{}".format(self.sites)
wb.open(self.visit)
if __name__ == "__main__":
root = Tk()
root.title("Web Shortcut")
root.resizable(False, False)
root.geometry("500x200")
app = Browser(master=root)
app.mainloop()
root.destroy()
Hope it helps. (●'◡'●)

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?

Ttk Frame, Background color

I'm using ttk, for my GUI. I know that it is also a very simple question ... I am trying to change the background color of the main window.
I tried to change the theme, because I am working on a Mac, (and Python 3.5) to avoid the problem with the theme 'aqua', which is the default.I've been reading about several solutions like these questions which are about the same problem... These are the numbers of the questions:
54476511,
38712352,
47327266,
23750141.
But, I haven't Solve the problem, yet.
Here it's my code.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from tkinter.scrolledtext import *
from tkinter import Tk, BOTH, W, N, E, S, messagebox, END
from tkinter.ttk import Button, Label, Style, Frame
class Example(Frame):
def __init__(self,master):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Example")
Style().theme_use("classic")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
self.txt_Pad = ScrolledText(self)
self.txt_Pad.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N)
self.txt_Pad.insert(END,'Type your info here')
btn_save = Button(self, text="Save", command=self.save_command)
btn_save.grid(row=1, column=3)
btn_close = Button(self, text="Close", command=self.onClose)
btn_close.grid(row=2, column=3, pady=4)
btn_help = Button(self, text="Help", command=self.about_command)
btn_help.grid(row=5, column=0, padx=5)
def onClose(self):
self.master.destroy()
def about_command(self):
msb = messagebox.showinfo("About", "\"Insert a useful tip Here\"")
def save_command(self):
print('Your info it\'s save now')
def open_command(self):
print('Choose your File')
def main():
root = Tk()
root.geometry("350x300+300+300")
root.configure(bg='#0059b3')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
Any Suggestions would be appreciated.
Create a style then apply it.
from tkinter.scrolledtext import *
from tkinter import Tk, BOTH, W, N, E, S, messagebox, END
from tkinter.ttk import Button, Label, Style, Frame
class Example(Frame):
def __init__(self, master):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Example")
# create a new style
self.style = Style()
# configure it to the background you want
self.style.configure('My.TFrame', background='#0059b3')
#Style().theme_use("classic")
# apply it
self.config(style='My.TFrame')
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
self.txt_Pad = ScrolledText(self)
self.txt_Pad.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N)
self.txt_Pad.insert(END,'Type your info here')
btn_save = Button(self, text="Save", command=self.save_command)
btn_save.grid(row=1, column=3)
btn_close = Button(self, text="Close", command=self.onClose)
btn_close.grid(row=2, column=3, pady=4)
btn_help = Button(self, text="Help", command=self.about_command)
btn_help.grid(row=5, column=0, padx=5)
def onClose(self):
self.master.destroy()
def about_command(self):
msb = messagebox.showinfo("About", "\"Insert a useful tip Here\"")
def save_command(self):
print('Your info it\'s save now')
def open_command(self):
print('Choose your File')
def main():
root = Tk()
root.geometry("350x300+300+300")
root.configure(background='#0059b3')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
I left comments at the parts I changed.

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 ''.

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