I'm new in Tkinter and I'm currently trying to create a small game. When something happens in the game I want to create a pop-up window which will inform the user about any changes. This is the code that I have written for it.
def message(self, text):
top = tkinter.Toplevel(width=50, height=25)
top.title("Message")
msg = tkinter.Message(top, text=text)
msg.pack()
ok = tkinter.Button(top, text="OK", command=top.destroy)
ok.pack()
My two questions are:
Can I replace this by an exception that will create an "Error Message" window? If it isn't necessary then can I use it to be raised by the exception?
I want the user to be forced to see and read the message, so how can I freeze the main window(the user can't click on anything else) until he presses the OK button on the pop-up window?
Use:
top.grab_set()
To show Error Message you can use tkmessagebox.showerror().
Related
I have assigned a function to my ttk button and I'm trying to disable the button before do_something_else() runs:
def do_something():
button.config(state='disabled')
do_something_else()
button = ttk.Button(mainframe, text="Click Me", command=do_something, state="normal")
The above doesn't disable the button until do_something_else() is finished. How do I disable correctly? The behavior I want to achieve is to disable the button -> run do_something_else() - > re-enable the button.
EDIT
Accepted answer is correct, for more details refer to Tkinter Button still responds to click after being disabled and updated
You can call button.update_idletasks() to force tkinter to refresh the display.
I have a multi-frame Tkinter program running and am in a situation where I need a new frame to open without a button press.
If I were to have a button it would be coded like this:
button = tk.Button(self, text="New Window",
command=lambda: controller.show_frame("NewWindow"))
Is there a way I can make a new window open after a time.sleep(60) command? This is what I have tried:
def on_button(self):
if LogIn in Data:
time.sleep(5)
print("Welcome")
root.after(6, controller.show_frame("HomePage"))
else:
print("please register")
Various Data and coding goes after the defining. If the condition is true it 'Logs In' This is when I want it to show the new frame
Root gives the error of: NameError: name 'root' is not defined
Controller.after(etc) gives : NameError: name 'controller' is not defined
Despite controller being used frequently without issue throughout the rest of the program
I would recommend the after callback See: Alarm handlers and other non-event callbacks
after(delay_ms, callback=None, *args) [#]
Registers an alarm callback that is called after a given time.
root.after(60000, new_window_func, args)
In my program I just need to notify user to not press a physical button om a system with no keyboad or mouse,
want to popup a Wait message that disapears when the system is again ready
There are two reasons you don't want a message box here.
First, the whole point of a message box is that it's a modal dialog with some standardized buttons, and you don't want those buttons.
Second, the whole point of a modal dialog is that it's modal—it runs its own event loop, and doesn't return until the dialog is dismissed. This means (unless you're using background threads) your app can't do anything while displaying it.
The first problem is easy to solve. tkMessageBox is just a simple wrapper around tkCommonDialog.Dialog. It's worth looking at the source to see just how simple it is to construct a dialog box that does what you want. But tkSimpleDialog.Dialog is even simpler than tkCommonDialog (hence the name). For example:
class WaitDialog(tkSimpleDialog.Dialog):
def __init__(self, parent, title, message):
self.message = message
Dialog.__init__(self, parent, title=title, message=message)
def body(self, master):
Label(self, text=self.message).pack()
def buttonbox(self):
pass
def wait(message):
WaitDialog(root, title='Wait', message=message)
That's all it takes to create a modal dialog with no buttons. Dialog Windows and the source to tkSimpleDialog have more details.
The second problem is even easier to solve: If you don't want a modal dialog, then all you want is a plain old Toplevel. You may want it to be transient, so it stays on top of the master, hides with it, doesn't show up on the taskbar, etc., and you may want to configure all kinds of other things. But basically, it's this simple:
def wait(message):
win = Toplevel(root)
win.transient()
win.title('Wait')
Label(win, text=message).pack()
return win
Now you can call wait() and continue to run:
def wait_a_sec():
win = wait('Just one second...')
root.after(1000, win.destroy)
root = Tk()
button = Button(root, text='do something', command=wait_a_sec)
root.mainloop()
I'm using EPD traits for a basic GUI interface. I'm able to pop up a settings window using code like this:
settings_w.configure_traits(kind="livemodal")
The window has 'OK' and 'Cancel' buttons and I want to do something different depending on which button was pressed to exit the window. Seems like it should be simple but I can't figure out how to set this up.
Theoretically I'd like to do something like this:
# Display the settings widget
settings_w.configure_traits(kind="livemodal")
if settings_w.CancelButtonPressed:
pass
else:
print "I got the input"
But let me know if there's a better or more correct way to do this.
Also FWIW: here's the view properties of my settings window with standard OK and Cancel buttons:
view = View(
settings_group,
title = 'Settings Editor',
width = 500,
buttons = [OKButton, CancelButton, 'Help' ],
kind = 'modal',
handler = SaveRestore_Handler()
)
If I understand the question, checking the output of configure_traits should do what you want:
result = settings_w.configure_traits(kind="livemodal")
if result:
print "The user pressed OK."
else:
print "The user pressed Cancel or closed the window."
When opening a new tkinter window, I only want the user to be able to click buttons on the new window. They should not be able to click on buttons from other windows that are part of the application. How would I accomplish this?
Here is a snip of my code:
def exportEFS(self):
self.exportGUI = Toplevel()
Button(self.exportGUI, text='Backup', command=self.backup).pack(padx=100,pady=5)
Button(self.exportGUI, text='Restore', command=self.restore).pack(padx=100,pady=5)
def backup(self):
self.backupWindow = Toplevel()
message = "Enter a name for your Backup."
Label(self.backupWindow, text=message).pack()
self.entry = Entry(self.backupWindow,text="enter your choice")
self.entry.pack(side=TOP,padx=10,pady=12)
self.button = Button(self.backupWindow, text="Backup",command=self.backupCallBack)
self.button.pack(side=BOTTOM,padx=10,pady=10)
In this snip, once the backupWindow is opened, the exportGUI remains open, but the user should not be able to click "Backup" or "Restore" while the backupWindow is opened.
Thanks!
You will want to call grab_set on the TopLevel window so that all keyboard and mouse events are sent to that.
def exportEFS(self):
self.exportGUI = Toplevel()
Button(self.exportGUI, text='Backup', command=self.backup).pack(padx=100,pady=5)
Button(self.exportGUI, text='Restore', command=self.restore).pack(padx=100,pady=5)
def backup(self):
self.backupWindow = Toplevel()
self.backupWindow.grab_set()
message = "Enter a name for your Backup."
Label(self.backupWindow, text=message).pack()
self.entry = Entry(self.backupWindow,text="enter your choice")
self.entry.pack(side=TOP,padx=10,pady=12)
self.button = Button(self.backupWindow, text="Backup",command=self.backupCallBack)
self.button.pack(side=BOTTOM,padx=10,pady=10)
What you can do is set the state to disabled. As so:
self.button.config(state="disabled")
And to enable it, you just use:
self.button.config(state="normal")
However, you must assign your buttons to variables first, like this:
self.backup=Button(self.exportGUI, text='Backup', command=self.backup)
self.backup.pack(padx=100,pady=5)
self.restore=Button(self.exportGUI, text='Restore', command=self.restore)
self.restore.pack(padx=100,pady=5)
so you would disable these using:
self.backup.config(state="disabled")
self.restore.config(state="disabled")
and re-enable using:
self.backup.config(state="normal")
self.restore.config(state="normal")
Please note however, that while the button is disabled, nothing can be changed to that button, both through the code, or through the user using it. So that means if you wanted to change the text of that button, you would have to change the state of the button to "normal" before changing it (if it already isn't in that state, which by default, all widgets are in that state when first created).
Cheers :)