Python 3 Tkinter : Popup not displaying - python

I have a 2 popups triggered by the same button : One have a progress bar, a label and a button. The other only have 2 labels and a button. If I comment the update function of the progress bar : neither of the popup is displayed. If I try to only display the second (without progress bar) it doesn't display. I can only display both at the same time and I want only to display the second one (without progress bar)
Here is the code of the first popup :
def sim_process_bar(self):
self.popup_process = Tk()
self.popup_process.wm_title("Simulation process...")
self.progressBar = ttk.Progressbar(self.popup_process, orient = 'horizontal', length = 286, mode = 'determinate')
self.progressBar['maximum'] = 100
self.stopBtn = Button(self.popup_process, text="Stop Simulation", command = self.popup_process.destroy)
self.progressBar.grid(column = 1, row = 1, pady = 10)
self.stopBtn.grid(column = 1, row = 2)
self.labelPercentage = Label(self.popup_process, text="Percentage complete : 0% ")
self.labelPercentage.grid(column = 1, row = 3, pady = 10)
def update_value_process_bar(self, value):
self.progressBar['value'] = value
self.progressBar.update()
The code of the second popup :
def process_feedback(self):
self.popupFeedback = Tk()
self.popupFeedback.wm_title("Simulation process...")
self.labelTimestep = Label(self.popupFeedback, text="Current timestep : ")
self.labelTimestep.grid(column = 0 , row = 1, pady = 10)
self.labelPercentage2 = Label(self.popupFeedback, text="Percentage complete : ")
self.labelPercentage2.grid(column = 0, row = 2, pady = 10)
self.Btnstop = Button(self.popupFeedback, text="Stop Simulation", command = self.popupFeedback.destroy)
self.Btnstop.grid(column = 0, row = 3)
I call the function at the just before the beggining of a loop and then update values inside this same loop :
the update :
if(round(k/self.total_timestep_of_simulation*100,1).is_integer()):
self.update_value_process_bar(k/self.total_timestep_of_simulation*100)
self.labelPercentage['text'] = "Percentage complete : " + str(round(k/self.total_timestep_of_simulation*100,1)) + "%"
#UPDATE POPUP FEEDBACK
self.labelTimestep['text'] = "Current timestep : " + str(data_update.strftime("%b %d %Y %H:%M:%S"))
self.labelPercentage2['text'] = "Percentage complete : " + str(round(k/self.total_timestep_of_simulation*100,1)) + "%"
so if I comment the "self.update_value"... function, nothing shows up on screen and if I only try to display the second one nothing shows up neither. I'm sure it's a dumb problem, but I'm struggling with this...

