How to use Tk button? [duplicate] - python

This question already has answers here:
How to pass arguments to a Button command in Tkinter?
(18 answers)
Closed 3 years ago.
I'm a beginner in Python and I'm trying to build some GUI to understand.
I want to pass to a button a function that requies a parameter, but when I launch the script, it does not
work.
I'm attaching a python file.
from tkinter import *
from tkinter import messagebox
window = Tk()
window.title("Hello World")
window.geometry('350x200')
def clicked(msg):
messagebox.showinfo("Message",msg)
text = Entry(window,width=100)
text.grid(column = 1, row = 0)
btn = Button(window,text = "Click me",command = clicked(text.get()))
btn.grid(column=5, row=1)
window.mainloop()

The following fix is required for your file:
When you assign the command parameter, it wont wait till your click on button, it will pop out the message box right after your tkinter application execution. (Thats what i experienced when i executed your code)
You have to use lambda here
So you can fix this by:
btn.bind('<Button-1>',lambda event: clicked('Your Text')) # Button-1 stands for left mouse click
More on bind() method:
https://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
This is the final code:
from tkinter import *
from tkinter import messagebox
window = Tk()
window.title("Hello World")
window.geometry('350x200')
def clicked(msg):
messagebox.showinfo("Message",msg)
text = Entry(window,width=100)
text.grid(column = 1, row = 0)
btn = Button(window,text = "Click me")
btn.bind('<Button-1>',lambda event: clicked(text.get()))
btn.grid(column=5, row=1)
window.mainloop()

The command will be executed when the code is interpreted, to avoid that you can use lambda to pass an argument to the function
command = lambda : clicked(text.get()))
Or you can use partial which will return a callable object that behaves like a function when it is called.
from functools import partial
...
command = partial(clicked, text.get()))

Related

