Tkinter memory leak - python

I am doing a rather easy project that many have done before. Here is my hardware setup:
Raspberry Pi 3 w/16GB SD card
DHT11 Temperature Humidity sensor
Raspberry Pi 7" display
I am using Tkinter with Python 2.7 and Adafruit_DHT library.
The code is very basic
from Tkinter import *
import tkFont
import Adafruit_DHT
import sys
import time
temp = 0
win = Tk()
win.title("Temperature")
sans = tkFont.Font(family='FreeSansBold', size=28, weight=tkFont.BOLD)
Label(win, text="Temperature", relief=SUNKEN, width=15, font=sans).grid(row=0, column=0)
Label(win, text="Humidity", relief=SUNKEN, width=15, font=sans).grid(row=1, column=0)
Label(win, text="Date/Time", relief=SUNKEN, width=15, font=sans).grid(row=2, column=0)
def READ():
global temp
humidity, temperature = Adafruit_DHT.read_retry(11, 4)
temp = temperature*9/5.0 + 32
Label(win, text=temp, relief=RIDGE, width=15, fg="black", bg="white", font=sans).grid(row=0, column=1)
Label(win, text=humidity, relief=RIDGE, width=15, fg="black", bg="white", font=sans).grid(row=1, column=1)
Label(win, text=time.strftime("%b %d %I:%M"), relief=RIDGE, width=15, fg="black", bg="white", font=sans).grid(row=2, column=1)
def read_every_second():
READ()
win.after(1000, read_every_second)
win.after(1000, read_every_second)
mainloop()
It works great except that it causes a memory leak. I am sure that it is forcing endless loops with the "win.after(1000, read_every_second) call however, I do not know how to fix it.
Any help would be appreciated.

Thanks to those that posted...
I have completely reworked my code and eliminated the leak.
I am not an accomplished programmer but, I am posting so others can get a idea of what I did (with others help) to make this project work.
from Tkinter import *
import Adafruit_DHT
import time
import tkFont
from PIL import ImageTk, Image
master = Tk()
sans = tkFont.Font(family='FreeSansBold', size=52) #weight=tkFont.BOLD)
#sans = tkFont.Font(family='Roboto', size=52)
dkblue = '#0b1c3c'
master.geometry("700x400")
master.configure(background=dkblue)
temperature = 0
humidity = 0
original = Image.open("./Downloads/fish.png")
resized = original.resize((100, 100), Image.ANTIALIAS)
image = ImageTk.PhotoImage(resized)
m1 = Label(master, text = 'Temp ', bg = dkblue, fg = 'yellow', font = sans)#, relief = RIDGE, borderwidth = 5)
m1.grid(row = 0, column = 0, sticky = E)
w1 = Label(master, text= temperature, bg = dkblue, fg = 'white', font = sans)
w1.grid(row = 0, column = 1, sticky = W)
m2 = Label(master, text = 'Humid ', bg = dkblue, fg = 'yellow', font = sans)#, relief = RIDGE, borderwidth = 5)
m2.grid(row = 1, column = 0, sticky = E)
w2 = Label(master, text = humidity, bg = dkblue, fg = 'white', font = sans)
w2.grid(row = 1, column = 1, sticky = W)
t1 = Label(master, text = 'Date ', bg = dkblue, fg = 'yellow', font = sans)
t1.grid(row = 2, column = 0, sticky = E)
t2 = Label(master, text = time.strftime('%b %d'), bg = dkblue, fg = 'white', font = sans)
t2.grid(row = 2, column = 1, sticky = W)
t3 = Label(master, text = 'Time ', bg = dkblue, fg = 'yellow', font = sans)
t3.grid(row = 3, column = 0, sticky = E)
t3 = Label(master, text = time.strftime('%I:%M:%S'), bg = dkblue, fg = 'white', font = sans)
t3.grid(row = 3, column = 1, sticky = W)
imglabel = Label(master, image=image, bg = dkblue)
imglabel.grid(row = 0, column = 2, sticky = E)
def CHANGE():
global temperature
global humidity
humidity, temperature = Adafruit_DHT.read_retry(11, 4)
temperature = (temperature * 9/5.0 + 32)
w1.config(text = temperature)
w2.config(text = humidity)
t2.config(text = time.strftime('%b %d'))
t3.config(text = time.strftime('%I:%M:%S'))
master.after(2000, CHANGE)
master.after(2000, CHANGE)
mainloop()

Related

My scrollbar is not working with mouse's scroller

