I want to create a button that I can disable and re-enable as soon as I click it. With the following code, I get a button that I can disable, but it won't re-enable when I click it. If looked at this threat, but it didn't help: Disable / Enable Button in TKinter
import tkinter
from tkinter import *
# toplevel widget of Tk which represents mostly the main window of an application
root = tkinter.Tk()
root.geometry('1800x600')
root.title('Roll Dice')
frame = Frame(root)
# label to display dice
label = tkinter.Label(root, text='', font=('Helvetica', 120))
# function activated by button
def switch1():
if button1["state"] == "active":
button1["state"] = "disabled"
else:
button1["state"] = "active"
button1 = tkinter.Button(root, text='Würfel 1', foreground='green', command=lambda: switch1, state = "active")
button1.pack(side = LEFT)
root.mainloop()
Look at this:
import tkinter as tk
def toggle_state():
if button1.cget("state") == "normal":
button1.config(state="disabled")
else:
button1.config(state="normal")
root = tk.Tk()
button1 = tk.Button(root, text="This button toggles state")
button1.pack()
button2 = tk.Button(root, text="Click me", command=toggle_state)
button2.pack()
root.mainloop()
This uses a button to toggle the state of the other button.
Related
I have a problem with bind_class. I want to bind some events for all buttons in my topLevel mainWindow. But my other topLevel themeWindow's buttons also effected from this.
My code:
root = tk.Tk()
mainWindow = Toplevel(root)
themeWindow = Toplevel(root)
#my buttons and labels
mainWindow.bind_class('Button', '<Enter>', onCursorButton, add='+')
mainloop()
And themeWindow's buttons keep effecting from <Enter> and <Leave> event.
Try this code:
import tkinter as tk
def get_masters(widget):
output = []
while widget.master is not None:
widget = widget.master # Get the widgets master
output.append(widget) # Append it to the list
if isinstance(widget, tk.Toplevel): # If we incounter a toplevel stop
break
return output
def function(event):
print("Is the widget's master `main_window`?: ", main_window in get_masters(event.widget))
# Check if the widget that caused the event is in `main_window`
if main_window in get_masters(event.widget):
print("Hangle event")
else:
print("Ignore event")
root = tk.Tk()
main_window = tk.Toplevel(root)
theme_window = tk.Toplevel(root)
button = tk.Button(main_window, text="Main Window")
button.pack()
button = tk.Button(theme_window, text="Theme Window")
button.pack()
main_window.bind_class("Button", "<Enter>", function, add="+")
root.mainloop()
The function get_masters returns a list of all of the frames+window that the widget is in. In function, we check if the widget that caused the even is in main_window or not. Based on that we can either handle or ignore the event.
So I'm trying to create a program which uses multiple tk.Toplevel windows. The problem with this is, that all windows show up seperated as their "own App", so when you alt tab, you switch between the toplevel windows.
The pseudocode would look something like this:
import tkinter as tk
top_levels = {}
def open_toplevel():
top_level = tk.Toplevel(root)
top_level.geometry("300x200+0+0")
top_levels.update({f"toplevel{len(top_levels.keys())}" : top_level})
root = tk.Tk()
button = tk.Button(root, command= open_toplevel)
button.place(x=0, y=0)
root.mainloop()
So my question, is: is there a way to unify them into "one window"?
If you want all of them to unify into one window then tk.Frame is a better widget to use instead of tk.Toplevel
The purpose of tk.Toplevel is to create a new temporary window, not an extra part of the window. But frames are a really good way to organise stuff.
This code below creates new frame every time you click the button. This is just a simple example. You can also use grid for widgets in a frame. I also put a border so you can see where the frames are located.
from tkinter import *
def open_frame():
frame = Frame(root, highlightbackground="black", highlightthickness=2)
lbl1 = Label(frame, text=f"Frame {len(frames) + 1} label 1")
lbl2 = Label(frame, text=f"Frame {len(frames) + 1} label 2")
lbl1.pack()
lbl2.pack()
frame.pack(padx=5, pady=5)
frames.append(frame)
root = Tk()
frames = []
btn = Button(root, text="Open Frame", command=open_frame)
btn.pack()
root.mainloop()
I hope this solution is helpful
EDIT
Use this code here to move the frames:
from tkinter import *
def open_frame():
global frame, frames
frame = Frame(root, highlightbackground="black", highlightthickness=2)
lbl1 = Label(frame, text=f"Frame {len(frames) + 1} label 1")
lbl2 = Label(frame, text=f"Frame {len(frames) + 1} label 2")
lbl1.pack()
lbl2.pack()
frame.pack(padx=5, pady=5)
frame_number = len(frames)
lbl1.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
lbl2.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
frame.bind('<B1-Motion>', lambda event: MoveWindow(event, frame_number))
frames.append(frame)
labels.append(lbl1)
labels.append(lbl2)
def MoveWindow(event, frame_number):
global root, frames
root.update_idletasks()
f = frames[frame_number]
x = f.winfo_width()/2
y = f.winfo_height()*1.5
f.place(x=event.x_root-x, y=event.y_root-y)
root = Tk()
root.geometry("500x500")
frames = []
labels = []
btn = Button(root, text="Open Frame", command=open_frame)
btn.pack()
root.mainloop()
Here is the code,
from tkinter import *
root = Tk()
update_button = Button(root, text='Update')
update_button.pack()
def button():
frame1 = Frame(root)
frame1.pack()
button1 = Button(frame1, text="Button 1")
button1.pack(side=LEFT)
button2 = Button(frame1, text="Button 2")
button2.pack(side=LEFT)
button()
root.mainloop()
I want button1 to be stacked upon button2 when I click update button.
Help please.
So I have a starter tab which has a textbox inside. I also want to create a new tab on the click of a button. When I create the new tab it does not show the textbox. I want all the tabs to have the same textbox and the same widgets.
Here is my code so far:
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("600x600")
def newTab(*args): # How do I keep the textbox and other widgets in the new tabs
newFrame = Frame(root, width=500, height=500)
newFrame.pack()
tabsArea.add(newFrame, text="Untitled.txt")
button = Button(root, command=newTab).pack()
# Tab Area --- First Tab
tabsArea = ttk.Notebook(root)
tabsArea.pack(pady=15)
# Create Main Frame
frame = Frame(root)
frame.pack(pady=5)
# Add Frame to Tab
tabsArea.add(frame, text="Untitled.txt")
# Textbox
textBox = Text(frame).pack()
root.mainloop()
How do I configure the text box and widgets in the newFrame/new tab?
You need to add a new text widget in each tab. Your code is just creating empty frames. Also, you shouldn't be calling newFrame.pack() since you are adding newFrame to the notebook.
Here is a slimmed down version of your code that shows the basic concept:
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("600x600")
def newTab(*args):
newFrame = Frame(root, width=500, height=500)
tabsArea.add(newFrame, text="Untitled.txt")
text = Text(newFrame)
text.pack(fill="both", expand=True)
button = Button(root, text="New Tab", command=newTab)
tabsArea = ttk.Notebook(root)
button.pack(side="top")
tabsArea.pack(pady=15, fill="both", expand=True)
# Add the first tab
newTab()
root.mainloop()
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()