Your code is ok, but try to remove the line self.stopBtn = Button(self... or replace it by
self.stopButton = Button(self.popup_process,
text="Stop Simulation",
command = self.destroy_popup)
and add
def destroy_popup(self):
self.popup_process.destroy()
And same for the other popup:
self.Btnstop = Button(self.popupFeedback,
text="Stop Simulation",
command = self.destroy_popup)
...
def destroy_popup(self):
self.popupFeedback.destroy()
Sometimes the button "makes the connection" to the control to which it is attached. In this example, self.popup_process.destroy is a loop contained in Tkinter module. So the button executes that command. Putting it in a def avoids this.
That is only valid for certain versions. Maybe the one you're using is one of them. Otherwise I don't know.

Related

Tkinter: Output widget isn't displaying text

I'm relatively new when it comes to python and even more new when it comes to Tkinter, and I am making a Dice game program using GUIs and functions. At the end of the game, a new window pops up and displays some text with an output Widget that is meant to display the score, however, it doesn't appear. I believe I am using the right syntax, and there are no error messages when I run the program. Any answer would be appreciated.
Here is my code below:
'''
# SPICEY DICE Code snippet.
# - Create window
window2 = Tk()
window2.title("SPICEY DICE - Single Player Finish")
# - Label 1
Label(window2, text = "CONGRATULATIONS!").grid(row = 0, column = 0, sticky = W)
# - Label 2
Label(window2, text = "You have finished SPICEY DICE with a score of:").grid(row = 1, column = 0, sticky = W)
# - Text box 1
Output5 = Text(window2, width = 5, height = 1, wrap = WORD, background = "yellow")
Output5.grid(row = 2, column = 0, sticky = W)
# - Button 1
Button(window2, text = "LEADERBOARD", width = 15, command = SPLeaderboard).grid(row = 3, column = 0, sticky = W)
# - Label 3
Label(window2, text = "Close all of the windows to finish.").grid(row = 4, column = 0, sticky = W)
# - Run mainloop
window2.mainloop()
Output5.delete(0.0, END)
Output5.insert(END, str(TotalScore))
'''
The Output widget in question is 'Output5' and 'TotalScore' is the variable that is meant to be printed into it but doesn't appear.
Many Thanks.
I guess you need to write:
Output5.delete(0.0, END)
Output5.insert(END, str(TotalScore))
these codes between Tk() and mainloop.

Python skipped one of my function

I am using a tkinter frame to call another tkinter frame. So from frame one i will click a button and it will check if there is a file at C:\ and if the file is not there it should call the Chrome_gui function which is another tkinter frame at "def p2(self)". When the Chrome_gui is called it will create the test file and the self.p2 will be called again to check if the file is there. But it will become a never ending loop as the function self.Chrome_guiis not called. And when i remove self.p2, the function self.Chrome_gui can be called. So can anyone tell me why it is skipping the self.Chrome_gui function?
def __init__(self):
tk.Tk.__init__(self)
tk.Tk.title(self,"qwerty")
self.b1 = tk.Button(self, text="P2", command = self.p2)
self.b1.grid(row = 3, column = 1, sticky = 'EWNS' )
def p2 (self):
self.values()
print ('printdwo')
my_file1 = Path("C:\test.pdf")
if my_file1.is_file():
print ("File Found")
else:
print ('not found')
self.Chrome_gui()
self.p2()
def Chrome_gui(self):
self.chrome = tk.Tk()
self.chrome.title('Date')
self.label = tk.Label(self.chrome, text="", width=20)
self.label.grid(row = 1, column = 1)
self.c1 = tk.Button(self.chrome, text="Yes", command = self.yes)
self.c1.grid(row = 2, column = 1, sticky = W+E)#side = LEFT)
global e
e = ""
self.c2 = tk.Button(self.chrome, text = "No" , command = self.no)
self.c2.grid(row = 3, column = 1, sticky = W+E)#side = LEFT)
Your code is looping because your condition if my_file1.is_file(): is always false so it's always calling self.p2() in the else part.
When you're defining a string and you want to put a '\', you have to put '\'. In your case you have '\t' so it will replace it by a tabulation. Replace it by Path("C:\\test.pdf")

.get() not working correctly with entry boxes in tkinter

game_entry = Entry(gs, width = 10, bg = 'white')
game_entry.grid(row=4, column = 0, sticky=W)
ip = game_entry.get()
part1 = partial(click2, ip)
Button(gs, text = "Submit", width = 6, command = part1, bg='white').grid(row=5, column = 0, sticky=W)
output = Text(gs, width = 25, height = 1, wrap=WORD,bg = 'white')
output.grid(row = 7,column=0,sticky=W)
def click2(a):
if a == 'a':
print('hello')
If I click the button and the entry box says 'a' (without the quote marks), nothing gets printed and if i define click2 as:
def click2(a):
if a != 'a':
print('hello')
and type 'a' (again, without quote marks), it does print it even thought it shouldn't.
Does anyone know why?
Thanks
The problem is because you get the value of the entry widget about a millisecond after you create the entry widget. You need to wait until the user clicks the button before you call the .get() method.

Multi-page window cannot highlight Entry text with callback

Recently I've changed the layout of my program to include a multi-page window similar to what is in the provided example.
In the original, two-window configuration I had a binding set on each window to highlight all of the text in the Entry widget, based on a condition (no condition present in the example). This was fine.
Upon upgrading to a multi-page window, I tried to combine the callback to highlight text by passing the relevant widget and calling widget.select_range(0, END) as it is done in the example. Now I can't seem to highlight any text on mouse-click.
In addition to this, I've also tested my example code with having a separate callback for each Entry; even this would not highlight the text in the Entry upon clicking on it.
Could this have something to do with lifting frames & where the focus lies? As a test I've added a similar callback for "submitting" the Entry value, and this is working fine. At this point I'm confused as to why this wouldn't work. Any help is greatly appreciated.
UPDATE:
I forgot that to solve the highlighting problem, I've needed to include a return "break" line in the callback that is used to highlight the text.
Now, with this included, I have some very strange behavior with the Entry widgets. I can't click on them unless they have been focused using the tab key.
Is there any way to work around this problem?
Here is the example code I have been playing with (with the updated return statement):
from Tkinter import *
class Window():
def __init__(self, root):
self.root = root
self.s1 = StringVar()
self.s1.set("")
self.s2 = StringVar()
self.s2.set("")
# Frame 1
self.f1 = Frame(root, width = 50, height = 25)
self.f1.grid(column = 0, row = 1, columnspan = 2)
self.page1 = Label(self.f1, text = "This is the first page's entry: ")
self.page1.grid(column = 0, row = 0, sticky = W)
self.page1.grid_columnconfigure(index = 0, minsize = 90)
self.val1 = Label(self.f1, text = self.s1.get(), textvariable = self.s1)
self.val1.grid(column = 1, row = 0, sticky = E)
self.l1 = Label(self.f1, text = "Frame 1 Label")
self.l1.grid(column = 0, row = 1, sticky = W)
self.e1 = Entry(self.f1, width = 25)
self.e1.grid(column = 1, row = 1, sticky = E)
self.e1.bind("<Button-1>", lambda event: self.event(self.e1))
self.e1.bind("<Return>", lambda event: self.submit(self.e1, self.s1))
# Frame 2
self.f2 = Frame(root, width = 50, height = 25)
self.f2.grid(column = 0, row = 1, columnspan = 2)
self.page2 = Label(self.f2, text = "This is the 2nd page's entry: ")
self.page2.grid(column = 0, row = 0, sticky = W)
self.page2.grid_columnconfigure(index = 0, minsize = 90)
self.val2 = Label(self.f2, text = self.s2.get(), textvariable = self.s2)
self.val2.grid(column = 1, row = 0, sticky = E)
self.l2 = Label(self.f2, text = "Frame 2 Label")
self.l2.grid(column = 0, row = 1, sticky = W)
self.e2 = Entry(self.f2, width = 25)
self.e2.grid(column = 1, row = 1, sticky = E)
self.e2.bind("<Button-1>", lambda event: self.event(self.e2))
self.e2.bind("<Return>", lambda event: self.submit(self.e2, self.s2))
self.b1 = Button(root, width = 15, text = "Page 1", command = lambda: self.page(1), relief = SUNKEN)
self.b1.grid(column = 0, row = 0, sticky = E)
# Buttons
self.b2 = Button(root, width = 15, text = "Page 2", command = lambda: self.page(2))
self.b2.grid(column = 1, row = 0, sticky = W)
# Start with Frame 1 lifted
self.f1.lift()
def page(self, val):
self.b1.config(relief = RAISED)
self.b2.config(relief = RAISED)
if val == 1:
self.f1.lift()
self.b1.config(relief = SUNKEN)
else:
self.f2.lift()
self.b2.config(relief = SUNKEN)
def event(self, widget):
widget.select_range(0, END)
return "break"
def submit(self, widget, target):
target.set(widget.get())
root = Tk()
w = Window(root)
root.mainloop()
Well, this has been a productive question. If anyone in the future is doing something similar to this and needs a reference for how to solve the problem:
I was able to work around the problem by forcing the Entry widgets into focus every time I switch frames, and using the return "break" statement that I mention in the question's update.
This isn't ideal, as every time a page is changed you automatically focus on the Entry widget, but once the widget is in focus it's behavior is exactly what I would expect so this isn't of great concern. In my program, if you are changing pages it is quite likely you will use the Entry widget anyway (it is a search entry).
Here's the final changes required to make the code work correctly:
# .... some code ....
self.f1.lift()
self.e1.focus_force()
def page(self, val):
self.b1.config(relief = RAISED)
self.b2.config(relief = RAISED)
if val == 1:
self.f1.lift()
self.b1.config(relief = SUNKEN)
self.e1.focus_force()
else:
self.f2.lift()
self.b2.config(relief = SUNKEN)
self.e2.focus_force()
def event(self, widget):
widget.select_range(0, END)
return "break"
# .... more code ....

Python: Waiting for the enter key OR button press (Text Based Adventure with GUI)

Hi I am making a text based adventure in python and am having trouble with taking the user input, the text the user reads is in one text box and the input goes in an entry box.
I don't know how to get it to wait for the user to press enter or for a button to be pressed on the actual GUI.
I have tried:
textin.bind('<Return>', get_input)
but that didn't work for some reason I couldn't work out.
I have also tried:
import msvcrt as m
def wait():
m.getch()
but that made the GUI not show up or I wasn't using it properly.
Another thing I have tired is:
import time
time.sleep(5.0)
but that had the same problem of the GUI not showing up until after the countdown.
I cannot use
input()
as I am using a GUI and if I use that then the GUI won't show up until after or some other problem (I may be wrong, I'm still new to some of this)
I need to know how I can get it to take the text in the entry when the user presses enter OR a button on the GUI, and all that needs to be in a function so that the main game can wait for them to enter a command.
The code so far:
import tkinter as tk
def get_input(): #the button I put in had problems
player_command = textin.get() #if this function wasn't before it
root = tk.Tk()
frame = tk.Frame(root)
frame.grid(row = 0, column = 0)
textout = tk.Text(frame, width = 50, height = 23)
scroll = tk.Scrollbar(frame)
textin = tk.Entry(frame, width = 50)
button = tk.Button(frame, text = 'Submit', command = get_input)
textout.grid(row = 0, columnspan = 2, sticky = tk.W + tk.E)
textin.grid(row = 1, column = 0, sticky = tk.W + tk.E)
button.grid(row = 1, column = 1, sticky = tk.W + tk.E)
scroll.grid(row = 0, column = 1, sticky = tk.N + tk.S + tk.E)
scroll.config(command = textout.yview)
def main_menu():
textout.configure(state = 'normal')
textout.insert(tk.END, "Welcome to The Adventure\n")
textout.insert(tk.END, "What would you like to do?\n")
textout.insert(tk.END, "Continue\n")
textout.insert(tk.END, "New Game\n")
textout.insert(tk.END, "Help\n")
textout.configure(state = 'disabled')
while True:
if player_command == 'continue':
load_game() #other function
elif player_command == 'new game':
character_creation() #other function
elif player_command == 'help':
help_info() #other function
else:
textout.configure(state = 'normal')
textout.insert(tk.END, "Unknown command, type 'help' for hints")
textout.configure(state = 'disabled')
main_menu()
root.mainloop()
Thanks in advance.
Here Is an example of taking user input from text box.
Note that in this example Enter key is used to get the string on current line and submit button is used to print the currently held data.
import Tkinter as tk
class Test(object):
def __init__(self, root):
self.laststat=0#just to check multiple <Enter key> press do not delete the data
self.currString=""
self.tempString=""
self.text = tk.Text(root)
self.text.bind('<Key>', self.stripLine)
self.text.pack(side=tk.LEFT)
self.text.focus()
self.button = tk.Button(root, text = 'Submit', command = self.printData)
self.button.pack(side=tk.LEFT)
def stripLine(self, event):
val=('{k!r}'.format(k = event.char))[1:-1]
if val=='\\r' and self.laststat==0:
self.currString=self.tempString
self.tempString=""
self.laststat=1
elif val!='\\r':
self.tempString+=val
self.laststat=0
def printData(self):
print 'Current String is :'+self.currString
#print 'temp String is :'+self.tempString
root = tk.Tk()
A = Test(root)
root.mainloop()
Also note that you can add similar functions (similar to stripLine) to handle backspace and similar other key presses

Categories

Resources