I am trying to make a tkinter script that won't cycle to the next text until a button is pressed
import tkinter as tk
from tkinter import *
window = tk.Tk()
window.geometry("300x300")
TabNum = ["1","2","3"]
TabNumInt = 0
Text = tk.Label(text = ("Page number" + TabNum[TabNumInt]))
Text.pack()
def continuefunct():
global Running
TabNumInt =+ 1
Continuebtn = Button(window, text = 'Continue', bd = '5', command = continuefunct()).pack()
tk.mainloop()
I want this to "print page number [1]" and for the number to increase everytime you press the button until you get to 3. (I know I could have while while TabNumInt =< len(TabNum) but this is just a proof of concept).
Any help would be appreciated :)
There are few issues in your code:
command = continuefunct() will execute the function immediately without clicking the button. Also nothing will be performed when the button is clicked later.
need to declare TabNumInt as global variable inside the function
TabNumInt =+ 1 should be TabNumInt += 1 instead
need to update text of the label inside the function
Below is the modified code:
import tkinter as tk
window = tk.Tk()
window.geometry("300x300")
TabNum = ["1", "2", "3"]
TabNumInt = 0
Text = tk.Label(window, text="Page number "+TabNum[TabNumInt])
Text.pack()
def continuefunct():
global TabNumInt
if TabNumInt < len(TabNum)-1:
TabNumInt += 1
Text.config(text="Page number "+TabNum[TabNumInt])
tk.Button(window, text='Continue', bd='5', command=continuefunct).pack()
window.mainloop()
Related
So I'm working on a function does something (turns a motor) every second. For counting the second I use time.sleep(1) because I don't know any other way to wait.
def wash_loop(wash_time):
count = 0
dist = 0
global error_flag
error_flag = 0
while (count < wash_time):
if(count%2==0):#going forward
GPIO.output(Motor_IN1,GPIO.HIGH)
GPIO.output(Motor_IN2,GPIO.LOW)
GPIO.output(Motor_EN,GPIO.HIGH)
print(count)
time.sleep(MOTOR_SLEEP)
else:#going backwards
GPIO.output(Motor_IN1,GPIO.LOW)
GPIO.output(Motor_IN2,GPIO.HIGH)
GPIO.output(Motor_EN,GPIO.HIGH)
print(wash_time - count) #want to display this on a Tkinter window instead
time.sleep(MOTOR_SLEEP)
count+=1
dist = distance_check()
if(dist < CRITICAL_DIS):
error_alert()
break
if(count>=wash_time):
GPIO.output(Motor_EN, GPIO.LOW)
break
The Tkinter function that I'm trying to do this in looks like this:
def wash_window():
#create the main window for GUI control applcation
window2 = TK.Tk()
temp = TK.IntVar()
window2.geometry(WINDOW_GEOMETRY)
window2.title("Wash Cycle ")
#create the frame that will hold instructions
frame0 = TK.Frame(window2)
frame0.pack(side=TK.TOP)
TK.Label(frame0, text="You've selected custom wash cycle").grid(row=0,column=0)
TK.Label(frame0, text="Please select the water temperature for the wash.")\
.grid(row=1,column=0)
frame1 = TK.Frame(window2)
frame1.pack(side=TK.TOP)
temp.get()
hot_button = TK.Radiobutton(frame1, text="HOT", variable=temp, value=1 ).grid(row=0, column=0)
cold_button = TK.Radiobutton(frame1, text="COLD", variable=temp, value=2).grid(row=0,column=1)
warm_button = TK.Radiobutton(frame1, text="WARM", variable=temp, value=3).grid(row=0,column=2)
#create the frame that will hold control entry in the window
frame2 = TK.Frame(window2)
frame2.pack(side=TK.TOP)
TK.Label(frame2, text = "Please enter the time below for the wash cycle").grid(row=0,column=0)
user_entry = TK.Entry(frame2)
user_entry.grid(row=1,column=0)
frame3= TK.Frame(window2)
frame3.pack(side=TK.TOP)
start_button = TK.Button(frame3, text="START", command = lambda: wash_cycle(user_entry,temp)).grid(row=0, column=0)
# stop_button = TK.Button(frame3, text="STOP", command = lambda: wash_cycle(user_entry,temp)).grid(row=0, column=1)
quit_button = TK.Button(frame3, text="QUIT", command = window2.destroy).grid(row=0, column=2)
What I'm trying to do is display the countdown (from the entered time to 0) on this Tkinter window as soon as the person presses start in the window. This is different from using the after() function because I want to show a value from a function which is only executing once, only with the exception that it has a loop.
Thank You!
So what you could do is work with threading.
You Need to:
from threading Import Timer
Then you create a timer
your_timer = Timer(the_seconds_you_want_to_wait, the_function_to_call)
You are calling a function with this and in that function you can display anything in your tkinter window.
What I recommend you to do here is create a Label and then change the properties of it.
For example if you want to show a number on a label:
L1 = Label(root, text="your text here")
L1.pack()
Now if you want to edit that later:
L1.configure(text="your new text here")
your_timer.start()
And at the end of your function you Need to Start the timer in order to the create a cycle or just create a Loop for it.
I have two widgets to work with, a text input, and a button, both are created inside a function. What I want to happen is the user types in their name and then clicks the button to submit the answer. What I want the computer to do, is on the button press it will read whats inside the text and the save it to a variable. Once it saves it, it will print it out.
The code below is bad because it runs through the if statement immediately without the consulting of the button press.
There has to be a simpler solution. Also this may not be PEP 8 or whatever please be patient because I'm new.
import tkinter as tk
from tkinter import Tk, Label, Button
import sys
import time
import random
import threading
from tkinter import *
window = tk.Tk()
window.geometry("300x300")
window.title("GUI")
def start_screen():
reset()
start = tk.Label(window, text="start of game")
start.place(x=110,y=20)
play = Button(window, text= "play", command = start_game)
play.place(x=110,y=50)
helper = Button(window, text="help", command = help_screen)
helper.place(x=110,y=70)
def stuff():
global t
t = True
print(t)
return t
def text_handling():
global t
t = False
reset()#clears the screen
label = Label(window, text='')
question1= "what is your name?"
label.pack()
print_slow(label, question1, 40)#prints out letters slowly
#here is the part I'm having problems with
name = Entry(window)
name.pack()
but = Button(window, text="enter", command= stuff)
but.pack()
print(t)
if t == True:
myPlayer.name = name.get()
print(myPlayer.name)
def start_game():
reset()
bt = tk.Button(window,text="Enter", bg="orange", command =
text_handling)
bt.place(x=100,y=100)
start_screen()
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.
Basically, I want to go through answers and check every time if that's correct with a button and then pop it from the list. In another file/code/application it's working when I try to use it on my Gui Application it doesn't iterate and only keeps the first answer right.
I tried multiple things like using Dictionaries and getting the key but it still doesn't iterate over after the Button press.
This is the code that works fine:
while answers == True:
answers = ["Sayajin", "Namek", "Cell", "TournamentOfPower"]
for a in range(4):
s = input()
if s in answers[0]:
print("Richtig")
answers.pop(0)
This is the code that doesnt work:
def check(event):
answers = ["Sayajin", "Namek", "Cell", "TournamentOfPower"]
for a in range(4):
s = entrysaga.get()
if s in answers[0]:
print("Richtig")
answers.pop(0)
Complete Code:
from tkinter import *
import tkinter.messagebox
import time
import random
root = Tk()
#Hint Button
hint = Button(root, text= "Hint")
hint.bind("<Button-1>")
hint.place(x=50, y=20)
#How to Play Button + Info Message how to play
def Howtoplay():
tkinter.messagebox.showinfo("How to play", "To start the game u have
to press the button (Start)\n---------------------------------------------
----------------\n"
""
"Then the Picture will switch
and its going to show u a Character and u have to guess from which Dragon
Ball Saga he is.\n--------------------------------------------------------
-----\n"
"Just type it in the Entry and
press Check after that if u were right the next picture shows up")
info = Button(root, text="How to Play", command=Howtoplay)
info.bind("<Button-1>")
info.place(x=150, y=20)
#textwidget
textwidget = Label(root, text="Entry the DragonBall Saga:")
#entry widget
entrysaga = Entry(root)
#Pictures for guessing the Saga
Sayajin = PhotoImage(file="sayajinsaga.png")
Namek = PhotoImage(file="NamekSaga.png")
Cell = PhotoImage(file="CellSaga.png")
Buu = PhotoImage(file="BuuSaga.png")
TournamentOfPower = PhotoImage(file="TournamentOfPowersaga.png")
#Start function
def start():
labelSagas.config(image=Sayajin)
#define check for pictures
def check(event):
answers = ["Sayajin", "Namek", "Cell", "TournamentOfPower"]
for a in range(4):
s = entrysaga.get()
if s in answers[0]:
print("Richtig")
answers.pop(0)
#button check
buttonsaga = Button(root, text="Check")
buttonsaga.bind("<Button-1>", check)
textwidget.place(x=300, y=170)
entrysaga.place(x=300, y= 200)
buttonsaga.place(x=440, y=195)
#Start Button
start = Button(root, text="Start", command=start)
start.bind("<Button-1")
start.place(x=400, y=20)
# Label with start picture,
startpic = PhotoImage(file="dbzsagas.png")
labelSagas = Label(root, image=startpic)
labelSagas.place(x=25, y=80)
#size of window
root.geometry("500x280")
#window title
root.title("Dragon Ball Saga´s guessing game")
#start of the window
root.mainloop()
My excepted output should be like in the first code that it iterates over and after getting the first answer right ur on to the next one. But the actual result it that stays on the first.
I have moved the widgets which should appear when you press the Start button. They are all in the def start(): function as they would not appear otherwise.
As entrysaga was being called within a different function it could not find the inputted value as the variable is not a global variable. By using global entrysaga it means that it is and can be called from anywhere within the script.
This is how it looks:
from tkinter import *
import tkinter.messagebox
import time
import random
root = Tk()
#Hint Button
hint = Button(root, text= "Hint")
hint.bind("<Button-1>")
hint.place(x=50, y=20)
#How to Play Button + Info Message how to play
def Howtoplay():
tkinter.messagebox.showinfo("How to play", "To start the game u have to press the button (Start)\n--------------------------------------------- ----------------\n"
""
"Then the Picture will switch and its going to show u a Character and u have to guess from which Dragon Ball Saga he is.\n-------------------------------------------------------- -----\n"
"Just type it in the Entry and press Check after that if u were right the next picture shows up")
info = Button(root, text="How to Play", command=Howtoplay)
info.bind("<Button-1>")
info.place(x=150, y=20)
#Pictures for guessing the Saga
Sayajin = PhotoImage(file="sayajinsaga.png")
Namek = PhotoImage(file="NamekSaga.png")
Cell = PhotoImage(file="CellSaga.png")
Buu = PhotoImage(file="BuuSaga.png")
TournamentOfPower = PhotoImage(file="TournamentOfPowersaga.png")
#Start function
def start():
labelSagas.config(image=Sayajin)
global entrysaga
entrysaga = tkinter.Entry(root)
entrysaga.place(x=300, y= 200)
buttonsaga = Button(root, text="Check")
buttonsaga.bind("<Button-1>", check)
buttonsaga.place(x=440, y=195)
textwidget = Label(root, text="Entry the DragonBall Saga:")
textwidget.place(x=300, y=170)
#define check for pictures
def check(event):
answers = ["Sayajin", "Namek", "Cell", "TournamentOfPower"]
for a in range(4):
s = entrysaga.get()
if s in answers[0]:
print("Richtig")
answers.pop(0)
#Start Button
start = Button(root, text="Start", command=start)
start.bind("<Button-1")
start.place(x=400, y=20)
# Label with start picture,
startpic = PhotoImage(file="dbzsagas.png")
labelSagas = Label(root, image=startpic)
labelSagas.place(x=25, y=80)
#size of window
root.geometry("500x280")
#window title
root.title("Dragon Ball Saga´s guessing game")
#start of the window
root.mainloop()
Hope this helps! :)
I just want that when I type my name inside the entry box then appears in another entry with some add text. The idea is type in the entry below and after that it showed in the big entry.I was looking for this solution, but just found place in Label. I don't want in Label. The window is more big, must drag to show the entry. There's is a picture that i use in this script:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
cat = Entry(root)
cat.place(x=48, y=25, width= 350, height=140)
user = Entry(root)
user.place(x=75, y=550)
btn = Button(root, text='START')
btn.place(x=220, y=410)
root.mainloop()
#
Ok, It works the way you told me,thank you!
But now i'm facing another problem.
The problem is when i insert the function of the game in the second window. I tested in one window and it works, but when i place the function in the second window gives an error when i press the "Start" button:
'''user_try = int(txt.get())
NameError: name 'txt' is not defined'''
When i press reset button gives another error:
'''user_try = int(txt.get())
NameError: name 'txt' is not defined'''
So i know that is missing definition, but i don't know how to make a reference for this command that it's in the second window. Like i said running with just one window the program works.
Maybe i should make using class, i don't know, but i wish to make this way that i started. However if there's no other way to do as i'm doing, let's go.
I just simplify the script here, actualy the main script is more bigger, so my idea is when open the program, there is a window and the user read the instructions about the game and proceed open the second window. The window have pictures and some hidden buttons in the next picture, so there will be an interactivity with the environment.
The guess number is just the beggining. After that there will be new challeges.
I'm very excited doing this, but i'm stuck in this point. The part one i finished, the pictures, the hidden buttons it's exacly the way i want, but the challenge stops here in this problem.
from tkinter import *
from PIL import Image, ImageTk, ImageSequence
import random
from tkinter import messagebox
pc = random.randint(1,10)
def reset():
global pc
pc = random.randint(1,10)
cat['text'] = 'Ok! Lets Try Again!'
def openwin2():
win1.withdraw()
win2 = Toplevel()
win2.geometry('350x300+180+100')
win2.title('second window')
txt = Entry(win2)
txt.place(x=10,y=10)
cat = Label(win2,wraplength=300)
cat.place(x=10,y=50)
cat.config(text='Hi! I Am thinking a number between 1 and 10.')
btn = Button(win2,text='start',command=check)
btn.place(x=30, y=150)
btn2 = Button(win2, text='reset', command=reset)
btn2.place(x=110,y=150)
win2.mainloop()
def check():
user_try = int(txt.get())
if user_try < pc:
msg = 'Hmmmm... the number, which I thought of, is greater than this.'
elif user_try > pc:
msg = 'How about trying a smaller number ?!'
elif user_try == pc:
msg = 'Well Done! You guessed! It was %s the number!' % user_try
else:
msg = 'Something Went Wrong...'
cat['text'] = msg
win1 = Tk()
win1.title('First Window')
win1.geometry('350x300')
user = Label(win1,text='first window')
user.place(x=10,y=10)
btn1 = Button(win1,text='Open Window 2', command=openwin2)
btn1.place(x=10,y=50)
win1.mainloop()
There are multiple ways to do this in tkinter, here's a rework of your code using StringVar objects set to the textvariable properties of your Entry objects:
import tkinter as tk
def doit():
out_string.set("Hello " + in_string.get())
root = tk.Tk()
in_string = tk.StringVar()
out_string = tk.StringVar()
cat = tk.Entry(root, textvariable=in_string)
cat.place(x=20, y=25, width=100)
user = tk.Entry(root, textvariable=out_string)
user.place(x=20, y=75)
btn = tk.Button(root, text='START', command=doit)
btn.place(x=20, y=150)
root.mainloop()
Per #Mike-SMT, here's a different approach using Entry.get() and Entry.insert(). It augments the text when the user clicks the button:
import tkinter as tk
def doit():
user.insert(tk.END, cat.get())
root = tk.Tk()
cat = tk.Entry(root)
cat.place(x=20, y=25, width=100)
user = tk.Entry(root)
user.place(x=20, y=75)
user.insert(0, "Hello ")
btn = tk.Button(root, text='START', command=doit)
btn.place(x=20, y=150)
root.mainloop()
However, you'll see that subsequent button clicks keep appending the text. When working with Entry.insert(), you need to work with Entry.delete() and/or other Entry methods to properly manipulate the text.