I have reused the code.
I am trying to scroll this frame and the scrollbar is working but
I want it to be scrolled using the scroller of mouse.
What should I do?
I want it to be scrolled vertically only.
from tkinter import *
root = Tk()
root['bg'] = 'wheat'
frame_container=Frame(root, width = 1000)
frame_container['bg'] = 'wheat'
canvas_container=Canvas(frame_container, width = 1000)
canvas_container['bg'] = 'wheat'
frame2=Frame(canvas_container, width = 1000)
frame2['bg'] = 'wheat'
scrollbar_tk = Scrollbar(frame_container,
orient="vertical",command=canvas_container.yview)#,
yscrollcommand=scrollbar_tk.set
# will be visible if the frame2 is to to big for the canvas
canvas_container.create_window((0,0),window=frame2,anchor='nw')
naan = IntVar()
roti=IntVar()
dal=IntVar()
manchurian = IntVar()
makhani=IntVar()
masala_bhindi = IntVar()
chole = IntVar()
rajma = IntVar()
shahi_panneer = IntVar()
kadahi_paneer = IntVar()
masala_gobhi = IntVar()
allo_gobhi = IntVar()
matar_paneer = IntVar()
menu_roti = "Tava Roti 25 ₹/piece"
menu_dal = "Dal 80 ₹/bowl"
menu_makhani = "Dal Makhni 110 ₹/bowl"
menu_naan = "Naan 50 ₹/piece"
menu_manchurian = "Manchurian 110 ₹/plate"
menu_shahi_panneer = "Shahi paneer 110₹/bowl"
menu_kadahi_paneer = "Kadhai paneer 150/bowl"
menu_masala_gobhi = "Masala gobhi 130₹/bowl"
menu_allo_gobhi = "Aloo gobhi 120₹/bowl"
menu_matar_paneer = "Matar paneer 135₹/bowl"
menu_masala_bhindi = "Masala bhindi 110₹/bowl"
menu_chole = "Chole 100₹/bowl"
menu_rajma = "Rajama 150₹/bowl"
menu_chaap = "Chaap 125₹/bowl"
menu_aloo_parntha = "Aloo parantha 35₹/peice"
menu_cheele = "Cheele 55₹/peice "
listItems = [menu_roti,menu_dal,menu_makhani, menu_naan,
menu_manchurian, menu_shahi_panneer,
menu_kadahi_paneer, menu_masala_gobhi,
menu_allo_gobhi, menu_matar_paneer, menu_masala_bhindi,
menu_chole, menu_rajma, menu_chaap, menu_aloo_parntha,
menu_cheele]
Title = Label(frame2, text = " Food Items
Prices Quantities", fg = 'red', bg = 'wheat', font=
("arial", 30))
Title.grid()
for item in listItems:
label = Label(frame2,text=item, fg = 'yellow', bg =
'wheat', font=("arial", 30))
label.grid(column=0, row=listItems.index(item)+1)
q_roti = Entry(frame2, font=("arial",20), textvariable = roti,
fg="Black", width=10)
q_roti.grid(column = 1, row = 1)
q_dal = Entry(frame2, font=("arial",20), textvariable = dal,
fg="black", width=10)
q_dal.grid(column = 1, row = 2)
q_makhani = Entry(frame2, font=("arial",20), textvariable =
makhani, fg="black", width=10)
q_makhani.grid(column = 1, row = 3)
q_naan = Entry(frame2, font=("arial",20), textvariable = naan,
fg="black", width=10)
q_naan.grid(column = 1, row = 4)
q_manchurian = Entry(frame2,font=("arial",20), textvariable =
manchurian, fg="black", width=10)
q_manchurian.grid(column = 1, row = 5)
q_shahi_panneer = Entry(frame2, font=("arial",20), textvariable
= shahi_panneer, fg="black", width=10)
q_shahi_panneer.grid(column = 1, row = 6)
q_kadahi_panneer = Entry(frame2, font=("arial",20),
textvariable = kadahi_paneer, fg="black", width=10)
q_kadahi_panneer.grid(column = 1, row = 7)
q_masala_gobhi = Entry(frame2, font=("arial",20), textvariable
= masala_gobhi, fg="black", width=10)
q_masala_gobhi.grid(column = 1, row = 8)
q_allo_gobhi = Entry(frame2, font=("arial",20), textvariable =
allo_gobhi, fg="black", width=10)
q_allo_gobhi.grid(column = 1, row = 9)
q_matar_panneer = Entry(frame2, font=("arial",20), textvariable
= matar_paneer, fg="black", width=10)
q_matar_panneer.grid(column = 1, row = 10)
q_masala_bhindi = Entry(frame2, font=("arial",20), textvariable
= masala_bhindi, fg="black", width=10)
q_masala_bhindi.grid(column = 1, row = 11)
q_cholle = Entry(frame2,font=("arial",20), textvariable =
chole, fg="black", width=10)
q_cholle.grid(column = 1, row = 12)
q_rajma = Entry(frame2,font=("arial",20), textvariable = rajma,
fg="black", width=10)
q_rajma.grid(column = 1, row = 13)
frame2.update() # update frame2 height so it's no longer 0 (
height is 0 when it has just been created )
canvas_container.configure(yscrollcommand=scrollbar_tk.set,
scrollregion="0 0 0 %s" % frame2.winfo_height()) # the
scrollregion
mustbe the size of the frame inside it,
#in this case "x=0 y=0 width=0 height=frame2height"
#width 0 because we only scroll verticaly so don't mind about
the width.
canvas_container.grid(column = 1, row = 0)
scrollbar_tk.grid(column = 0, row = 0, sticky='ns')
frame_container.grid()#.pack(expand=True, fill='both')
root.mainloop()
Sorry for this code. This is not much understandable but maybe it is sufficient for someone of my level. please someone give me some advices to improve my skills.
You can use <MouseWheel> virtual event to scroll the canvas and ultimately the frame.
canvas_container.create_window((0,0),window=frame2,anchor='nw')
def _on_mousewheel(event):
canvas_container.yview_scroll(-1*int(event.delta/120), "units")
canvas_container.bind_all("<MouseWheel>", _on_mousewheel)

