how to update tkinter lables - python-3.x

Im trying to display user inputs in a lable on a tkinter tab using a function that makes a lable, but instead of it updating ever time I run it, it prints a new lable. How do I stop this? My code looks like this:
import time
from tkinter import *
import tkinter as tk
calNums = []
root = Tk()
def key(event):
if event.keysym == '1':
calNums.append(1)
time.sleep(0.05)
displayScreenProgress()
root.bind_all('<Key>', key)
def displayScreenProgress():
cal_display = StringVar()
label = Label(root, textvariable=cal_display, relief=RAISED)
cal_display.set(calNums)
label.pack()
root.mainloop()
I have nine more of these for the other nine numbers:
if event.keysym == '1':
calNums.append(1)
time.sleep(0.05)

Try following:
import time
from tkinter import *
root = Tk()
calNums = []
cal_display = StringVar()
mylabel = Label(root, textvariable=cal_display, relief=RAISED)
mylabel.pack()
def displayScreenProgress():
print(calNums)
cal_display.set(calNums)
def key(event):
if event.keysym == '1':
calNums.append(1)
time.sleep(0.05)
displayScreenProgress()
root.bind_all('<Key>', key)
root.mainloop()
You should create label only once and use that in the function.
What you were doing was creating a new label every time the function was called.

Related

Tkinter how update main window combobox values from Toplevel list python3.8

