Hey guys I have just started learning about GUI's and in particular just started using tkinter. I have spent hours searching forums for what I believe should be an obvious and simple solution and found a few people asking similar questions but i failed to understand the solutions.
Basically I am just trying to get the user to input a letter with an entry widget and display that on a label when the go button is pressed. If anyone could explain to me how to do this I would be extremely grateful.
Here's the code I have written:
#!/usr/bin/env python3
from tkinter import*
from tkinter import ttk
import random
root = Tk()
root.title('test')
frame = ttk.Frame(root, padding='3 3 12 12 ')
frame.grid(column=0, row=0, sticky=(N, W, E, S))
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)
letter = StringVar()
def gobutton(*args):
print_label['text'] += letter
print_label = ttk.Label(frame, text="")
print_label.grid(column=1, row=1, sticky=N)
letter_entry = ttk.Entry(frame, width=7, textvariable=letter)
letter_entry.grid(column=1, row=2, sticky=S)
g_button = ttk.Button(frame, width=7, text='GO', command=gobutton)
g_button.grid(column=3, row=3, sticky=S)
for child in frame.winfo_children():
child.grid_configure(padx=5, pady=5)
letter_entry.focus() #WHAT DOES THIS DO?
root.bind('<Return>', gobutton)
root.mainloop()
You should .get() what StringVar contains when button is clicked.
def gobutton(): #if you don't plan to pass any parameters, *args is unnecesarry
print_label['text'] += letter.get()
Also, for this program, using a StringVar a little bit overkill. You can easily go for Entry.get() to get what entry contains. Below code demonstrates how to use get() method with a quite simple(and a little bit dirty) code.
def getMethod():
lbl.configure(text=ent.get())
#or
#lbl["text"] = ent.get()
root = tk.Tk()
tk.Button(root, text="Get Entry", command=getMethod).pack()
ent = tk.Entry(root)
lbl = tk.Label(root, text = "Before click")
lbl.pack()
ent.pack()
root.mainloop()
.focus() is an alias for .focus_set() method.
Moves the keyboard focus to this widget. This means that all keyboard
events sent to the application will be routed to this widget.
Related
from tkinter import *
def Click():
label = Label(root, text="You clicked it")
label.pack()
root = Tk()
label2 = Label(root, text="You can only click one time")
Button = Button(root, text="Click me", padx=20, pady=20, state=NORMAL,
command=Click,state=DISABLED)
Button.pack()
label2.pack()
root.mainloop()
Because I use state 2 times I am getting this error:
SyntaxError: keyword argument repeated: state
How can I fix this error and make a button that can be clicked one time?
This should do what you want. The idea is to update the button's state from within the click handler function.
FYI, star imports can cause trouble and are best avoided, so I've done that here. I've also changed some variable names to use lowercase, since capitalized names are typically reserved for class objects in Python (things like Label and Tk, for instance!)
import tkinter as tk
def click():
label = tk.Label(root, text="You clicked it")
label.pack()
button.config(state=tk.DISABLED) # disable the button here
root = tk.Tk()
label2 = tk.Label(root, text="You can only click one time")
button = tk.Button(root, text="Click me", padx=20, pady=20, command=click)
button.pack()
label2.pack()
root.mainloop()
Bonus Round - if you want to update the existing label (label2, that is) instead of creating a new label, you can also accomplish this with config
def click():
label2.config(text="You clicked it") # update the existing label
button.config(state=tk.DISABLED) # disable the button here
I been searching for methods to copy text to clipboard or copy the results from Tkinter gui but idk if there is a command or something
here is my code for now here the result comes in a messagebox can i copy it to clipboard
import tkinter.messagebox
import string
import random
def qs_msgbbox(): # qs_msgbbox
tkinter.messagebox.showinfo("Info", "For customer support or tip or rating contact:"
"dghaily725#gmail.com\npress the button for generated pass\nmsg will appear then copy\nthe generated password")
def gen_pass(k=9): # gen_pass
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*"
password = ''
for i in range(9):
password += random.choice(char)
tkinter.messagebox.showinfo("Password", password)
root = Tk()
root.title("Password Generator")
lbl1 = Label(root, text="Generate Password", bd=2, relief=SUNKEN, height=5, width=50, bg='black', fg='white')
lbl1.configure(font=(70))
lbl1.grid(row=0, column=2)
lbl2 = Label(root, text='For more information press the Question mark', bd=2, relief=SUNKEN, fg='red')
lbl2.configure(font=(70))
lbl2.grid(row=0, column=0, pady=10)
btn1 = Button(root, text='Press to Generate', height=5, width=50, bg='grey', command=gen_pass)
btn1.configure(font=(70))
btn1.grid(row=1, column=2, padx=460, pady=50)
btn2photo = PhotoImage(file='question.png')
btn2 = Button(root, image=btn2photo, width=30, height=30, command= qs_msgbbox)
btn2.grid(row=0, column=1)
root.mainloop()
and also just a quick small question is it better to use classes or this form
Tkinter does have a function for that, simply just
from tkinter import Tk
root = Tk()
root.clipboard_clear()
root.clipboard_append("Something to the clipboard")
root.update() # the text will stay there after the window is closed
Hope I could help
Greets
The above answer is perfectly fine. Infact its the method to do it. I read the comments, He had mentioned that it could only take in string. That is completely false. It can also take in functions. For example..
import tkinter as tk
root = tk.Tk()
#creating a entry Widget.(Labels are fine as well)
entry = tk.Entry(root)
entry.pack()
#NOW if you want to copy the whole string inside the above entry box after you
typed in #
def copy ():#assign this function to any button or any actions
root.clipboard_clear()
root.clipboard_append(entry.get()) #get anything from the entry widget.
root.mainloop()
Hoping this was helpful
I'm new to trying out python GUI's and tried tkinter and pyglet, but only through tutorials, in-order-to understand the basic classes and functions. But what I'm currently trying to do is to get a button to increase a number whilst displaying that number at the same time. Somehow, even though the variable number was stated globally as 0, the function to increase it doesn't do anything, it actually produces an error: 'UnboundLocalError: local variable 'number' referenced before assignment'. I have no idea how to correct this.
The tutorials I've seen on both YouTube and as an article, don't talk about how to do this exactly. The article does mention how to change a certain text though, but not a previously created variable (which in my case would be 'number').
from tkinter import *
number = 0
window = Tk()
window.title("Programme")
window.geometry('350x250')
label = Label(window, text=number)
label.grid(column=0,row=0)
def clicked():
number += 1
button = Button(window, text="Push Me", command=clicked)
button.grid(column=1, row=2)
window.mainloop()
Is there any way to do this?
Also I've been looking for how to add time, to handle events and such, through ticks. But everything I find on the internet is about literally displaying a clock on the GUI, which is useless, or at least I don't know how to use it to have a ticking function.
You need to increment the number, like you do, but also update the Label to display the new number:
from tkinter import *
number = 0
window = Tk()
window.title("Programme")
window.geometry('350x250')
label = Label(window, text=number)
label.grid(column=0,row=0)
def clicked():
global number
number += 1
label.config(text=number)
button = Button(window, text="Push Me", command=clicked)
button.grid(column=1, row=2)
window.mainloop()
An easier way to do this is to use tkinter's version of an integer: IntVar. It takes care of the Label updates automatically, but it requires you use get() and set() to work with it.
from tkinter import *
def clicked():
number.set(number.get()+1)
window = Tk()
window.title("Programme")
window.geometry('350x250')
number = IntVar()
label = Label(window, textvariable=number)
label.grid(column=0,row=0)
button = Button(window, text="Push Me", command=clicked)
button.grid(column=1, row=2)
window.mainloop()
Here is my entire code:
from tkinter import *
def up():
number.set(number.get()+1)
def down():
number.set(number.get()-1)
window = Tk()
window.title("Programme")
window.geometry('350x250')
number = IntVar()
frame = Frame(window)
frame.pack()
entry = Entry(frame, textvariable=number, justify='center')
entry.pack(side=LEFT, ipadx=15)
buttonframe = Frame(entry)
buttonframe.pack(side=RIGHT)
buttonup = Button(buttonframe, text="▲", font="none 5", command=up)
buttonup.pack(side=TOP)
buttondown = Button(buttonframe, text="▼", font="none 5", command=down)
buttondown.pack(side=BOTTOM)
window.mainloop()
It looks better for me when the buttons are inside of the entry widget directly.
I'm new to tkinter and have a rather simple question. I would like to change focus from the first window, root, to the txt window after it pops up. I would also like the "OK" button to be focused as well. Of course, the idea is for the user to just be able to hit enter when they see this error. I'm terribly confused after various attempts with focus(), focus_set(), and takefocus. I'm not finding the documentation for this particularly helpful.
Below is my code:
from tkinter import *
from tkinter import ttk
def close(self):
self.destroy()
def browse(*args):
fileName = filedialog.askopenfilename()
guiInputFile_entry.insert(0, fileName)
return fileName
def formatInput(*args):
if guiInputFile.get()[-4:] != ".txt": #checks for correct file extension (.txt)
txt = Tk()
txt.title("Error")
txtFrame = ttk.Frame(txt, padding="30 30 30 30")
txtFrame.grid(column=0, row=0, sticky=(N,W,E,S))
txtFrame.columnconfigure(0, weight=1)
txtFrame.rowconfigure(0, weight=1)
ttk.Label(txtFrame, text = "Please enter a .txt file.\n").grid(column=2, row=1)
okButton = ttk.Button(txtFrame, text = "OK", command = lambda: close(txt)).grid(column=2, row=2)
return
root = Tk()
root.title("Cost Load Formatter")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N,W,E,S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
guiInputFile = StringVar()
guiInputFile_entry = ttk.Entry(mainframe, width=100, textvariable=guiInputFile)
guiInputFile_entry.grid(column=1, row=2, stick=(W,E))
ttk.Label(mainframe, text="Please enter the full filepath of the .txt file you wish to format:").grid(column=1, row=1)
browseButton = ttk.Button(mainframe, text="Browse...", underline=0, command=browse).grid(column=2, row=2, sticky=W)
formatButton = ttk.Button(mainframe, text="Format", underline=0, command= lambda: formatInput(guiInputFile)).grid(column=1, row=3)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
guiInputFile_entry.focus()
root.mainloop()
Thank you for any light you can shed.
You're on the right track.
Firstly, you should only ever have one instance of Tk at a time. Tk is the object that controls the tkinter application, it just so happens that it also shows a window. Whenever you want a second window (third, fourth, etc.) you should use Toplevel. You can use it as you have used Tk, just pass it root:
txt = Toplevel(root)
It is just missing things like mainloop.
Secondly grid and pack do not return anything. So for example:
okButton = ttk.Button(txtFrame, text = "OK", command = lambda: close(txt)).grid(column=2, row=2)
Should be:
okButton = ttk.Button(txtFrame, text = "OK", command = lambda: close(txt))
okButton.grid(column=2, row=2)
But you should have been getting an error if that was causing you problems.
So to answer your main question, as you do with the Entry at the bottom you just call focus on the appropriate widget. focus_set does exactly the same, in fact if you look in Tkinter.py you will find focus_set is the name of the method, and focus is just an alias.
This will give the widget focus when the application has focus. If the application is not in focus there are ways to force it into the focus, but it is considered impolite and you should let the window manager control that.
Instead of making a seperate Tk Window, you could use the built in tkmessagebox. This will give the window and OK button focus right out of the box.
Something like this:
tkMessageBox.showinfo("Warning","Please enter a .txt file.")
http://www.tutorialspoint.com/python/tk_messagebox.htm
Also, note I wrote this in Python 2.7, the syntax may be slightly different for Python 3, but the functionality should be the same.
I'm trying to use an Entry field to get manual input, and then work with that data.
All sources I've found claim I should use the get() function, but I haven't found a simple working mini example yet, and I can't get it to work.
I hope someone can tel me what I'm doing wrong. Here's a mini file:
from tkinter import *
master = Tk()
Label(master, text="Input: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
content = entry.get()
print(content) # does not work
mainloop()
This gives me an Entry field I can type in, but I can't do anything with the data once it's typed in.
I suspect my code doesn't work because initially, entry is empty. But then how do I access input data once it has been typed in?
It looks like you may be confused as to when commands are run. In your example, you are calling the get method before the GUI has a chance to be displayed on the screen (which happens after you call mainloop.
Try adding a button that calls the get method. This is much easier if you write your application as a class. For example:
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.entry = tk.Entry(self)
self.button = tk.Button(self, text="Get", command=self.on_button)
self.button.pack()
self.entry.pack()
def on_button(self):
print(self.entry.get())
app = SampleApp()
app.mainloop()
Run the program, type into the entry widget, then click on the button.
You could also use a StringVar variable, even if it's not strictly necessary:
v = StringVar()
e = Entry(master, textvariable=v)
e.pack()
v.set("a default value")
s = v.get()
For more information, see this page on effbot.org.
A simple example without classes:
from tkinter import *
master = Tk()
# Create this method before you create the entry
def return_entry(en):
"""Gets and prints the content of the entry"""
content = entry.get()
print(content)
Label(master, text="Input: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
# Connect the entry with the return button
entry.bind('<Return>', return_entry)
mainloop()
*
master = Tk()
entryb1 = StringVar
Label(master, text="Input: ").grid(row=0, sticky=W)
Entry(master, textvariable=entryb1).grid(row=1, column=1)
b1 = Button(master, text="continue", command=print_content)
b1.grid(row=2, column=1)
def print_content():
global entryb1
content = entryb1.get()
print(content)
master.mainloop()
What you did wrong was not put it inside a Define function then you hadn't used the .get function with the textvariable you had set.
you need to put a textvariable in it, so you can use set() and get() method :
var=StringVar()
x= Entry (root,textvariable=var)
Most of the answers I found only showed how to do it with tkinter as tk. This was a problem for me as my program was 300 lines long with tons of other labels and buttons, and I would have had to change a lot of it.
Here's a way to do it without importing tkinter as tk or using StringVars. I modified the original mini program by:
making it a class
adding a button and an extra method.
This program opens up a tkinter window with an entry box and an "Enter" button. Clicking the Enter button prints whatever is in the entry box.
from tkinter import *
class mini():
def __init__(self):
master = Tk()
Label(master, text="Input: ").grid(row=0, sticky=W)
Button(master, text='Enter', command=self.get_content).grid(row=1)
self.entry = Entry(master)
self.entry.grid(row=0, column=1)
master.mainloop()
def get_content(self):
content = self.entry.get()
print(content)
m = mini()