self.label_5 = tk.Checkbutton(self.master, text="I agree to the", bg='white', width=14,font=("Arial", 8), command= activator)
self.label_5.place(x=112, y=410)
self.button_2 = tk.Button(text='Proceed', width=20, bg='white', state = tk.DISABLED, bd=1,
highlightbackground='black', font=("Arial", 10)).place(x=208, y = 512)
def activator(button):
if (self.button_2 ['state'] == tk.DISABLED):
self.button_2 ['state'] = tk.NORMAL
else:
self.button_2['state'] = tk.DISABLED
I want to enable the proceed button after I checked the checkbutton but I can't seem to figure it out.
You have to make the following changes to your code:
You have to refer to the function named activator as self.activator when giving it to the Button(button_2) as command.
You have to change the parameter named button of the function named activator to self.
And the most important thing you need to do is move the part of code where you are placing the Button(button_2) and the Checkbutton(label_5), to a new line. Like I have done in the code below. The reason for doing so is that pack, grid and place always return None. And when you do it in the same line where you have created your widgets and assigned them to a variable i.e. button_2 and label_5, the value None gets stored in that widget.
Here's the corrected code:
import tkinter as tk
class Test:
def __init__(self):
self.master = tk.Tk()
self.master.geometry('550x550')
self.label_5 = tk.Checkbutton(self.master, text="I agree to the", bg='white', width=14, font=("Arial", 8),
command=self.activator)
self.label_5.place(x=112, y=410)
self.button_2 = tk.Button(text='Proceed', width=20, bg='white', state=tk.DISABLED, bd=1,
highlightbackground='black', font=("Arial", 10))
self.button_2.place(x=208, y=512)
self.master.mainloop()
def activator(self):
if self.button_2['state'] == tk.DISABLED:
self.button_2['state'] = tk.NORMAL
else:
self.button_2['state'] = tk.DISABLED
if __name__ == '__main__':
Test()
Related
I actually found a solution for this but they used an entirely different way of making windows/buttons and i can't figure out how to use it.
Please tell me if there's a way to make this happen with my code.
The code for my window and its content is as below
from tkinter import *
title = 'zromber'
window = Tk()
window.geometry("800x400")
def play():
print('welcome')
window.destroy()
def save():
print('yes')
playbutton = Button(window, text='play')
playbutton.config(command=play)
playbutton.config(font=('none', 50, 'bold'))
testlabel = Label(window, text=title)
testlabel.config(font=('Ink Free', 50))
testlabel.pack()
playbutton.pack()
savebutton = Button(window, text='save')
savebutton.config(command=save)
savebutton.config(font=('none', 50, 'bold'))
savebutton.pack()
window.mainloop()
from tkinter import *
title = 'zromber'
window = Tk()
window.geometry("800x400")
my_text = "Hi, I'm a the new label"
def play():
#use label.config(text="new text") to change text
my_label.config(text=my_text+" and I'm from play")
def save():
my_label.config(text=my_text+" and I'm from save")
playbutton = Button(window, text='play')
playbutton.config(command=play)
playbutton.config(font=('none', 50, 'bold'))
testlabel = Label(window, text=title)
testlabel.config(font=('Ink Free', 50))
testlabel.pack()
playbutton.pack()
savebutton = Button(window, text='save')
savebutton.config(command=save)
savebutton.config(font=('none', 50, 'bold'))
savebutton. pack()
#Define the label
my_label = Label(window, text="THIS IS A LABEL")
my_label.config(font=('none', 10, 'bold'))
my_label.pack()
window.mainloop()
Here I've created a new label called my_label and when the play button calls for the play() function, i've used label.config(text="new text") to change text.
You can run the sample code above to get your results.
I am trying to create a basic invoicing system. However i have encountered an issue as you can tell from my the title, is there any way to achieve this. I have been using a counter to determine if the window should open or not but i dont think it is right.
from tkinter import *
window = Tk()
count = 0
def openNewWindow():
global count
count = count + 1
if count == 1:
newWindow = Toplevel(window)
newWindow.title("New Window")
newWindow.geometry("800x800")
newWindow.title('test ©') # Frame title
newWindow.iconbitmap('icon4.ico') # Frame logo
if 'normal' == newWindow.state():
count = 2
else:
count = 0
width = window.winfo_screenwidth()
height = window.winfo_screenheight()
window.geometry("%dx%d" % (width, height))
bg = PhotoImage(file="bsor.gif")
label_image = Label(window, image=bg)
label_image.place(x=0, y=0)
title_label = Label(window, text="Job Management System", bg="black", fg="white")
title_label.config(font=("Courier", 70))
title_label.place(x=65, y=3)
customer_database_button = Button(window, text="Customer Database", width="23", height="2",
font=('Courier', 13, 'bold'), command=openNewWindow)
customer_database_button.grid(row=3, column=0, pady=185, padx=(110, 0))
employee_database_button = Button(window, text="Employee Database", width="23", height="2",
font=('Courier', 13, 'bold'))
employee_database_button.grid(row=3, column=1, pady=10, padx=(50, 0))
job_category_button = Button(window, text="Job Category (Pricing)", width="23", height="2",
font=('Courier', 13, 'bold'))
job_category_button.grid(row=3, column=2, pady=10, padx=(50, 0))
quote_sale_button = Button(window, text="Quotes / Sales", width="23", height="2", font=
('Courier', 13, 'bold'))
quote_sale_button.grid(row=3, column=3, pady=10, padx=(50, 0))
cash_management_button = Button(window, text="Cash Management", width="23", height="2", font=
('Courier', 13, 'bold'))
cash_management_button.grid(row=3, column=4, pady=10, padx=(50, 0))
analysis_mode_button = Button(window, text="Analysis Mode", width="23", height="2", font=
('Courier', 13, 'bold'))
analysis_mode_button.grid(row=3, column=5, pady=10, padx=(50, 0))
window.title('test') # Frame title
window.iconbitmap('icon4.ico') # Frame logo
window.mainloop()
Here is a minimal example on how to do it (works best with only one additional allowed window):
from tkinter import Tk, Toplevel, Button
def open_window(button):
button.config(state='disabled')
top = Toplevel(root)
top.transient(root)
top.focus_set()
top.bind('<Destroy>', lambda _: btn.config(state='normal'))
root = Tk()
root.geometry('300x200')
btn = Button(root, text='Open new window!', command=lambda: open_window(btn))
btn.pack(expand=True)
root.mainloop()
Just have the function disable the button and bind a <Destroy> event to the Toplevel to set the button's state back to normal. (Also you may want to use .transient on the Toplevel to make it appear above its master so that people don't forget that they haven't closed the window and wonder why they can't press the button (it will also not display additional icon in the taskbar))
Also:
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.
I strongly suggest following PEP 8 - Style Guide for Python Code. Function and variable names should be in snake_case, class names in CapitalCase. Don't have space around = if it is used as a part of keyword argument (func(arg='value')) but have space around = if it is used for assigning a value (variable = 'some value'). Have space around operators (+-/ etc.: value = x + y(except here value += x + y)). Have two blank lines around function and class declarations.
What I am trying to do:
I want the button Confirmar to disappear once it is clicked, for that I redirected it to the function dConfirm which is supposed to trigger the destroy process.
What is happening:
The button is defined in a different function from the destroy process, so it is returning a not defined error.
My code:
def dSim():
btn3=Button(janela, text= "Hipertensao arterial", command = add1)
btn3.place(x = 80, y = 219)
btn4=Button(janela, text= "Pedras nos rins", command = add2)
btn4.place(x = 200, y = 219)
btn5=Button(janela, text= "Osteoporose", command = add3)
btn5.place(x = 295, y = 219)
btn6=Button(janela, text= "Colesterol elevado", command = add4)
btn6.place(x = 378, y = 219)
btn7=Button(janela, text= "Esclerose multipla", command = add5)
btn7.place(x = 492, y = 219)
btn.destroy()
btn2.destroy()
lb7=Label(janela, text= "Selecione as suas doencas:", font = ("Verdana", "14"))
lb7.place(x = 185, y = 190)
btn8=Button(janela, text= "Confirmar", command = dConfirm)
btn8.place(x = 80, y = 240)
def dNao():
lb5=Label(janela, text=Gperf, font = ("Verdana", "14"))
lb5.place(x = 80, y = 165)
btn.destroy()
btn2.destroy()
lb6=Label(janela, text="E perfeitamente saudavel, otimo!", font = ("Verdana", "14"))
lb6.place(x = 185, y = 190)
def dConfirm():
btn8.destroy()
You have three options:
btn8 is a local variable, so you cannot refer to it outside its scope. You can make it global.
Instead of directly calling dConfirm(), pass to it the button instance using a lambda like this:
btn8 = Button(janela, text="Confirmar", command=lambda: dConfirm(btn8)) and change the function definition to def dConfirm(btn8):(I would prefer this if you don't want to move to option 3 and modify your code)
If you are using classes, make it an instance of the class by using self.btn8 and then destroy it by using self.btn8.destroy().
#1 You can try this:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root)
frame.grid(row=0, column=0, padx=4, pady=4)
# destroy the button on dConfirm function call
def dConfirm():
btn8.destroy()
# Declare btn8 outside of the two function
btn8 = tk.Button(frame, text="Confirmar", command=dConfirm)
# Place btn8 inside the function you want
def dSim():
btn8.grid(row=0, column=0, padx=4, pady=4)
dSim()
root.mainloop()
#2 You can also try this (In my opinion this is better):
import tkinter as tk
class MainWindow:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.frame.grid(row=0, column=0, padx=4, pady=4)
self.dSim()
def dConfirm(self):
self.btn8.destroy()
def dSim(self):
self.btn8 = tk.Button(self.frame, text="Confirmar", command=self.dConfirm)
self.btn8.grid(row=0, column=0, padx=4, pady=4)
def main():
root = tk.Tk()
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
I have the following code, which causes a color/text change when a Tkinter button is clicked. I would like to revert to the original color/text when the button is clicked a second time.
from Tkinter import *
window = Tk()
window.title("Start/Stop Button")
window.geometry('200x100')
def clicked_rf1():
btn_rf1.configure(text="Stop")
lbl_rf1.configure(text=" ON ", bg="green")
btn_rf1 = Button(window, text="Start", command=clicked_rf1)
btn_rf1.grid(column=1, row=1)
lbl_rf1 = Label(window, text=" OFF ", bg="red")
lbl_rf1.grid(column=2, row=1)
window.mainloop()
I want something that behaves a little more like a toggle, but I would like the look of a button.
Help gratefully received.
You will need an if block to choose what to do. You can make another flag variable to keep track of the state, or just use the current Label or Button text:
from Tkinter import *
window = Tk()
window.title("Start/Stop Button")
window.geometry('200x100')
def clicked_rf1():
if btn_rf1['text'] == "Start":
btn_rf1.configure(text="Stop")
lbl_rf1.configure(text=" ON ", bg="green")
else:
btn_rf1.configure(text="Start")
lbl_rf1.configure(text=" OFF ", bg="red")
btn_rf1 = Button(window, text="Start", command=clicked_rf1)
btn_rf1.grid(column=1, row=1)
lbl_rf1 = Label(window, text=" OFF ", bg="red")
lbl_rf1.grid(column=2, row=1)
window.mainloop()
This would be an ideal place to make a custom Button subclass, so you could have many of these in your program:
from Tkinter import *
window = Tk()
window.title("Start/Stop Button")
window.geometry('200x100')
class Christina(Frame):
def __init__(self, master=None, **kwargs):
Frame.__init__(self, master, **kwargs)
self.btn = Button(self, text="Start", command=self.clicked)
self.btn.grid(column=0, row=0)
self.lbl = Label(self, text=" OFF ", bg="red")
self.lbl.grid(column=1, row=0)
def clicked(self):
if self.btn['text'] == "Start":
self.btn.configure(text="Stop")
self.lbl.configure(text=" ON ", bg="green")
else:
self.btn.configure(text="Start")
self.lbl.configure(text=" OFF ", bg="red")
btn1 = Christina(window)
btn1.grid()
btn2 = Christina(window)
btn2.grid()
btn3 = Christina(window)
btn3.grid()
window.mainloop()
If you want a toggle, you can use the checkbutton without an indicator. It has options for the color in the selected and deselected state, and you can tie the value and the label together so that the label changes when you toggle the button.
Like any button, you can tie a command to it. The command can check the value of the variable to determine whether it should do the "on" function or the "off" function.
Here's a simple example:
import Tkinter as tk
def toggle():
if var.get() == "ON":
print("turning on...")
else:
print("turning off...")
root = tk.Tk()
var = tk.StringVar()
toggle = tk.Checkbutton(root, onvalue="ON", offvalue="OFF", width=4,
indicatoron=False,
variable=var, textvariable=var,
selectcolor="green", background="red",
command=toggle)
var.set("OFF")
toggle.pack()
root.mainloop()
Another approach might be to put the "pile of code" to run into different function, collect those in an iterator, and then get the next function from that iterator and execute it:
def bunchofcode():
print("foo")
def somethingelse():
print("bar")
whattodo = iter([bunchofcode, somethingelse])
def clicked_rf1():
try:
next(whattodo)()
except StopIteration:
print("nothing to do")
Or for cyclic behaviour:
from itertools import cycle
whattodo = cycle([bunchofcode, somethingelse])
For a two-state toggle button, you could also use a dict to map the current state to the next. You could also use the button's relief to mark the state.
def clicked_rf1():
transition = {"raised": "sunken", "sunken": "raised"}
btn_rf1["relief"] = transition[btn_rf1["relief"]]
I want two buttons to show up when I press my rectangle (function door1), each one of them will give different true value to my global variable CHANGED.
The problem is that I'm having trouble with the aligning. The buttons always show up in an additional part to my current window, and I want them to show up on top of my current window
from tkinter import Tk, Canvas, Button
CHANGED = False
def options():
global window
button1 = Button(window, text='Click to change door')
button1.bind("<Button-1>", change)
button1.pack(side='top')
button2 = Button(window, text='Click to keep door')
button2.bind("<Button-1>", keep)
button2.pack(side='top')
def change(*args):
global CHANGED
CHANGED = True
def keep(*args):
global CHANGED
CHANGED = False
def door1(*args):
options()
window = Tk()
canvas = Canvas(window, width=600, height=500)
square1 = canvas.create_rectangle(50, 500, 150, 200, fill="blue", tags="open_door_1")
canvas.tag_bind("open_door_1", "<Button-1>", door1)
canvas.pack()
window.mainloop()
How can I change it?
You can use grid to achieve that, by defining the row to place your widgets :
from tkinter import Tk, Canvas, Button
CHANGED = False
def options():
button1 = Button(window, text='Click to change door')
button1.bind("<Button-1>", change)
button1.grid(row=0, sticky='w')
button2 = Button(window, text='Click to keep door')
button2.bind("<Button-1>", keep)
button2.grid(row=1, sticky='w')
def change(*args):
global CHANGED
CHANGED = True
def keep(*args):
global CHANGED
CHANGED = False
def door1(*args):
options()
window = Tk()
canvas = Canvas(window, width=600, height=500)
square1 = canvas.create_rectangle(50, 500, 150, 200, fill="blue", tags="open_door_1")
canvas.tag_bind("open_door_1", "<Button-1>", door1)
canvas.grid(row=2)
window.mainloop()
EDIT:
A solution to keep the window from resizing when the widgets appear, you can use the rowconfigure method like below and specify a geometry :
Also, another point to fix : you should be careful about the creation of the buttons, each click on the canvas creates 2 more widgets (visible or not depending on the layout).
The functional pattern may not be the best to handle this, you need to define the buttons as global variables and only create them if they are not already displayed :
from tkinter import Tk, Canvas, Button
CHANGED = False
button1 = None
button2 = None
def options():
global button1, button2
button1 = Button(window, text='Click to change door')
button1.bind("<Button-1>", change)
button1.grid(row=0, sticky='w')
button2 = Button(window, text='Click to keep door')
button2.bind("<Button-1>", keep)
button2.grid(row=1, sticky='w')
def change(*args):
global CHANGED
CHANGED = True
def keep(*args):
global CHANGED
CHANGED = False
def door1(*args):
if button1 is None and button2 is None:
options()
window = Tk()
window.geometry("600x600")
window.rowconfigure(2,weight=1)
canvas = Canvas(window, width=600, height=500)
square1 = canvas.create_rectangle(50, 500, 150, 200, fill="blue", tags="open_door_1")
canvas.tag_bind("open_door_1", "<Button-1>", door1)
canvas.grid(row=2,sticky='s')
window.mainloop()