How to access text inside an Entry widget from a function in tkinter?

I have a python GUI assignment in which I have to create a GUI application which will evaluate a single variable function within a specified range of input values. We have to use classes. I have written the following code:
from tkinter import *
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
import tkinter.font as font
class eval_interface:
def __init__(self):
self.root = Tk()
self.root.title("Function Evaluator")
self.topframe = Frame(self.root)
self.createTopFrame()
self.topframe.grid(row=0, column=0, columnspan=10, sticky=N + S + W + E)
self.frame2 = Frame(self.root)
self.createFrame2()
self.frame2.grid(row = 1, column = 0, pady = 15, columnspan = 10, sticky = N + S + W + E)
self.frame3 = Frame(self.root)
self.createFrame3()
self.frame3.grid(row=2, column=0, pady=15, columnspan=10, sticky=N + S + W + E)
self.frame4 = Frame(self.root)
self.frame5 = Frame(self.root)
self.createFrame5()
self.frame5.grid(row=4, column=0, pady=15, columnspan=10, sticky=N + S + E + W)
self.createFrame4()
self.frame4.grid(row = 3, column = 0, pady = 15, columnspan = 10, sticky = N+S+E+W)
self.root.mainloop()
def createTopFrame(self): #Frame containing title
title = Label(self.topframe, text="Function evaluator and plotter".center(228, " "), font=font.Font(size=17))
title.grid(row=0, column=0, columnspan=7)
def createFrame2(self): #Frame containing function Entry widget
title = Label(self.frame2, text = "Enter the function in x : ", font = font.Font(size = 14))
title.grid(row = 0, column = 0, sticky = N + S + W + E)
function_entry = Entry(self.frame2, width = 150)
function_entry.grid(row = 0, column = 1, sticky = N + S + W + E)
def createFrame3(self): #Frame containing range Entry widgets
range_label = Label(self.frame3, text="Enter the range of the function from : ", font = font.Font(size = 14))
lower_range_entry = Entry(self.frame3, width=10)
range_label2 = Label(self.frame3, text=" to ")
upper_range_entry = Entry(self.frame3, width=10)
range_label.grid(row=1, column=0, sticky="nsew")
lower_range_entry.grid(row=1, column=1)
range_label2.grid(row=1, column=2, sticky="nsew")
upper_range_entry.grid(row=1, column=3, sticky="nsew")
def createFrame4(self): #Frame containing button widgets
btn_evaluate = Button(self.frame4, text = "Evaluate", font = font.Font(size = 14), command = self.evaluate())
btn_plot = Button(self.frame4, text = "Plot", font = font.Font(size = 14))
btn_clear = Button(self.frame4, text = "Clear", font = font.Font(size = 14))
btn_exit = Button(self.frame4, text = "Exit", font = font.Font(size = 14), command = exit)
btn_evaluate.grid(row=0, column=0, padx=10, pady=5)
btn_plot.grid(row=0, column=1, padx=10, pady=5)
btn_clear.grid(row=0, column=2, padx=10, pady=5)
btn_exit.grid(row=0, column=3, padx=10, pady=5)
def createFrame5(self): #Frame containing Result Textbox
res_text = Text(self.frame5, width = 95, height = 55, padx = 10)
res_text.grid(row = 0, column = 0)
def evaluate(self):
x = 10
def clear(self):
z=12
eval_interface()
My question is, how do I access the data inputted by the user in the three entry widgets (in frames 2 and 3) when the Evaluate button is clicked? And after I have accessed the data and done the necessary operations on it, how do I display the result in the Textbox in Frame 5? (I have just coded some random statement in evaluate and clear functions for now to see the output GUI.)
If you want to access the Entry widgets inside evaluate() function, you need to change the three local variables function_entry, lower_range_entry and upper_range_entry to instance variables self.function_entry, self.lower_range_entry and self.upper_range_entry. Same for the Text widget res_text. Then you can get the values from the three Entry widgets and insert the result into self.res_text inside evaluate() function:
def createFrame2(self): #Frame containing function Entry widget
title = Label(self.frame2, text = "Enter the function in x : ", font = font.Font(size = 14))
title.grid(row = 0, column = 0, sticky = N + S + W + E)
self.function_entry = Entry(self.frame2, width = 150)
self.function_entry.grid(row = 0, column = 1, sticky = N + S + W + E)
def createFrame3(self): #Frame containing range Entry widgets
range_label = Label(self.frame3, text="Enter the range of the function from : ", font = font.Font(size = 14))
self.lower_range_entry = Entry(self.frame3, width=10)
range_label2 = Label(self.frame3, text=" to ")
self.upper_range_entry = Entry(self.frame3, width=10)
range_label.grid(row=1, column=0, sticky="nsew")
self.lower_range_entry.grid(row=1, column=1)
range_label2.grid(row=1, column=2, sticky="nsew")
self.upper_range_entry.grid(row=1, column=3, sticky="nsew")
...
def createFrame5(self): #Frame containing Result Textbox
self.res_text = Text(self.frame5, width = 95, height = 55, padx = 10)
self.res_text.grid(row = 0, column = 0)
def evaluate(self):
# get content from entries
x = self.function_entry.get()
lower = self.lower_range_entry.get()
upper = self.upper_range_entry.get()
# example on inserting result into text box
result = ", ".join([x, lower, upper]) # or whatever you want
self.res_text.insert("end", result)
...
Also command=self.evaluate() inside createFrame4() should be command=self.evaluate instead.

