I would like to know how to display text or a number to an empty label, after a button is clicked. Let's pretend, I want to display the number "0" to an empty label after a button is clicked.
My questions in simplified form are:
How to set a numeric value of 0 to a button.
Once the numeric integer value of (0) is set, how do you display the result to an empty label after the button widget is clicked?
You need to bind a callback helper method which would be triggered when the button is clicked. Here's an MCVE:
import tkinter as tk
root = tk.Tk()
label = tk.Label(root)
label.pack()
button = tk.Button(
root,
text='Click Me!',
command=lambda: label.configure(text='beautiful spam')
)
button.pack()
root.mainloop()
...you'd do the same for 0 - the text doesn't matter, nor does it matter whether you're configuring an empty label, or a label which already has some text.
Related
I am new to tkinter application. The below code is working fine. Please help how to implement mentioned features.
The dynamic value should be displayed above clear button or below the combo box ( Used pack is bottom )- Now working
Clear the label value on combo box selection.
import tkinter as tk
from tkinter import ttk
from tkinter import *
from datetime import datetime
# root window
root = tk.Tk()
root.geometry("500x350")
root.resizable(False, False)
root.title('Test')
# Log Generator in frame
Generator = tk.Frame(root)
Generator.pack(padx=10, pady=10, fill='x', expand=True)
def clear():
combo.set('')
# Function to print the index of selected option
# in Combobox
def get_log_file_name(*arg):
date_Value = datetime.now().strftime("%Y_%m_%d_%I%M%S")
output_file_name_value = "Log_"+date_Value
if var.get() == "apple":
Label(Generator, text="The value at index: "+output_file_name_value+".txt", font=('Helvetica 12')).pack()
else:
Label(Generator, text="The value at index: "+output_file_name_value+".html", font=('Helvetica 12')).pack()
# Define Tuple of months
months = ('apple','banana')
# Create a Combobox widget
label = ttk.Label(Generator, text="Selection_Option:",font=('Helvetica', 10, 'bold'))
label.pack(fill='x', expand=True)
var = StringVar()
combo = ttk.Combobox(Generator, textvariable=var)
combo['values'] = months
combo['state'] = 'readonly'
combo.pack(padx=5, pady=5)
# Set the tracing for the given variable
var.trace('w', get_log_file_name)
# Create a button to clear the selected combobox
# text value
button = Button(Generator, text="Clear", command=clear)
button.pack(side=left)
# Make infinite loop for displaying app on
# the screen
Generator.mainloop()
Clear the label value on combo box selection.
You need to capture the ComboboxSelect event to do that and the function to execute if captured
the function should be like this
What you want to do here, is to capture the combobox event, and then, do the label configuration when capturing it,
Below is the code to do the thing. and you can add code there.
def comboboxEventCapture(e=None):
label.configure(text='')
# Your code after resetting variables!
Here's the event capturing part
combo.bind("<<ComboboxSelect>>", comboboxEventCapture)
You can name the function whatever you want though.
Note that the arguement e is needed because if the event is captured, the event itself is passed as a parameter into the function, that is of no use here (unless you are going to do something with it, then use e.objname)
The dynamic value should be displayed above clear button
The second label could be outside of get_log_file_name() function.
And also configure inside function. So you don't do duplicate Label widget, naming Label2
Also the pack() must be split to prevent an error.
To clear Label2 use .configure(text='')
We will be using ttk. So don't do this from tkinter import *
Code:
import tkinter as tk
from tkinter import ttk
from datetime import datetime
root = tk.Tk()
root.geometry("500x350")
root.resizable(False, False)
root.title('Test')
Generator = tk.Frame(root)
Generator.pack(padx=10, pady=10, fill='x', expand=True)
def clear():
label2.configure(text='')
def get_log_file_name(*arg):
date_Value = datetime.now().strftime("%Y_%m_%d_%I%M%S")
output_file_name_value = "Log_"+date_Value
if var.get() == "apple":
label2.configure(text="The value at index: "+output_file_name_value+".txt", font=('Helvetica 12'))
else:
label2.configure(text="The value at index: "+output_file_name_value+".html", font=('Helvetica 12'))
# Define Tuple of months
months = ('apple','banana')
# Create a Combobox widget
label2 = ttk.Label(Generator)
label2.pack()
label = ttk.Label(Generator, text="Selection_Option:",font=('Helvetica', 10, 'bold'))
label.pack(fill='x', expand=True)
var = tk.StringVar()
combo = ttk.Combobox(Generator, textvariable=var)
combo['values'] = months
combo['state'] = 'readonly'
combo.pack(padx=5, pady=5)
# Set the tracing for the given variable
var.trace('w', get_log_file_name)
# Create a button to clear the selected combobox
# text value
button = ttk.Button(Generator, text="Clear", command=clear)
button.pack(side='left')
# Make infinite loop for displaying app on
# the screen
Generator.mainloop()
Screenshot for apple:
Screenshot for banana:
Screenshot to clear Label2:
I am placing labels on a Tab in Tkinter with a for loop. How can I identify in the event handler which label was clicked (or its loop index)? I guess it is functionally similar to a ListBox but without the formatting restrictions. I might want to put the labels in a circle or place them diagonally. I tried finding the coordinates of the label but these are available only if the tab is the first one visible or the tab is redrawn when made active. Also the x, y passed in the event handler is the x, y within the label which does not help to identify the label.
I could copy the label code about 10 times and and have about 10 event handlers. This would work but this is no longer 1970!
Perhaps I could bind a handler to the tab canvas and identify the label from its coordinates. The label would need to be on the first tab or the tab drawn when active.
Perhaps I could create a different event handler for each label by holding the event handlers in an array. I would need an event handler for each label. The code would need to change if the number of labels changed.
I am currently trying a label with ''. Would using buttons with command be easier?
What simple part of Python am I missing? I cannot be the first person to need this! Any help or advice would be appreciated.
You can save a reference to the label text for each label widget in a dict.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry('+800+50')
notebook = ttk.Notebook(root, width=300, height=200, padding=[10,10,10,10])
notebook.pack()
tab_one = tk.Frame(notebook, bg='wheat')
notebook.add(tab_one, text='Cheese', padding=[10,10,10,10])
tab_two = tk.Frame(notebook, bg='mint cream')
notebook.add(tab_two, text='Misc.', padding=[10,10,10,10])
def clicked(event):
print('Clicked:', name_dict[event.widget])
# Populating Cheese tab with clickable Labels
name_list = ['Cheddar', 'Ilchester', 'Limburger']
name_dict = {}
for index, name in enumerate(name_list):
a = tk.Label(tab_one, width=10, text=name, bg='peru')
a.grid(row=index, column=0, padx=5, pady=5)
name_dict[a] = name # Save references in a dict
a.bind('<Button-1>', clicked)
tk.Label(tab_two, text='Just some text...', bg='powder blue').pack(anchor='nw')
root.mainloop()
Is this what you had in mind?
When you bind events, the function receives an object that includes a reference to the widget that received the event. In the following example, notice how it uses event.widget to refer to the widget that was clicked on.
import tkinter as tk
def update_label(event):
event.widget.configure(text="You clicked me")
root = tk.Tk()
for i in range(10):
l = tk.Label(root, text="Click me", width=20)
l.pack()
l.bind("<1>", update_label)
root.mainloop()
My problem: I can't display the value to Text widget when I select a row.
how can I display a value inside the Text widget from the selected row?
I tried using textvariable attribute in Text widget but its not working.
Use insert method of the Text widget. Minimal example:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
def add_text():
# text.delete(1.0, tk.END) # Uncomment if you need to replace text instead of adding
text.insert(tk.END, f"Some text\n")
tk.Button(root, text="Add text", command=add_text).pack()
root.mainloop()
I used window_create to create interactive buttons inside a Text element. The buttons represent random or static values and I want to be able to compile the contents of the text element and replace the buttons with their respective values. However, I cannot find where any of the buttons are.
I've tried self.text.get("1.0",tk.END), but it only returns the text, not including the button elements
the button elements are created like so:
btn_text = tk.StringVar()
value = StaticValue('static', btn_text, self.custom_val_veiwer, idx)
button = tk.Button(self.text,
textvariable=btn_text, command=lambda v=value:
self.veiw_custom_val(None, val=v))
btn_text.set('static')
self.custom_vals.append(value)
self.text.window_create(tk.INSERT, window=button)
edit:
if you want to recreate the problem use this:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
text.insert(tk.END, 'before button')
button = tk.Button(text, text='button')
text.window_create(tk.END, window=button)
text.insert(tk.END, 'after button')
print(text.get("1.0",tk.END))
root.mainloop()
notice how the button appears in the text field, but it is not printed out
(the output is before buttonafter button I want someting like before button<button>after button or a function that would tell me there is a button at row x at index y)
There's nothing that gives you exactly what you want, but it just takes a couple lines of code to get the index of the clicked button.
What I would do is have the button pass a reference to itself as an argument to the command. That requires making the button in two steps, since you can't reference the button before it is created.
button = tk.Button(text, text="button")
button.configure(command=lambda button=button: handle_click(button))
In the function called by the button, you can use the text widget dump command to get a list of all windows, and from that you can find the index of the button. The dump command will return a list of tuples. Each tuple has a key (in this case, "window"), the window name, and the index of the window. You can iterate over the result of that command to find the index of the button which was passed to the function.
def handle_click(button):
for (key, name, index) in text.dump("1.0", "end", window=True):
if name == str(button):
print("you clicked on the button at index {}".format(index))
break
Example
Here is a contrived example that adds several buttons. Clicking on the button will display the index of that button in a label. Notice how it will continue to work even if you manually edit the text widget to change the index of the button.
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
label = tk.Label(root)
label.pack(side="top", fill="x")
text.pack(side="top", fill="both", expand=True)
def handle_click(button):
for (key, name, index) in text.dump("1.0", "end", window=True):
if name == str(button):
label.configure(text="You clicked on the button at {}".format(index))
break
for word in ("one", "two", "three", "four", "five"):
text.insert("end", word + "\n")
button = tk.Button(text, text="click me")
button.configure(command=lambda button=button: handle_click(button))
text.window_create("insert-1c", window=button)
tk.mainloop()
I'm just wondering how I can deselect from a list box in thinter. Whenever I click on something in a list box, it gets highlighted and it gets underlined, but when I click off of the screen towards the side, the list box selection stays highlighted. Even when I click a button, the selection still stays underlined. For ex: in the example code below, I can't click off of the list box selection after clicking on one of them.
from tkinter import *
def Add():
listbox.insert(END, textVar.get())
root = Tk()
textVar = StringVar()
entry = Entry(root, textvariable = textVar)
add = Button(root, text="add", command = Add)
frame = Frame(root, height=100, width=100, bg="blue")
listbox = Listbox(root, height=5)
add.grid(row=0, column=0, sticky=W)
entry.grid(row=0, column=1, sticky=E)
listbox.grid(row=1, column=0)
frame.grid(row=1, column=1)
root.mainloop()
Yes, that's the normal behavior of the listbox. If you want to change that you could call the clear function every time the listbox left focus:
listbox.bind('<FocusOut>', lambda e: listbox.selection_clear(0, END))
Use the selectmode parameter on the Listbox widget.
You can click the selected item again and it will clear the selection.
See the effbot link:
http://effbot.org/tkinterbook/listbox.htm
listbox = Listbox(root, height=5, selectmode=MULTIPLE)
I have managed to create the functionality needed within the Listbox widget so that when a user clicks either back on the same item in the Listbox or elsewhere on screen the currently selected item is deselected. The solution came out to be quite simple.
Firsly I created a binding so that when the left mouse button is pressed anywhere on the window a function to deselect the list box is executed.
root.bind('<ButtonPress-1>', deselect_item)
I then created a variable to store the value of the last listbox item to be selected and initialised its value to None
previous_selected = None
Then I defined the function to deselect the listbox as follows. Firsly the new item (what item the user has just clicked on) is selected and compared to the previously selected item. If this is true then the user has clicked on an already highlighted item in the listbox and so the listbox's selection is cleared, removing the selected item. Finally, the function updates the previously selected box to the current selected box.
def deselect_item(event):
if listbox.curselection() == previous_selected:
listbox.selection_clear(0, tkinter.END)
previous_selected = listbox.curselection()
A full working example of this (in python 3.8.0) is shown below:
import tkinter
class App(tkinter.Tk):
def __init__(self):
tkinter.Tk.__init__(self)
self.previous_selected = None
self.listbox = tkinter.Listbox(self)
self.bind('<ButtonPress-1>', self.deselect_item)
self.listbox.insert(tkinter.END, 'Apple')
self.listbox.insert(tkinter.END, 'Orange')
self.listbox.insert(tkinter.END, 'Pear')
self.listbox.pack()
def deselect_item(self, event):
if self.listbox.curselection() == self.previous_selected:
self.listbox.selection_clear(0, tkinter.END)
self.previous_selected = self.listbox.curselection()
app = App()
app.mainloop()