I am able to get a frame to open from a button. I can close the frame and reopen it from the same button but it throws an error everytime I push the button.
What is throwing the error in my code is root.Show() , it gives me a AttributeError Show error
My question is, although it is working beautifully, could it develop a serious problem for my application?
EDIT: This is the code in my python file
from Tkinter import *
root = Tk()
root.title("Help")
scrollbar = Scrollbar(root)
scrollbar.pack(side=RIGHT, fill=Y)
help_message = 'This is the help menu. Please scroll through the menu to find the answer to your question'
txt = Text(root, wrap=WORD) # wrap=CHAR, wrap=NONE
txt.pack(expand=1, fill=BOTH)
txt.insert(END, help_message)
txt.config(yscrollcommand=scrollbar.set, state=DISABLED)
scrollbar.config(command=txt.yview)
root.Show()
It is taking the error from the last line of this program. And this is the error in the command prompt:
You probably just want to use root.mainloop(), because I don't see anywhere the method Show or show (Python is case sensitive, and methods/functions are usually lower_case_with_underscores).
The mainloop function essentially waits for the program to end, but if you have things like buttons, you can have Tkinter call a certain function to respond (event driven).
I removed root.Show(), added a button that has to be clicked in order for the window to stay hidden but running. I then added in the main file HelpBox.root.deiconify() which makes the screen pop up. If the user does click the "X" button, then the help menu cannot be reopened until they restart the application.
Thanks for everyone's help and ideas
Related
I'm making an app in tkinter which uses the ttk.Scale widget to show the process of an mp3 song.
I have a function that I want to add buttons with the names of which (the buttons) should be relied on filenames. Therefore I've made this example:
from tkinter import Tk, Button
from tkinter.filedialog import askopenfilenames
from tkinter.ttk import Scale
from threading import Timer
root = Tk()
slider = Scale(root, from_=0, to=100, orient='horizontal')
slider.pack()
# slider is continuously set to a bigger number so that it keeps going
def update_slider(num):
slider.set(num)
num += 1
root.after(50, update_slider, num)
update_slider(num=0)
# this function creates buttons based on the files opened
def add_buttons():
# the 'X' button of this particular window slows down execution of update_slider function
files = askopenfilenames(title='Add Buttons')
for i in list(files):
Button(root, text=i).pack()
button = Button(root, text='Browse', command=lambda: Timer(0.1, add_buttons).start())
button.pack()
root.mainloop()
The problem I'm facing is that when I open the askopenfilenames dialog box or when I press its 'X' button, my slider which is running continuously in the background gets stuck, and as a result doesn't show the process correctly.
Here is a picture where I hold down the 'X' button and the ttk.Scale stops moving:
I've tried using threading to run the add_buttons function but the behavior of the program remains the same.
Can I edit the askopenfilenames dialog box with something similar like overrideredirect(True) so that I can make my own title bar and 'X' button and the events generated not to slow down my Scale?
Replying to:
I cannot reproduce the issue in Linux, the scale keeps moving no matter what I do with the filedialog window. So this may be an OS specific issue.
I'm aware that this problem doesn't appear on Linux. I faced the same problem with the root's close button and other Toplevels' close button, but I fixed it by replacing the title bar using overrideredirect(True).
Is there anything similar I can do with this askopenfilenames window?
This error is popping up when I close a subwindows in tkinter. The program runs OK but everytime I click the close button I got that error.
I guess the right question is how can I assigned the close button to the exit command.
I think what you want is this:
from tkinter import *
window = Tk()
def close():
window.destroy()
button1 = Button(window, text = "close", command = close).pack()
window.mainloop()
When you click the button in the window, the window closes. The .destroy() command makes a widget dissapear, and it also deletes all data associated with it.
This means if you call it again, you will get an error.
Read up more about .destroy() here.
Hopefully this helps!
I'm woking on a project of a chatting app, using tkinter, running on python 3.7 and Windows 10 OS. One of the things I would like to add to my app, is an option of opening up the Windows's Touch Keyboard.
Although you can open the keyboard by pressing its button on the taskbar, I would like to give access to it from my app. My idea is to bind an Entry widget, used as the console line of my app, to an event, that whenever it occurrs, it makes the Touch Keyboard to pop up. The event I'll probably be using is '<FocusIn>', which means that the keyboard focus is moved to it. Here is a quick example of the mechanics:
def open_keyboard(event):
pass # open the Touch Keyboard
root = Tk()
console = Entry(root, font=('Verdana', 14), cursor='pencil', bg='red', fg='yellow') # creating console
console.pack()
console.bind('<FocusIn>', open_keyboard) # bind the console to the event
root.mainloop()
NOTICE: The Touch Keyboard IS NOT the On-Screen Keyboard. I don't want to use this keyboard, because it poppes up as a new window and not as a Toplevel window, which blocks my chatting app. More Importantly, it has no Emoji keyboard :)
A simple way to open the On-Screen Keyboard, is by running the following lines:
import os
os.system('osk')
I've been searching all over the internet for a solution, but they're all seem to be handling the On-Screen Keyboard. If someone knows how to help me or divert me to a source that explains how to handle it, he's more than welcomed to do so, because I'm stuck right now :/
Try this (explanation in code comment)
I think this directory will be the same on almost all Windows installations, still I'm looking for a way to make it path independent.
from tkinter import *
import os
root = Tk()
def callback(event):
# so the touch keyboard is called tabtip.exe and its located in C:\Program Files\Common Files\microsoft shared\ink
# here we run it after focus
os.system("C:\\PROGRA~1\\COMMON~1\\MICROS~1\\ink\\tabtip.exe")
frame = Frame(root, width=100, height=100)
frame.pack()
addressInput = Entry(frame, font = "Verdana 20 ", justify="center")
addressInput.bind("<FocusIn>", callback)
addressInput.pack()
root.mainloop()
I've made a program in python with Tkinter that allows you to free draw and choose different colors. I decided to make a button that would close the window instead of clicking the exit button in the top right corner. My question is how do I make the window close when the button is pressed?
If you are using a main loop for your application, then you can use the .destroy() method to release all the resources associated with the window and close the application. You call this method within the command function for your button like so:
from tkinter import *
root = Tk()
frame = Frame(root)
frame.pack(side=LEFT)
button = Button(frame, text="Exit", command=exit)
button.pack()
root.mainloop()
def exit():
root.destroy()
That should close your window. Optionally, the destroy() method may also be used at the end of your main loop if the X button of your application won't close the window immediately.
See these examples for more info:
http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.destroy-method
http://effbot.org/tkinterbook/tkinter-hello-again.htm
In tkinter, when a button has the focus, you can press the space bar to execute the command associated with that button. I'm trying to make pressing the Enter key do the same thing. I'm certain I've done this in the past, but I can't find the code, and what I'm doing now isn't working. I'm using python 3.6.1 on a Mac.
Here is what I've tried
self.startButton.bind('<Return>', self.startButton.invoke)
Pressing the Enter key has no effect, but pressing the space bar activates the command bound to self.startButton. I've tried binding to <KeyPress-KP_Enter> with the same result.
I also tried just binding to the command I want to execute:
self.startButton.bind('<Return>', self.start)
but the result was the same.
EDIT
Here is a little script that exhibits the behavior I'm talking about.
import tkinter as tk
root = tk.Tk()
def start():
print('started')
startButton.configure(state=tk.DISABLED)
clearButton.configure(state=tk.NORMAL)
def clear():
print('cleared')
clearButton.configure(state=tk.DISABLED)
startButton.configure(state=tk.NORMAL)
frame = tk.Frame(root)
startButton = tk.Button(frame, text = 'Start', command = start, state=tk.NORMAL)
clearButton = tk.Button(frame, text = 'Clear', command = clear, state = tk.DISABLED)
startButton.bind('<Return>', start)
startButton.pack()
clearButton.pack()
startButton.focus_set()
frame.pack()
root.mainloop()
In this case, it works when I press space bar and fails when I press Enter. I get an error message when I press Enter, saying that there an argument was passed, but none is required. When I change the definition of to take dummy argument, pressing Enter works, but pressing space bar fails, because of a missing argument.
I'm having trouble understanding how wizzwizz4's answer gets both to work. Also, I wasn't seeing the error message when I pressed Enter in my actual script, but that's way too long to post.
** EDIT AGAIN **
I was just overlooking the default value of None in Mike-SMT's script. That makes things plain.
Your use of self.startButton.bind('<Return>', self.start) should work fine as long as compensate for the event that the bind will send to the function/method.
Here is a simple example that will work with the enter key as long as the button has focus.
import tkinter as tk
root = tk.Tk()
def do_something(event=None):
print("did something!")
btn = tk.Button(root, text="Do something", command=do_something)
btn.pack()
btn.bind("<Return>", do_something)
#root.bind("<Return>", do_something) will work without the button having focus.
root.mainloop()
This only works when the button has keyboard focus. Also, an argument representing the event object is passed to the callable provided. The former doesn't seem to be the problem, so try:
self.startButton.bind('<Return>', lambda e: self.startButton.invoke())