Tkinter checkbox executing command only once [duplicate]

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 1 year ago.
x = tk.IntVar()
def test():
print(x.get())
checkBox = tk.Checkbutton(text="test",command=test(),variable=x)
checkBox.grid(row=12,column=2)
b=tk.Button(text="test",command=test)
b.grid(row=12,column=0
this is some code I put in my program for testing, when I check the checkbox the value does change (I can confirm it with the button I made to test) but the command does not get executed.
Remove () in command
command= test
This works fine:
import tkinter as tk
win = tk.Tk()
x = tk.IntVar()
def test():
print(x.get())
checkBox = tk.Checkbutton(text="test", command=test, variable=x)
checkBox.grid(row=12, column=2)
win.mainloop()

button won't repeat commands tkinter [duplicate]

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 6 years ago.
I'm new to GUIs and just learning how to use Tkinter. I wrote a python program to put the students in my class into pairs for my seating charts. The program itself runs fine; the problem is the tkinter gui.
I've tried to make the button generate and display a new set of pairs each time. Instead, the GUI will display the first set of pairs as soon as I open it, without even pressing the button. The button does nothing. If I run it in console, I don't get any error messages or anything printed to console.
At Button commands in Tkinter I saw an answer to do with using lambda. When I tried it, the label will initially be blank. It will display the pairs when the button is pressed the first time, as expected, but on subsequent presses it just makes the label blank again.
I'm not sure what the problem is. Can you help me? Here is the code:
from Tkinter import *
from SeatingChart import *
root = Tk()
class App:
def __init__(self, master):
self.win = Frame(master)
self.win.pack()
self.d = Label(self.win, text = "", width=140)
self.d.pack()
self.b = Button(self.win, text="Pair Up!", command=self.display_pairs(roster))
self.b.pack()
def display_pairs(self, l):
self.d.config(text=pair(roster))
app = App(root)
mainloop()
When creating the button, the command that you supply is the result of the display_pairs method (which is None because it doesn't return anything) rather than a reference to the method.
Try:
class App:
def __init__(self, master):
self.win = Frame(master)
self.win.pack()
self.d = Label(self.win, text = "", width=140)
# Maybe display an initial roster?
# self.d = Label(self.win, text = pair(roster), width=140)
self.d.pack()
self.b = Button(self.win, text="Pair Up!", command=self.display_pairs)
self.b.pack()
def display_pairs(self):
self.d.config(text=pair(roster))

How to close a Tkinter window by pressing a Button?

Write a GUI application with a button labeled "Good-bye". When the
Button is clicked, the window closes.
This is my code so far, but it is not working. Can anyone help me out with my code?
from Tkinter import *
window = Tk()
def close_window (root):
root.destroy()
frame = Frame(window)
frame.pack()
button = Button (frame, text = "Good-bye.", command = close_window)
button.pack()
window.mainloop()
With minimal editing to your code (Not sure if they've taught classes or not in your course), change:
def close_window(root):
root.destroy()
to
def close_window():
window.destroy()
and it should work.
Explanation:
Your version of close_window is defined to expect a single argument, namely root. Subsequently, any calls to your version of close_window need to have that argument, or Python will give you a run-time error.
When you created a Button, you told the button to run close_window when it is clicked. However, the source code for Button widget is something like:
# class constructor
def __init__(self, some_args, command, more_args):
#...
self.command = command
#...
# this method is called when the user clicks the button
def clicked(self):
#...
self.command() # Button calls your function with no arguments.
#...
As my code states, the Button class will call your function with no arguments. However your function is expecting an argument. Thus you had an error. So, if we take out that argument, so that the function call will execute inside the Button class, we're left with:
def close_window():
root.destroy()
That's not right, though, either, because root is never assigned a value. It would be like typing in print(x) when you haven't defined x, yet.
Looking at your code, I figured you wanted to call destroy on window, so I changed root to window.
You could create a class that extends the Tkinter Button class, that will be specialised to close your window by associating the destroy method to its command attribute:
from tkinter import *
class quitButton(Button):
def __init__(self, parent):
Button.__init__(self, parent)
self['text'] = 'Good Bye'
# Command to close the window (the destory method)
self['command'] = parent.destroy
self.pack(side=BOTTOM)
root = Tk()
quitButton(root)
mainloop()
This is the output:
And the reason why your code did not work before:
def close_window ():
# root.destroy()
window.destroy()
I have a slight feeling you might got the root from some other place, since you did window = tk().
When you call the destroy on the window in the Tkinter means destroying the whole application, as your window (root window) is the main window for the application. IMHO, I think you should change your window to root.
from tkinter import *
def close_window():
root.destroy() # destroying the main window
root = Tk()
frame = Frame(root)
frame.pack()
button = Button(frame)
button['text'] ="Good-bye."
button['command'] = close_window
button.pack()
mainloop()
You can associate directly the function object window.destroy to the command attribute of your button:
button = Button (frame, text="Good-bye.", command=window.destroy)
This way you will not need the function close_window to close the window for you.
from tkinter import *
window = tk()
window.geometry("300x300")
def close_window ():
window.destroy()
button = Button ( text = "Good-bye", command = close_window)
button.pack()
window.mainloop()
You can use lambda to pass a reference to the window object as argument to close_window function:
button = Button (frame, text="Good-bye.", command = lambda: close_window(window))
This works because the command attribute is expecting a callable, or callable like object.
A lambda is a callable, but in this case it is essentially the result of calling a given function with set parameters.
In essence, you're calling the lambda wrapper of the function which has no args, not the function itself.
from tkinter import *
def close_window():
import sys
sys.exit()
root = Tk()
frame = Frame (root)
frame.pack()
button = Button (frame, text="Good-bye", command=close_window)
button.pack()
mainloop()

Python 2.7 Tkinter open webbrowser on click

from Tkinter import *
import webbrowser
root = Tk()
frame = Frame(root)
frame.pack()
url = 'http://www.sampleurl.com'
def OpenUrl(url):
webbrowser.open_new(url)
button = Button(frame, text="CLICK", command=OpenUrl(url))
button.pack()
root.mainloop()
My goal is to open a URL when I click the button in the GUI widget. However, I am not sure how to do this.
Python opens two new windows when I run the script without clicking
anything. Additionally, nothing happens when I click the button.
You should use
button = Button(root, text="CLCK", command=lambda aurl=url:OpenUrl(aurl))
this is the correct way of sending a callback when arguments are required.
From here:
A common beginner’s mistake is to call the callback function when
constructing the widget. That is, instead of giving just the
function’s name (e.g. “callback”), the programmer adds parentheses and
argument values to the function:
If you do this, Python will call the callback function before creating
the widget, and pass the function’s return value to Tkinter. Tkinter
then attempts to convert the return value to a string, and tells Tk to
call a function with that name when the button is activated. This is
probably not what you wanted.
For simple cases like this, you can use a lambda expression as a link
between Tkinter and the callback function:
Alternatively, you don't have to pass the URL as an argument of the command. Obviously your OpenUrl method would be stuck opening that one URL in this case, but it would work.
from Tkinter import *
import webbrowser
url = 'http://www.sampleurl.com'
root = Tk()
frame = Frame(root)
frame.pack()
def OpenUrl():
webbrowser.open_new(url)
button = Button(frame, text="CLICK", command=OpenUrl)
button.pack()
root.mainloop()

Tkinter button command activates upon running program? [duplicate]

This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 6 months ago.
I'm trying to make a build retrieval form, and seem to have issues with the buttons... I'm a novice at Python/tkinter GUI programming (and GUI programming in general) and borrowed the skeleton of a Hello World app, and sorta built off that.
In the code below, I've set the "command" option of my Browse button to call my class's internal get_dir() function when it's clicked. However, as soon as I attempt to run the app, the get_dir() function is called and I'm prompted to choose a directory. Any ideas why this happens, and what I can do to make it behave properly?
from Tkinter import *
import tkFont
from tkFileDialog import askdirectory
class App:
def __init__(self, master):
fontHead = tkFont.Font(family="Arial", size=10, weight=tkFont.BOLD)
fontBold = tkFont.Font(family="Arial", size=8, weight=tkFont.BOLD)
fontReg = tkFont.Font(family="Arial", size=8)
frameN = Frame(master)
frameN.grid(row=0,padx=5,pady=5)
frameXBH = Frame(frameN)
frameXBH.grid(row=0,columnspan=5,padx=5)
Canvas(frameXBH,borderwidth=0,relief="flat",height=1,width=20,background="#cccccc").grid(row=0)
Label(frameXBH, text="Xbox 360",font=fontBold,width=9).grid(row=0,column=1)
Canvas(frameXBH,borderwidth=0,relief="flat",height=1,width=440,background="#cccccc").grid(row=0,column=2,sticky="WE")
Label(frameN, text="Destination Path:",font=fontReg).grid(row=1,sticky="W")
xbPath = Entry(frameN,width=30,font=fontReg)
xbPath.grid(row=1,column=1,sticky="W")
xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath))
xbBrowse.grid(row=1,column=2,sticky="W")
xbRel = Checkbutton(frameN,text="Release",font=fontReg)
xbRel.grid(row=1,column=3,sticky="W")
xbShip = Checkbutton(frameN,text="Ship",font=fontReg)
xbShip.grid(row=1,column=4,sticky="W")
Canvas(frameN,borderwidth=1,relief="groove",width=550,height=0).grid(row=2,columnspan=5,pady=10)
# SAVE AND CANCEL
btnSave = Button(frameN,text="Save",width=10)
btnSave.grid(row=3,column=3,sticky="E")
btnCancel = Button(frameN,text="Cancel",width=10)
btnCancel.grid(row=3,column=4,sticky="W")
def get_dir(self,box):
tmp = askdirectory(mustexist=1,title="Please select a destination")
tmp = tmp.replace("/","\\")
box.delete(0,END)
box.insert(0,tmp)
root = Tk()
root.resizable(0,0)
app = App(root)
root.mainloop()
Make your event handler a lambda function, which calls your get_dir() with whatever arguments you want:
xbBrowse = Button(frameN, text="Browse...", font=fontReg, command=lambda : self.get_dir(xbPath))
In the above code:
xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath))
You are invoking the function already, you should be simply passing the function:
xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir)
You need to pass a reference of your get_dir method
so change
xbBrowse = Button(frameN,text="Browse...",font=fontReg,command=self.get_dir(xbPath))
to
xbBrowse = Button(frameN,text="Browse...",font=fontReg, command=self.get_dir)
Then make your Entry widget an instance variable so that you can access it in your get_dir method.
e.g.
self.xbPath = Entry(frameN,width=30,font=fontReg)
Then your get_dir() method will look like:
def get_dir(self):
tmp = askdirectory(mustexist=1,title="Please select a destination")
tmp = tmp.replace("/","\\")
self.xbPath.delete(0,END)
self.xbPath.insert(0,tmp)

Categories

Resources