Tkinter Dual Command for one Button - python

I'm doing my GCSE's and this is one of the tasks that I have been given, (btw I'm not very good at this) I need help with putting two commands into one button on tkinter for python. Here is my Code
# --------------------- START OF SCRIPT ---------------------
# Imports
from tkinter import *
# Question 1
def rootclose():
root.destroy()
def question1():
q1 = Tk()
q1.geometry("500x500+200+200")
f1 = Frame()
f1.pack(side=LEFT)
f2 = Frame()
f2.pack(side=RIGHT)
q1l1 = Label(q1, text="Question 1", fg="Green")
q1l1.pack()
q1l2 = Label(q1, text="What Operating System Dose Your Phone Run?", fg="Green")
q1l2.pack()
def question2v1():
q2v1 = Tk()
a1.destroy()
q2v1.geometry("500x500+200+200")
q2v1l1 = Label(q2v1, text="", fg="Green")
q2v1l1.pack()
q2v1l2 = Label(q2v1, text="", fg="Green")
q2v1l2.pack()
b1 = Button(q2v1, text="Android")
b2 = Button(q2v1, text="")
b1.pack()
b2.pack()
q2v1.mainloop()
def ios():
q3 = Tk()
q1.destroy()
q3.geometry("500x500+200+200")
q3l1 = Label(q3, text="Question 1", fg="Green")
q3l1.pack()
q3l2 = Label(q3, text="Did you select IOS", fg="Green")
q3l2.pack()
b1 = Button(q3, text="Android")
b2 = Button(q3, text="IOS")
b1.pack()
b2.pack()
q3.mainloop()
q1b1 = Button(q1, text="Android", command=question2v1)
q1b2 = Button(q1, text="IOS", command=ios)
q1b1.pack()
q1b2.pack()
q1.mainloop()
# Tkinter startups
root = Tk()
# Size ect..
root.geometry("500x500+200+200")
#HelpBot
L1 = Label(root, text="Welcome To HelpBot", fg="Green")
L1.pack()
# StartButton
B1 = Button(root, text="Start!", command=question1 and rootclose)
B1.pack()
# END OF SCRIPT
root.mainloop()
I am specifically trying to fix this
# StartButton
B1 = Button(root, text="Start!", command=question1 and rootclose)
B1.pack()
The And that I have put in the command section of the button will only run the Last function in this case "rootclose" and not bother with this first which in this case is "question1"

Create a function to do your 2 commands, and make calling that the command that the button does.

Related

how to cancel the after method for an off delay timer in tkinter using python 3.8

I have a off delay program in which when I select the input checkbutton, the output is 1. When I deselect the input checkbutton, the output goes back to 0 after a timer (set up in a scale). For that I use the after method. That part works. My problem is that I want to reset the timer if the checkbutton is selected again before the output went to 0; but once the checkbutton is selected the first time, the after method get triggered and it doesn't stop. I'm trying to use after_cancel, but I can't get it to work. Any solution?
from tkinter import *
root = Tk()
t1= IntVar()
out = Label(root, text="0")
remain_time = IntVar()
grab_time = 1000
def start_timer(set_time):
global grab_time
grab_time = int(set_time) * 1000
def play():
if t1.get() == 1:
button1.configure(bg='red')
out.configure(bg="red", text="1")
else:
button1.configure(bg='green')
def result():
out.configure(bg="green", text="0")
out.after(grab_time,result)
button1 = Checkbutton(root,variable=t1, textvariable=t1, command=play)
time = Scale(root, from_=1, to=10, command=start_timer)
button1.pack()
time.pack()
out.pack()
root.mainloop()
Expected: when press the checkbutton before the output went to 0, reset the counter.
So you could use the .after_cencel when the value of checkbutton is 1:
from tkinter import *
root = Tk()
t1= IntVar()
out = Label(root, text="0")
remain_time = IntVar()
grab_time = 1000
def start_timer(set_time):
global grab_time
grab_time = int(set_time) * 1000
def play():
if t1.get() == 1:
button1.configure(bg='red')
out.configure(bg="red", text="1")
try: # when the first time you start the counter, root.counter didn't exist, use a try..except to catch it.
root.after_cancel(root.counter)
except :
pass
else:
button1.configure(bg='green')
def result():
out.configure(bg="green", text="0")
root.counter = out.after(grab_time,result)
button1 = Checkbutton(root,variable=t1, textvariable=t1, command=play)
time = Scale(root, from_=1, to=10, command=start_timer)
button1.pack()
time.pack()
out.pack()
root.mainloop()

How to open a new frame from a current window in python tkinter?

class Login:
def __init__(self):
Label1 = Label(root,text = "Username")
Label2 = Label(root,text = "Password")
self.Entry1 = Entry(root)
self.Entry2 = Entry(root,show = "*")
Label1.grid(row=0)
Label2.grid(row=1)
self.Entry1.grid(row = 0,column = 1)
self.Entry2.grid(row = 1,column = 1)
root.minsize(width = 300,height = 80)
##new_window_button = Button(text="new window", command = ????)
##new_window_button.grid(columnspan = 2)
lgbutton = Button(text = "Login",command = self.ButtonClicked)
lgbutton.grid(columnspan = 2)
def ButtonClicked(self):
username = self.Entry1.get()
password = self.Entry2.get()
GetDatabase(username,password)
Currently this is what I have to create a window, however I want it to that when the new_window_button is clicked, the new page has its own widgets. I've used Toplevel before but it creates a child window without the widgets. Instead, the widgets are added to the parent window.
Judging by the comments it looks as though you are struggling with declaring the correct parent for widgets.
When a widget is declared the first parameter passed in to it is it's parent. For example:
Label(root, text="I'm in the root window.")
# ^ This is the parent
As opposed to:
Label(top, text="I'm in the top window.")
# ^ This is the parent
Please see a more fleshed out example below:
from tkinter import *
root = Tk()
top = Toplevel(root)
label1 = Label(root, text="I'm a placeholder in your root window.")
label2 = Label(top, text="I'm a placeholder in your top window.")
label1.pack()
label2.pack()
root.mainloop()
import tkinter
from tkinter import *
class LoginForm(Frame):
def __init__(self,master=None):
super().__init__(master)
self.pack()
self.createWidget()
def createWidget(self):
self.lblEmailId=Label(self,text="Email Id")
self.lblEmailId.grid(row=0,column=0)
self.varEmailid=StringVar()
self.txtEmailId=Entry(self,textvariable=self.varEmailid)
self.txtEmailId.grid(row=0,column=1)
self.txtEmailId.bind("<KeyRelease>",self.key_press)
self.lblPassword = Label(self, text="Password")
self.lblPassword.grid(row=1, column=0)
self.varPassword=StringVar()
self.txtPassword= Entry(self, textvariable=self.varPassword)
self.txtPassword.grid(row=1, column=1)
self.btnLogin=Button(self,text="Login")
self.btnLogin.grid(row=2,column=1)
self.btnLogin.bind("<Button-1>",self.btnLogin_click)
def btnLogin_click(self,event):
self.varPassword.set(self.varEmailid.get())
LoginWindow=Toplevel()
def key_press(self,event):
self.varPassword.set(self.varEmailid.get())
root=Tk()
fromLogin=LoginForm(root)
root.mainloop()

Making a Tkinter Listbox with Scrolll

I'm currently trying to make a Listbox with a Scroll bar on the side appear on my Tkinter Window. I can't figure out how to make the Scrollbar size the same size as my listbox. Heres my code:
global R3
global lb
R3 = Tk()
gg = "white"
g = "blue"
R3.geometry('720x720')
R3.title(username + " Dropbox")
R3.resizable(width=False, height=False)
logoutbt = Button(R3, text="Logout", width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE, command=rectologout)
upload = Button(R3, text="Upload", width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE, command=rectoupload)
logoutbt.place(x=220, y=500)
upload.place(x=480, y=500)
button1 = Button(R3, text='Receive file', width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE,command = get_file)
lb = Listbox(R3, height=6,width = 15)
s.send("RETREIVEA-"+username)
file_list = s.recv(1024).split("-")
if file_list == [""]:
button1.config(state = DISABLED)
for file in file_list:
lb.insert("end", file)
yscroll = Scrollbar(R3, orient=VERTICAL)
lb['yscrollcommand'] = yscroll.set
yscroll['command'] = lb.yview
lb.place(x=280,y=200)
yscroll.place(x=370,y=200)
button1.place(x=400, y=200)
R3.mainloop()
Any suggestions on how to do it?
First of all, please read how to create a Minimal, Complete and Verifiable example.
Your code lacks imports and references non-initialized objects / variables / functions.
How to achieve what you want?
Either use grid instead of place or pass height parameters to lb.place(..., height=<whatever you want>) and yscroll.place(..., height=<whatever you want>)

Python Tk _tkinter.TclError: invalid command name ".42818376"

I am getting the error mentioned in the title of the post I really just want this to work. Been working on this problem for a while now and it is frustrating. My ultimate goal is to obtain the values for the varables text, chkvar, and v.
Thanks to anyone who can reply and help on this!!
#!C:/Python27/python.exe
from Tkinter import *
import ImageTk, Image
root = Tk()
root.title('HADOUKEN!')
def killwindow():
root.destroy()
text = Text(root, height=16, width=40)
scroll = Scrollbar(root, command=text.yview)
text.configure(yscrollcommand=scroll.set)
text.grid(sticky=E)
scroll.grid(row=0,column=1,sticky='ns')
text.focus()
chkvar = IntVar()
chkvar.set(0)
c = Checkbutton(root, text="CaseIt", variable=chkvar)
c.grid(row=1,column=0,sticky=W)
v = ""
radio1 = Radiobutton(root, text="Src", variable=v, value=1)
radio1.grid(row=1,column=0)
radio1.focus()
radio2 = Radiobutton(root, text="Dst", variable=v, value=2)
radio2.grid(row=2,column=0)
b1 = Button(root, text="Submit", command=killwindow)
b1.grid(row=1, column=2)
img = ImageTk.PhotoImage(Image.open("Hadoken.gif"))
panel = Label(root, image = img)
panel.grid(row=0, column=2)
root.mainloop()
tk1 = text.get(text)
tk2 = chkvar.get(chkvar)
tk3 = v.get(v)
print tk1
print tk2
print tk3
Once mainloop exits, the widgets no longer exist. When you do text.get(text), you're trying to access a deleted widget. Tkinter simply isn't designed to allow you to access widgets after the main window has been destroyed.
The quick solution is to modify killwindow to get the values before it destroys the window, and store them in a global variable which you can access after mainloop exits.
The program didn't make it through the variable getting, so it never reported the incorrect method calls. I made a few changes to the original code (added a textval StringVar, and changed the v variable to another IntVar). I had a feeling the "associated variables" wouldn't have a problem, and didn't need to be included in the killwindow code. The only variable I grab in killwindow is the text data.
Working code (changed lines marked with #++) :
#!C:/Python27/python.exe
from Tkinter import *
import ImageTk, Image
root = Tk()
root.title('HADOUKEN!')
textval = StringVar() #++ added
def killwindow():
textval.set(text.get('1.0',END)) #++ grab contents before destruction
root.destroy()
text = Text(root, height=16, width=40)
scroll = Scrollbar(root, command=text.yview)
text.configure(yscrollcommand=scroll.set)
text.grid(sticky=E)
scroll.grid(row=0,column=1,sticky='ns')
text.focus()
chkvar = IntVar()
chkvar.set(0)
c = Checkbutton(root, text="CaseIt", variable=chkvar)
c.grid(row=1,column=0,sticky=W)
v = IntVar() #++ changed
v.set(1) #++ initial value
radio1 = Radiobutton(root, text="Src", variable=v, value=1)
radio1.grid(row=1,column=0)
radio1.focus()
radio2 = Radiobutton(root, text="Dst", variable=v, value=2)
radio2.grid(row=2,column=0)
b1 = Button(root, text="Submit", command=killwindow)
b1.grid(row=1, column=2)
img = ImageTk.PhotoImage(Image.open("Hadoken.gif"))
panel = Label(root, image = img)
panel.grid(row=0, column=2)
root.mainloop()
# windows are destroyed at this point
tk1 = textval.get() #++ changed
tk2 = chkvar.get() #++ changed
tk3 = v.get() #++ changed
print tk1
print tk2
print tk3

How can I update a text box 'live' in tkinter?

I would like to ask how would I go about maybe creating a 'LIVE' text box in python? This program is a simulator for a vending machine (code below). I want there to be a text box showing a live credit update How do you do that in tkinter?
For Example: Say there is a box for credit with 0 inside it in the middle of the window. When the 10p button is pressed the box for credit should change from '0' to '0.10'.
Is it possible to do thit in tkinter and python 3.3.2?
Thank you in advance!
import sys
import tkinter as tk
credit = 0
choice = 0
credit1 = 0
coins = 0
prices = [200,150,160,50,90]
item = 0
i = 0
temp=0
n=0
choice1 = 0
choice2 = 0
credit1 = 0
coins = 0
prices = [200,150,160,50,90]
item = 0
i = 0
temp=0
n=0
choice1 = 0
choice2 = 0
def addTENp():
global credit
credit+=0.10
def addTWENTYp():
global credit
credit+=0.20
def addFIFTYp():
global credit
credit+=0.50
def addPOUND():
global credit
credit+=1.00
def insert():
insert = Tk()
insert.geometry("480x360")
iLabel = Label(insert, text="Enter coins.[Press Buttons]").grid(row=1, column=1)
tenbutton = Button(insert, text="10p", command = addTENp).grid(row=2, column=1)
twentybutton = Button(insert, text="20p", command = addTWENTYp).grid(row=3, column=1)
fiftybutton = Button(insert, text="50p", command = addFIFTYp).grid(row=4, column=1)
poundbutton = Button(insert, text="£1", command = addPOUND).grid(row=5, column=1)
insert()
Sure you can! Just add another label to the frame, and update the text attribute whenever one of your add functions is called. Also, you can simplify that code, using one add function for all the different amounts.
def main():
frame = Tk()
frame.geometry("480x360")
Label(frame, text="Enter coins.[Press Buttons]").grid(row=1, column=1)
display = Label(frame, text="") # we need this Label as a variable!
display.grid(row=2, column=1)
def add(amount):
global credit
credit += amount
display.configure(text="%.2f" % credit)
Button(frame, text="10p", command=lambda: add(.1)).grid(row=3, column=1)
Button(frame, text="20p", command=lambda: add(.2)).grid(row=4, column=1)
Button(frame, text="50p", command=lambda: add(.5)).grid(row=5, column=1)
Button(frame, text="P1", command=lambda: add(1.)).grid(row=6, column=1)
frame.mainloop()
main()
Some more points:
note that you define many of your variables twice
you should not give a variable the same name as a function, as this will shadow the function
probably just a copy paste error, but you forgot to call mainloop and your tkinter import is inconsistent with the way you use the classes (without tk prefix)
you can do the layout right after creating the GUI elements, but note that in this case not the GUI element will be bound to the variable, but the result of the layouting function, which is None
Borrowing a framework from tobias_k's excellent answer, I would recommend you use a DoubleVar instead.
from tkinter import ttk
import tkinter as tk
def main():
frame = Tk()
frame.geometry("480x360")
credit = tk.DoubleVar(frame, value=0)
# credit = tk.StringVar(frame, value="0")
ttk.Label(frame, textvariable = credit).pack()
def add_credit(amt):
global credit
credit.set(credit.get() + amt)
# new_credit = str(int(credit.get().replace(".",""))+amt)
# credit.set(new_credit[:-2]+"."+new_credit[-2:])
ttk.Button(frame, text="10p", command = lambda: add_credit(0.1)).pack()
# ttk.Button(frame, text="10p", command = lambda: add_credit(10)).pack()
ttk.Button(frame, text="20p", command = lambda: add_credit(0.2)).pack()
# ttk.Button(frame, text="20p", command = lambda: add_credit(20)).pack()
ttk.Button(frame, text="50p", command = lambda: add_credit(0.5)).pack()
# ttk.Button(frame, text="50p", command = lambda: add_credit(50)).pack()
ttk.Button(frame, text="P1", command = lambda: add_credit(1.0)).pack()
# ttk.Button(frame, text="P1", command = lambda: add_credit(100)).pack()
frame.mainloop()
The comments in that code is an alternate implementation that will work better, if only just. This will guarantee you won't have any strange floating-point errors in your code.

Categories