function to open a main GUI using a button from a PopUp GUI

I am new to Python, trying to make the Launch TFL App button open another GUI called "Menu GUI" but I don't know what to do for the def open_Menu(): function below. I want to use the popup GUI below as a launcher which takes the user to my main GUI. The only problem with the code below is that the button for launch TFL app doesn't do anything when you click it.
Here's my current code :
from tkinter import *
root = Tk()
root.title('TFL App')
p = Label(root, text = "TFL Journey Planner", height = "18", width = "250", bg = 'brown', fg =
'white',
font = ('Helvetica', '20', 'bold', 'italic'))
p.pack()
root.configure(bg = 'brown')
root.geometry('400x700')
photo = PhotoImage(file = 'trainstation.png')
label = Label(root, image = photo)
label.pack()
****#Buttons****
def open_Menu():
pass
Button1 = Button(root, text = "Launch TFL App", command = open_Menu, bg = "black", fg = 'white', padx
= 40,
pady = 10,
font = ('Calibri Light', '15', 'bold'))
Button1.pack(padx = 25, pady = 0)
Button2 = Button(root, text = "Exit ", command = root.destroy, bg = "black", fg = 'white', padx = 65,
pady = 8,
font = ('Calibri Light', '15', 'bold'))
Button2.pack(padx = 25, pady = 10)
root.mainloop()
How can I implement open_menu()
The code below is for my Main GUI which should open through the PopUp GUI above but the button on the PopUp GUI is not working.
from tkinter import *
def find():
# get method returns current text
# as a string from text entry box
From = From_field.get()
To = To_field.get()
travel_modes = mode_field.get()
# Calling result() Function
result(From, To, travel_modes)
# Function for inserting the train string
# in the mode_field text entry box
def train():
mode_field.insert(10, "train")
# Function for clearing the contents
def del_From():
From_field.delete(0, END)
distance_field.delete(0, END)
duration_field.delete(0, END)
def del_To():
To_field.delete(0, END)
distance_field.delete(0, END)
duration_field.delete(0, END)
def del_modes():
mode_field.delete(0, END)
distance_field.delete(0, END)
duration_field.delete(0, END)
def delete_all():
From_field.delete(0, END)
To_field.delete(0, END)
mode_field.delete(0, END)
distance_field.delete(0, END)
duration_field.delete(0, END)
# Driver code
if __name__ == "__main__":
# Create a GUI root
root = Tk()
# Set the background colour of GUI root
root.configure(background = 'light blue')
# Set the configuration of GUI root
root.geometry("600x400")
# Created a welcome to distance time calculator label
headlabel = Label(root, text = 'Welcome to your TFL Journey Planner',
fg = 'white', bg = "dark red", height = "0", width = "30",
font = ('calibri light', '19', 'italic'))
# Created a From: label
label1 = Label(root, text = "From:",
fg = 'white', bg = 'black')
# Created a To: label
label2 = Label(root, text = "To:",
fg = 'white', bg = 'black')
# Created a Distance: label
label4 = Label(root, text = "Distance:",
fg = 'white', bg = 'black')
# Created a Duration: label
label5 = Label(root, text = "Duration:",
fg = 'white', bg = 'black')
label6 = Label(root, text = "Choose travelling mode Below: ",
fg = 'white', bg = 'black')
headlabel.grid(row = 0, column = 1)
label1.grid(row = 1, column = 0, sticky = "E")
label2.grid(row = 2, column = 0, sticky = "E")
label4.grid(row = 7, column = 0, sticky = "E")
label5.grid(row = 8, column = 0, sticky = "E")
label6.grid(row = 3, column = 1)
# Created a text entry box
# for filling or typing the data.
From_field = Entry(root)
To_field = Entry(root)
mode_field = Entry(root)
distance_field = Entry(root)
duration_field = Entry(root)
From_field.grid(row = 1, column = 1, ipadx = "100")
To_field.grid(row = 2, column = 1, ipadx = "100")
mode_field.grid(row = 5, column = 1, ipadx = "50")
distance_field.grid(row = 7, column = 1, ipadx = "100")
duration_field.grid(row = 8, column = 1, ipadx = "100")
# CLEAR Button and attached
# to del_source function
button1 = Button(root, text = "Clear", bg = "light grey",
fg = "black", command = del_From)
# Create a CLEAR Button and attached to del_destination
button2 = Button(root, text = "Clear", bg = "light grey",
fg = "black", command = del_To)
# Create a RESULT Button and attached to find function
button3 = Button(root, text = "Result",
bg = "black", fg = "white",
command = find)
# Create a CLEAR ALL Button and attached to delete_all function
button4 = Button(root, text = "Clear All",
bg = "light grey", fg = "black",
command = delete_all)
# Create a Train Button and attached to train function
button5 = Button(root, text = "Train",
bg = "light grey", fg = "black",
command = train)
# Create a CLEAR Button and attached to del_modes function
button6 = Button(root, text = "Clear",
fg = "black", bg = "light grey",
command = del_modes)
button1.grid(row = 1, column = 2)
button2.grid(row = 2, column = 2)
button3.grid(row = 6, column = 1)
button4.grid(row = 9, column = 1)
button5.grid(row = 4, column = 1)
button6.grid(row = 5, column = 2)
root.mainloop()
Here is a solution using from subprocess import call. All you have to do is replace 'YOUR_FILE_NAME' with... your file name :D
from tkinter import *
from subprocess import call
root=Tk()
root.geometry('200x100')
frame = Frame(root)
frame.pack(pady=20,padx=20)
def open_Menu():
call(["python", "YOUR-FILE-NAME.py"])
btn=Button(frame,text='Open File',command=Open)
btn.pack()
root.mainloop()
What it will look like:
I hope this works for you :D