I have 3 modules (small, dont worry).
main_module = it has a combobox and a button. Comobobox list must be update each time a list (in module2) increases in number of names (combo values). Button calls the second window (module2)-->
myapp_second_window.py which has a entry box and another button. We write a name in the entry, push the button...voila..the list increases. In the origina app the list is created automatically when (2) is called.
Now I pass the list to a Pages.variable that is in -->
my_pages_to_connect_modules.
So, when app start I can populate combobox calling (2) to generate a Pages.variable list or populate combobox with json previously written.
The problem? --> how populate combobox while app is running. I mean, we go to (2) create a new name in entry come back to (1) and it is already there.
main_module
import tkinter as tk
from tkinter import*
from tkinter import ttk
import myapp_second_window
from myapp_second_window import SecondClass
root= Tk()
root.geometry("500x500")
root.title('myAPP_Main_Window')
class MainClass:
def __init__(self, parent,myapp_second_window):
self.parent = parent
self.my_widgets1()
def call_second_page (self):
Window2 = tk.Toplevel(root)
Window2.geometry('400x300')
myapp_second_window.SecondClass(Window2)
def my_widgets1(self):
self.field1_value = StringVar()
self.field1 = ttk.Combobox(self.parent, textvariable=self.field1_value)
self.field1['values'] = [1,2] # Pages.variable comes Here
self.field1.grid( row=0, column=0)
self.myButton = tk.Button(self.parent, text = "Call Second module", command = self.call_second_page)
self.myButton.grid(row=2, column=0)
if __name__ == '__main__':
app = MainClass(root, myapp_second_window)
root.mainloop()
myapp_second_window.py
import tkinter as tk
from tkinter import*
from tkinter import ttk
root= Tk()
root.minsize(550,450)
root.maxsize(560,460)
root.title('myAPP_Second_Window')
class SecondClass:
def init(self, parent):
self.parent = parent
self.my_widgets()
self.names = []
def my_widgets(self):
mylabel = Label(self.parent, text='Insert new name in next widget:')
mylabel.grid(column=0, row=0, sticky=W, pady=3)
button1 = tk.Button(self.parent, text="Click to enter Names in list", command=self.addToList)
button1.grid(column=3, row=0, sticky=W, pady=3)
self.name = StringVar()
valueEntry = tk.Entry(self.parent, textvariable= self.name)
valueEntry.grid(row=1, column=0, sticky=W, pady=3)
def addToList(self):
self.names.append(self.name.get())
print('listentries', self.names)
Pages.list_of_names = self.names
my_pages_to_connect_modules.
class Pages():
list_of_names = " "
It`s been challenging to me, every help is welcome. But please dont say just that I must update main window, I need to know how. Thanks to all of you.

How to close current tkinter window and open a new tkinter window when the user inputs test into a tkinter Entry widget

I would like to close the current tkinter window, and open a new tkinter window when the user inputs text into an entry widget. That might sound confusing so let me explain.
First tkinter window:
When the user inputs text into the Entry widget, I would like this current window to close and the second window to open with the text the user entered displayed in a label widget.
Second window:
Here is my current code:
from tkinter import *
user_input = ''
class Startup_window:
def __init__(self, master):
self.master = master
master.title('Window 1')
def get_input(event):
global user_input
# Gets the user input from the Entry widget
user_input = self.input.get()
# Clears Entry widget
self.input.delete(0, END)
master.destroy()
self.label = Label(master, text='Input:')
self.label.grid(row=0, column=0)
self.input = Entry(master)
self.input.grid(row=0, column=1)
self.input.focus()
self.input.bind("<Return>", get_input)
class Main_window:
def __init__(self, master):
self.master = master
master.title('Window 2')
self.label = Label(master, text="You've entered (user_input)" + user_input)
self.label.pack()
root = Tk()
startup_window = Startup_window(root)
if user_input != '':
main_window = Main_window(root)
mainloop()
I am new to tkinter and object oriented programming so any help would be greatly appreciated!
This would work for you. As #CoolCloud mentioned, the if condition will be checked only once. Because mainloop() actually waits for events to be triggered (maybe through some buttons or whatever), NOT that it executes the blocks of code over and over again
import tkinter as tk
class MainApp():
def __init__(self, root):
self.root = root
self.inputBox = tk.Entry(self.root)
self.inputBox.pack()
self.inputBox.bind('<Return>', self.checkInput)
def checkInput(self, args):
if self.inputBox.get() != '':
userVal = self.inputBox.get()
self.root.destroy() # try root.quit if it doesn't work
newWindow = tk.Tk()
myLabel = tk.Label(newWindow, text='You entered: ' + userVal)
myLabel.pack()
win = tk.Tk()
MainApp(win)
win.mainloop()

How to get input from tkinter Entry widget on second window while the first window continues to run

from tkinter import *
def first():
root1 = Tk()
Button(root1, text = 'get Second', command= second).pack()
root1.mainloop()
def second():
root2 = Tk()
user_input = StringVar()
Entry(root2, text = user_input).pack()
Button(root2, text = 'submit', command = lambda : print(user_input.get(), '\t printed')).pack()
root2.mainloop()
first()
You are making a few basic mistakes in here -
You if want to use a second window, it should be Toplevel not root Tk window. There should be only one root window in the program. This should act as parent to all the windows.
Its a good practice in most of the cases to define the widgets like Button, Entry separately and then pack() them.
Entry should have 'textvariable' not 'text'
Following is the updated code which may help you -
from tkinter import *
root = Tk()
def first():
button = Button(root, text = 'get Second', command= second)
button.pack()
root.mainloop()
def second():
window2 = Toplevel(root)
user_input = StringVar()
entry = Entry(window2, textvariable=user_input)
entry.pack()
button = Button(window2, text = 'submit', command = lambda: print(user_input.get()))
button.pack()
first()

How to share data between two threads [duplicate]

This question already has answers here:
Call a function defined in another function
(4 answers)
Closed 3 years ago.
I am creating an application using Tkinter. I have two Threads, the first is an algorithm that looks for results and the second is my Tkinter window that displays the number of results found.
import time
from tkinter import *
from threading import Thread
global results
results = []
class thread(Thread):
def __init__(self, name):
Thread.__init__(self)
self.name = name
def run(self):
global results
if self.name == "algo":
algo()
elif self.name == "window":
window = Tk()
tmp = StringVar()
tmp.set(str(len(results)))
text = Label(window, textvariable=tmp, font=(None, 12))
text.place(x=10, y=15)
window.mainloop()
def algo():
global results
while True:
time.sleep(1)
results += [1]
print(len(results))
thread_1 = thread("algo")
thread_2 = thread("window")
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
The problem is that the textvariable does not update.
You can run the tkinter mainloop in the mainthread, and your function in a specially spawned new Thread. It does not appear necessary to have more:
import time
import tkinter as tk
from threading import Thread
def algo():
while True:
time.sleep(1)
result.set(result.get() + 1)
print(result.get())
root = tk.Tk()
result = tk.IntVar(value=0)
label = tk.Label(root, textvariable=result)
label.pack()
thread_1 = Thread(target=algo)
thread_1.start()
root.mainloop()

How can I put this script in a function?

I want to display a text first and remove it after a second, and keep the software running during this time (that is, preventing the loop) and getting the text and display it repeatedly.
I want this to be in the form of a function
I want to display the text with each key and the text operation is in a function
import keyboard
import pynput
import tkinter, win32api, win32con, pywintypes
def printer(text):
label = tkinter.Label(text=text, font=('Times New Roman','16'), fg='white', bg='blue')
label.master.overrideredirect(True)
label.master.geometry("+0+0")
label.master.lift()
label.master.wm_attributes("-topmost", True)
label.master.wm_attributes("-disabled", True)
label.master.wm_attributes("-transparentcolor", "blue")
hWindow = pywintypes.HANDLE(int(label.master.frame(), 16))
exStyle = win32con.WS_EX_COMPOSITED | win32con.WS_EX_LAYERED | win32con.WS_EX_NOACTIVATE | win32con.WS_EX_TOPMOST | win32con.WS_EX_TRANSPARENT
win32api.SetWindowLong(hWindow, win32con.GWL_EXSTYLE, exStyle)
label.pack()
label.after(1000, lambda:label.config(text=''))
label.mainloop()
pressedList = ''
def on_press(key):
global pressedList
try:
pressedKey = key.char # single-char keys
except:
pressedKey = key.name # other keys
pressedList += pressedKey
if pressedList.rfind('a')+len('a') == len(pressedList) and pressedList[pressedList.rfind('a'):] == 'a':
printer('a')
elif pressedList.rfind('f1')+len('f1') == len(pressedList) and pressedList[pressedList.rfind('f1'):] == 'f1' and pressedKey == 'f1':
printer('f1')
else:
printer('pass')
pass
lis = pynput.keyboard.Listener(on_press=on_press)
lis.start()
lis.join()
You probably do not need to mix tkinter with other events listeners; binding a keypress to a tkinter window will do what you require:
import tkinter as tk
def display_key(e=None):
if e is not None:
tv.set(e.keysym)
root.after(1000, display_key)
else:
tv.set('-')
root = tk.Tk()
root.geometry('300x200')
tv = tk.StringVar()
tv.set('-')
label = tk.Label(root, textvariable=tv)
label.config(font=("Courier", 144))
label.pack(expand=True, fill='both')
root.bind('<Key>', display_key)
root.mainloop()

Resources