How to get the Scrollbar work during the multiple-entry (with condition) in tkinter frame within the tab?

I was trying to create the scrolled-abled in the frame, where there will be multiple entry lines according to the number of items present. My questions are
1.) My frame Nofy_frame1 with scrollbar is not working (Mentioned the comment #NOT WORKING part) and its position is too close to the entries I did not get any error response. How to solve it?
2.) How to stop/restart the loop while shifting the radio buttons of method 1 and method 2? Since for each click on Add entry button for method 2, the result would be :
Price 1 :
Price 2 :
Price 3 :
Price 4 :
Price 5 :
and then next click on the same Add entry button I am getting
Price 6 :
Price 7 :
Price 8 :
Price 9 :
Price 10 :
instead of the above result
How to resolve it?
I have written the fair code below, Please let me know and clarify my mistakes
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from tkcalendar import Calendar,DateEntry
from tkinter import messagebox
from tkinter.scrolledtext import ScrolledText
import os
from tkinter import *
import numpy as ny
master0 = tk.Tk()
master0.config(background = "white")
master0.title("Shop Cashier")
master0.geometry("1000x600")
master0.colour_schemes = [{"bg": "#eef1f5", "fg": "black"}, {"bg": "blue", "fg": "white"}]
tabs = ttk.Notebook(master0)
C_1 = 'black'
C_2 = 'white'
TStyler = ttk.Style()
TStyler.configure("TFrame", background=C_2, foreground=C_1, borderwidth=0)
tab1 = ttk.Frame(tabs, style = "TFrame")
tab2 = ttk.Frame(tabs, style = "TFrame")
tab3 = ttk.Frame(tabs, style = "TFrame")
C1 = Canvas(tab1, borderwidth=1, background="white")
C2 = Canvas(tab2, borderwidth=1, background="white")
C2 = Canvas(tab3, borderwidth=1, background="white")
tabs.add(tab1, text ='1')
tabs.add(tab2, text ='2')
tabs.add(tab3, text ='3')
tabs.pack(expand = 1, fill ="both")
#-TAB1
quit_button = tk.Button(tab1, text="Finish", fg="White", bg = "#53c653",padx=10, pady=3,command=master0.destroy)
quit_button.place(x = 450, y= 430)
#-TAB2
InitialInv_r = tk.DoubleVar()
CF_result = tk.DoubleVar()
P_r = tk.DoubleVar()
iiit_r = tk.IntVar()
alent = []
FCI_list = []
VCI_list = []
def addEntry():
if CF_result.get() == 2:
Nofy_frame = Frame(tab2, width = 10, height = 200, bd = 0, background = "#fff080")
Nofy_frame.place(x = 50, y= 150)
Nofy_frame1 = Frame(tab2, width = 270, height = 400, bd = 0, background = "#fff080")
Nofy_frame1.place(x = 50, y= 150)
#============================================================NOT WORKING
Nofy_frame1.pack_propagate(0) # stops frame from shrinking
scroll = Scrollbar(Nofy_frame1)
scroll.pack(side = RIGHT, fill = Y)
#============================================================NOT WORKING
for number in range(iiit_r.get()):
number = len(alent)
#label
ylab = Label(Nofy_frame1, text="Price "+str(number+1)+" :",bg = "#fff080")
ylab.grid(row=number+1, column=0, padx=10, pady=10)
#Entry
ent = Entry(Nofy_frame1, font=('calibri', 11), width = 33)
ent.grid(row=number+1, column=2,padx=10, pady=20)
alent.append( ent )
elif CF_result.get() == 0:
Nofy_frame = Frame(tab2, width = 328, height = 400, bd = 0, background = "#fff080")
Nofy_frame.place(x = 50, y= 150)
Nofy_frame2 = Frame(tab2, width = 270, height = 400, bd = 0, background = "#fff080")
Nofy_frame2.place(x = 50, y= 150)
ylab1 = Label(Nofy_frame2, text="Fixed Price :",bg = "#fff080" )
ylab1.grid(row=1, column=0, padx=2, pady=10)
#Entry
ent = Entry(Nofy_frame2, font=('calibri', 11), width = 30)
ent.grid(row=1, column=2,padx=10, pady=20)
alent.append( ent )
Disct = Label(tab2, text = ' Percentage', bg = "white",padx=3, pady=1,font = ("calibri", 12))
Disct.place(x=400, y=50)
Disctp = Label(tab2, text = '%', bg = "white",padx=3, pady=1,font = ("calibri", 12))
Disctp.place(x=642, y=50)
#Disct_frame = Frame(tab2, width = 200, height = 25, bd = 0, background = "white", highlightcolor = "black", highlightthickness = 1)
#Disct_frame.place(x = 530, y= 50)
Disctv = Entry(tab2,font=('calibri', 12), textvariable= P_r,width = 10, bd=1, bg='#fffce6', justify='left')
Disctv.place(x=560, y=50)
Nofy = Label(tab2, text = 'No. of items :', bg = "white",padx=3, pady=1,font = ("calibri", 12))
Nofy.place(x=700, y=50)
Nofy_frame = Frame(tab2, width = 328, height = 400, bd = 0, background = "#fff080", highlightcolor = "#fff080", highlightthickness = 1)
Nofy_frame.place(x = 50, y= 150)
Nofyv = Entry(tab2,font=('calibri', 12), textvariable= iiit_r, width = 5, bd=1, bg='#fffce6', justify='left')
Nofyv.place(x=800, y=50)
CashFlow = Label(tab2, text = 'Method', bg = "white",padx=3, pady=1,font = ("calibri light", 18))
CashFlow.place(x=50, y=100)
FCF_r = Radiobutton(tab2, variable = CF_result, value = 0, bg = "white")
FCF_r.place(x=180, y=110)
FCF_rr = Label(tab2, text = "method 1", bg = "white",padx=3, pady=1,font = ("calibri light", 12))
FCF_rr.place(x=200, y=108)
vCF_r = Radiobutton(tab2, variable = CF_result, value = 2,bg = "white")
vCF_r.place(x=380, y=110)
vCF_rr = Label(tab2, text = "method 2", bg = "white",padx=3, pady=1,font = ("calibri light", 12))
vCF_rr.place(x=400, y=108)
addEnt = Button(tab2, text='Add entry', fg="White", bg = "#1a1700", command=addEntry)
addEnt.place(x = 400, y= 150)
quit_button = tk.Button(tab2, text="Finish", fg="White", bg = "#53c653",padx=10, pady=3,command=master0.destroy)
quit_button.place(x = 900, y= 530)
master0.mainloop()

Executable using tkinter and multiprocessing creates multiple windows

I have built a gui for a script using tkinter.
I have tried building an executable with both cx_freeze and pyinstaller.
I make extensive use of scipy, numpy, statsmodels and matplotlib
Whenever I click the "Run" button, it spawns another window and the window beneath it stops responding. This can occur seemingly indefinitely.
I do use multiprocessing in my application, but I fixed the multiple windows issue in the python script version
How do I fix the multiple windows issue in my standalone program?
If there is not a reasonable fix, is there another way to package the program for use? Maybe a custom Python distribution?
from tkinter import *
from tkinter import ttk
def run():
import multiprocessing
import risers_fallers
import time
time_periods = list()
time_periods.append(month.get())
time_periods.append(threemonth.get())
time_periods.append(sixmonth.get())
time_periods.append(year.get())
#print(infile.get(), time_periods, filter_val.get(), outfile.get())
#loading screen
toplevel = Toplevel()
toplevel.focus_force()
loading = Label(toplevel, text = "RUNNING")#PhotoImage(file= photopath, format="gif - {}")
loading.pack()
subproc = multiprocessing.Process(target = risers_fallers.risers_fallers, args = (infile.get(), time_periods, filter_val.get(), outfile.get(),
top_x.get(), excel.get(), tableau.get(), onecat.get(), multicat.get(), external.get()))
subproc.start()
subproc.join()
toplevel.destroy()
def browsecsv():
from tkinter import filedialog
Tk().withdraw()
filename = filedialog.askopenfilename()
#print(filename)
infile.set(filename)
if __name__ == "__main__":
#initialize tk
root = Tk()
#set title
root.title("FM Risers and Fallers")
#create padding, new frame, configure columns and rows
#mainframe = ttk.Frame(root, padding="3 3 12 12")
#our variables
month = BooleanVar()
threemonth = BooleanVar()
sixmonth = BooleanVar()
year = BooleanVar()
excel = BooleanVar()
tableau = BooleanVar()
onecat = BooleanVar()
multicat = BooleanVar()
external = BooleanVar()
top_x = StringVar()
top_x.set("15")
infile = StringVar()
outfile = StringVar()
filter_val = StringVar()
photopath = "./41.gif"
#default values
filter_val.set("30")
import datetime
from re import sub
d = datetime.datetime.now()
outfile.set(sub('[^0-9|\s]',' ', str(d)))
"""
our widgets
"""
#labels for tab 1 Not needed with pane view
# ttk.Label(mainframe, text="Input file") #.grid(column=3, row=1, sticky=W)
# ttk.Label(mainframe, text="Output name") #.grid(column=3, row=1, sticky=W)
# ttk.Label(mainframe, text="Dashboard period of times") #.grid(column=3, row=1, sticky=W)
# ttk.Label(mainframe, text="Filter by growth rate") #.grid(column=3, row=1, sticky=W)
master = Frame(root, name = 'master')
master.pack(fill=BOTH)
#notebook container
notebook = ttk.Notebook(master)
notebook.pack(fill=BOTH, padx=2, pady=3)
tab0 = ttk.Frame(notebook)
tab1 = ttk.Frame(notebook)
tab2 = ttk.Frame(notebook)
notebook.add(tab0, text='Risers and Fallers')
notebook.add(tab1, text='Help')
notebook.add(tab2, text='About')
#tab 1 panes
panel_0 = ttk.Panedwindow(tab0, orient=VERTICAL)
file_pane_0 = ttk.Labelframe(panel_0, text='Input and Output', width = 300, height=100)
dashboard_pane_0 = ttk.Labelframe(panel_0, text='Dashboard Time Period', width = 300, height=200)
filter_pane_0 = ttk.Labelframe(panel_0, text='Filter by Growth Rate', width = 300, height=200)
run_frame_0 = Frame(panel_0, width = 300, height=100)
output_options_frame = ttk.Labelframe(panel_0, text='Output Options', width = 300, height=200)
top_x_frame_0 = ttk.Labelframe(panel_0, text = "Number of Risers", width = 300, height=100)
#grid it
panel_0.pack(fill=BOTH, expand=1)
file_pane_0.grid(row = 0, column = 0, columnspan = 3)
dashboard_pane_0.grid(row = 1, column = 0)
filter_pane_0.grid(row = 2, column = 0)
output_options_frame.grid(row = 1, column = 1)
top_x_frame_0.grid(row = 2, column = 1)
#pack em!
# panel_0.pack(fill=BOTH, expand=1)
# file_pane_0.pack(fill=X, expand=1)
# dashboard_pane_0.pack(side = LEFT, fill = Y)
# filter_pane_0.pack(side = RIGHT, fill = Y)
# top_x_frame_0.pack(fill=BOTH, expand=1)
#tab 2 panes
panel_1 = ttk.Panedwindow(tab1, orient=VERTICAL)
file_pane_1 = ttk.Labelframe(panel_1, text='Input and Output', width = 300, height=100)
dashboard_pane_1 = ttk.Labelframe(panel_1, text='Dashboard Time Period', width = 300, height=300)
filter_pane_1 = ttk.Labelframe(panel_1, text='Filter by Growth Rate', width = 300, height=300)
#pack em!
panel_1.pack(fill=BOTH, expand=1)
file_pane_1.pack(fill=BOTH, expand=1)
dashboard_pane_1.pack(side = LEFT, fill = Y)
filter_pane_1.pack(side = RIGHT, fill = Y)
#tab 3 panes
panel_2 = ttk.Panedwindow(tab2, orient=VERTICAL)
about_pane = ttk.Labelframe(panel_2, text='About', width = 300, height=200)
description_pane = ttk.Labelframe(panel_2, text='Description', width = 300, height=200)
citation_pane = ttk.Labelframe(panel_2, text='Citations', width = 300, height=200)
#pack em!
panel_2.pack(fill=BOTH, expand=1)
about_pane.pack(fill=BOTH, expand=1)
description_pane.pack(fill=BOTH, expand=1)
citation_pane.pack(fill=BOTH, expand=1)
#labels for tab 2 (help)
dashboard_help = ttk.Label(dashboard_pane_1, text= """Choose what units of
time to create a
dashboard for.
Note that time
periods are most
recent, not a
defined quarter or
calendar year.""")
io_help = ttk.Label(file_pane_1, text="""Output file: the first words to use in the naming of the output files
Input file: the BW output that you want to analyze.
See documentation for required format.""")
dashboard_help.pack()
io_help.pack(fill = BOTH)
#labels for tab 3 (about)
about_section = ttk.Label(about_pane, text="""The FM Risers and Fallers project was created by Jeremy Barnes
from May 2016 - July 2016 as a way to identify highest growing
parts.
Business logic was created based upon discussions with
Daniel DiTommasso, David Enochs, Alex Miles
and Robert Pietrowsky.
""")
description_section = ttk.Label(description_pane, text="""The FM Risers and Fallers application loads BW output from a
specific format, performs seasonal adjustment on the data,
derives information from the dataand then outputs all
derived information and dashboards with ranking information.
""")
citations_section = ttk.Label(citation_pane, text="""The FM Risers and Fallers project was created using
x13-ARIMA-SEATS by the US Census Bureau
pandas
statsmodels
Download links are available in the documentation
""")
#pack em
about_section.pack(fill=BOTH, expand=1)
description_section.pack(fill=BOTH, expand=1)
citations_section.pack(fill=BOTH, expand=1)
#file entry
#output
#output = Frame(file_pane_0, width = 300, height=50)
output_label = ttk.Label(file_pane_0, text="Output file").grid(column=1, row=1, sticky=W)
outfile_entry = ttk.Entry(file_pane_0, width = 50, textvariable = outfile).grid(column=2, row=1, sticky=W)
# output.pack(side = TOP, fill = X)
# output_label.pack(side = LEFT)
# outfile_entry.pack(side = RIGHT)
#input
#input = Frame(file_pane_0, width = 300, height=50)
input_label = ttk.Label(file_pane_0, text="Input file").grid(column=1, row=2, sticky=W)
infile_entry = ttk.Entry(file_pane_0, width = 50, textvariable = infile).grid(column=2, row=2, sticky=W)
#cbutton.grid(row=10, column=3, sticky = W + E)
bbutton= Button(file_pane_0, text="Browse", command= browsecsv).grid(column = 3, row = 2)
# input.pack(side = BOTTOM, fill = X)
# input_label.pack(side = LEFT)
# infile_entry.pack(side = RIGHT)
#top_x
top_x_label = ttk.Label(top_x_frame_0, text="Risers/Fallers to identify").grid(column=1, row=2, sticky=W)
top_x_entry = ttk.Entry(top_x_frame_0, width = 7, textvariable = top_x).grid(column=2, row=2, sticky=W)
#dashboard times
monthly = Checkbutton(dashboard_pane_0, text = "Month", variable = month).grid(row = 1, sticky=W, pady=1)
threemonthly = Checkbutton(dashboard_pane_0, text = "3 Months", variable = threemonth).grid(row = 2, sticky=W, pady=1)
sixmonthly = Checkbutton(dashboard_pane_0, text = "6 Months", variable = sixmonth).grid(row = 3, sticky=W, pady=1)
yearly = Checkbutton(dashboard_pane_0, text = "Year", variable = year).grid(row = 4, sticky=W, pady=1)
#output options
excel_button = Checkbutton(output_options_frame, text = "Excel", variable = excel).grid(row = 1, sticky=W, pady=1)
tableau_button = Checkbutton(output_options_frame, text = "Tableau", variable = tableau).grid(row = 2, sticky=W, pady=1)
onecat_button = Checkbutton(output_options_frame, text = "One Category", variable = onecat).grid(row = 3, sticky=W, pady=1)
multicat_button = Checkbutton(output_options_frame, text = "Many Categories", variable = multicat).grid(row = 4, sticky=W, pady=1)
external_button = Checkbutton(output_options_frame, text = "External Report", variable = external).grid(row = 5, sticky=W, pady=1)
#growth rate stuff
growth_input_label = ttk.Label(filter_pane_0, text="Analyze only top: ").grid(row = 1, column = 1, sticky=W, pady = 4, padx = 4)
growth_input = ttk.Entry(filter_pane_0, width = 7, textvariable = filter_val).grid(row = 1, column = 2, sticky=W, pady = 4, padx = 4)
# Radiobutton(filter_pane_0, text = "Standard Deviations", variable = stddev, value = 1).grid(row = 2, column = 1, sticky=W, pady = 4)
# Radiobutton(filter_pane_0, text = "Percentage", variable = stddev, value = 0).grid(row = 2, column = 2, sticky=W, pady = 4)
#growth_default_label = ttk.Label(filter_pane_0, text="(Leave blank for default").grid(row = 3, column = 1, sticky=W, pady = 4, padx = 4)
percent_label = ttk.Label(filter_pane_0, text=" %").grid(row = 1, column = 3, sticky=W, pady = 4, padx = 4)
#launch button
run_buttom_frame = Frame(panel_0, width = 300, height=50)
run_button = Button(run_buttom_frame, text = "RUN ANALYSIS", command = run)
run_button.pack()
run_buttom_frame.grid(row = 3, column = 0, columnspan = 2, pady = 4)
root.mainloop()
Two processes or more can't share a single root window. Every process that creates a widget will get its own window.
I managed to fix this with some experimentation.
It no longer launches multiple windows after I made the business logic launch within the same process.

Categories

Resources