tkinter: How to get value in optionsmenu? - python

I'm trying to use the OptionMenu in order to assign a command via a button widget, however I am unable to get the proper value for some reason.
So my code goes something along those lines:
root = tk.Tk()
choice1 = tk.StringVar()
choice1.set("DEFAULT")
options1 = tk.OptionMenu(root, choice1, "text1", "text2")
options1.place(x=320, y=355)
start_button = tk.Button(root, text="start")
start_button.place(x=200, y=400)
if choice1.get() == "text1":
start_button.configure(command=lambda: print("some text"))
root.mainloop()
And it doesn't work if the option is on "text1", however if I change if choice1.get() == "text1" to if choice1.get() == "DEFAULT" then it seems to work, but for every option, not only default.
How do I assign a specific command to an external button based on what's selected in the OptionMenu widget?
By the way, if I change the command to print choice1.get() it does print out the correct option (while I just assign the command to the button widget without an if statement).
Edit:
As per request, the game is connect 4, and the options are Human and PC.
What I'm trying to do is have 2 option menus, one for player 1 (Yellow) one for player 2 (Red). Once Human vs Human is selected, the I would like the start button to direct me to a specific function.
Here is what I wrote (needs editing, sorry for how it looks):
self.__root = root
self.__global_size = 70
self.game = Game()
menu_draw = tk.Canvas(self.__root, width=500, height=500)
menu_draw.pack()
self.__root.resizable(0, 0)
welcome_label = tk.Label(self.__root, text=WELCOME_MSG, font=("Comic Sans MS", 20), bg="White", fg="Blue",
relief="groove")
menu_draw.create_oval((100, 250), (200, 350), fill="red")
menu_draw.create_oval((300, 250), (400, 350), fill="Yellow")
welcome_label.place(x=60, y=40)
choice1 = tk.StringVar()
choice1.set("Yellow")
options1 = tk.OptionMenu(self.__root, choice1, "Human", "PC")
options1.configure(bg="Yellow")
options1.place(x=320, y=355)
choice2 = tk.StringVar()
choice2.set("Red")
options2 = tk.OptionMenu(self.__root, choice2, "Human", "PC")
options2.configure(bg="Red")
options2.place(x=100, y=355)
start_button = tk.Button(self.__root, text="START", font=("Comic Sans MS", 20), bg="White", fg="Blue")
start_button.place(x=200, y=400)
if choice1.get() == "Human" and choice2.get() == "Human":
start_button.configure(command=lambda: self.mainm(self.__root))
self.__root.mainloop()
But ya, it doesn't work. If I replace both "Human" to "Yellow" and "Red" respectively, then it works, but it works for every option that is selected.
self.mainm directs do another function that destroys the old root and creates a new one (to create the board and rules).

Related

How do I delete a text content when I press a botton using tkinter?

I am creating a code that adds numbers or words to a text box and then switches the numbers or words around. I want to create a clear button that deletes all the content in the textbox and when the user presses one of the other buttons it appears again. When I created the code the clear button does not work, how can I fix it?
from tkinter import *
class main:
def __init__(self, test):
self.lbl1=Label(text="Select Button")
self.btn6 = Button(test, text="Random Number 1", command=lambda : self.Label(float(3+3)))
self.Example = Text(window, height = 3, width = 10)
self.b1=Button( test, text='Random Number 2', command= lambda: self.testingLabel(float(2+3)))
self.clear = Button(test,text="Clear", command= self.clear_text)
v0=IntVar()
v0.set(1)
self.s1=Radiobutton(test, text="Switch", variable=v0,value=1)
self.s2=Radiobutton(test, text="Switch Back", variable=v0,value=2)
self.lbl1.place(x=0, y=0)
self.btn6.place(x=0, y=50)
self.b1.place(x=0 , y= 100 )
self.s1.place(x=0,y=180)
self.s2.place(x=80, y=180)
self.clear.place(x = 200 , y = 80 )
def testingLabel(self,text):
self.Example.insert(1.0, text)
self.Example.pack()
def Label(self,text):
self.Example.insert(1.0, text)
self.Example.pack()
def clear_text(self):
self.Example.delete("0",END)
self.Example.pack()
window=Tk()
mywin=main(window)
window.title("Testing")
window.geometry("400x300+10+10")
window.mainloop()
Change your code to read this.
def clear_text(self):
self.Example.delete("1.0" ,END) # changed your "0" to "1.0" for clearing textbox
self.Example.pack()

How do I make two independent drop down lists that don't interact with eachother?

This is the code I got so far and I woul'd like to make two speperate lists, one for the difficulty and one for the characters. But if I change the variable in one list the otherlist changes too. I cant find anything on youtube or forums that explain how to make them independant from eachother.
import tkinter as tk
from tkinter import messagebox
import random
import pygame
root= tk.Tk()
root.title("Generic Game")
canvas1 = tk.Canvas(root, width = 300, height = 300, bg="black")
canvas1.pack()
canvas1.create_text(150,50, text="Square attak 2: The Devil returns", font="Times", fill="white")
root.resizable(False, False)
def startEasy():
print("Game started")
def startgame():
if variable.get() == DifficultyList[1]:
startEasy()
elif variable.get() == DifficultyList[2]:
messagebox.showinfo("Info", "You are now not playing on Medium mode!")
elif variable.get() == DifficultyList[3]:
messagebox.showinfo("Info", "You are now not playing on Hard mode!")
else:
messagebox.showinfo("Disclaimer", "You need to choose a difficulty!")
startbutton = tk.Button(root, text="Start", command=startgame, fg="black", activeforeground="white", activebackground ="green").place(x=96, y=150)
exitbutton = tk.Button(root, text="Exit Game", command=root.destroy, fg="black", activebackground="red").place(x=96, y=250)
canvas1.create_window(150, 150, window=exitbutton)
canvas1.create_window(150, 150, window=startbutton)
DifficultyList = [
"Difficulty",
"Easy",
"Medium",
"Hard"
]
Characters = [
"Harold",
"Stefan",
"Peter"
]
variable = tk.StringVar(root)
variable.set(DifficultyList[0])
variable.set(Characters[0])
Difficulty = tk.OptionMenu(root, variable, *DifficultyList).place(x=96, y=100)
Characters = tk.OptionMenu(root, variable, *Characters).place(x=10, y=10)
root.mainloop()
give a different control variable to Characters (change tk.OptionMenu(root, variable, *Characters) change that variable to something else) – JacksonPro
you see this:
variable = tk.StringVar().
Make a similar variable say:
char_var = tk.StringVar()
now change Characters = tk.OptionMenu(root, variable, *Characters).place(x=10, y=10) -> Characters = tk.OptionMenu(root, char_var, *Characters).place(x=10, y=10) also change variable.set(Characters[0]) to char_var.set(Characters[0]).
Note Your Characters is None since place returns None and don't assign optionmenu to the same variable as the list. – JacksonPro

When I click on button 2 after pressing on button 1 it does not work

When I click on button 2 after pressing on button 1 it does not work.
I am making an auto clicker for fun, as a side project.
import tkinter as tk
from pynput.mouse import Button, Controller
import time
Height = 700
Width = 800
mouse = Controller()
flag = True
def click_function():
while flag == True:
time.sleep(.001)
mouse.click(Button.left, 1)
def endclick_function():
flag = False
root = tk.Tk()
canvas = tk.Canvas(root, height=Height, width=Width)
canvas.pack()
frame = tk.Frame(root,bg='black')
frame.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.5)
button = tk.Button(frame, text="Start" , bg='white', fg='black', font=50, command=click_function)
button.place(relx=0, rely=0, relwidth=0.5, relheight=0.5)
button2 = tk.Button(frame, text="Stop" , bg='white', fg='black', font=50, command=lambda: endclick_function)
button2.place(relx=.5, rely=0, relwidth=0.5, relheight=0.5)
label = tk.Label(frame, text='Time to Sleep:', bg='white', font=50)
label.place(relx=0, rely =0.5, relwidth=0.5, relheight=0.25)
label2 = tk.Label(frame, text='How many times to click:', bg='white', font=50)
label2.place(relx=0, rely =0.75, relwidth=0.5, relheight=0.25)
entry = tk.Entry(frame, bg='white')
entry.place(relx=0.5, rely =0.5, relwidth=0.5, relheight=0.25)
entry2 = tk.Entry(frame,text='Time to Sleep(ms):', bg='white')
entry2.place(relx=0.5, rely =0.75, relwidth=0.5, relheight=0.25)
root.mainloop()
you have to declare flag global if you want to change it
also as Joe Ferndz pointed out, the flag is never set back to True
def click_function():
global flag
flag = True # of course, only if you want to use clicker more than once
while flag == True:
time.sleep(.001)
mouse.click(Button.left, 1)
def endclick_function():
global flag
flag = False
Something I just noticed
in button2, command=lambda:end_f
remove lambda
this is basically saying
def l():
return end_f
button2['command'] = l
and since the command (l) is executed at the click on the button,
it only returns the function, does not execute it
When you click the first button, the flag is set to True. However, when you click on second button, the flag gets set to False. Later when you come back to first button, the flag is False so it never goes into the while loop.
Do you want to try and implement this an alternate way?
def click_function():
while flag == True:
time.sleep(.001)
mouse.click(Button.left, 1)
def endclick_function():
flag = False

Tkinter Radio Button Controlling If True

I am trying to do a simple program. I am trying to check if radio button 1 is selected show a button and if radio button 2 selected and if there is a button on the screen disappear it. Please help me.
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
bati = tkinter.Tk()
bati.geometry('500x500')
bati.title('Project')
def hello():
messagebox.showinfo("Say Hello", "Hello World")
def askfile():
bati.filename = filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
lb2 = Label(bati, text=bati.filename, fg='red', font=("Times", 10, "bold"))
lb2.place(x='270',y='34')
def first():
b = Button(bati, text='Import', activebackground='red', bd='3', bg='gray', fg='yellow', font=("Times New Roman", 10, "bold"), command=askfile)
b.place(x='200',y='30')
working = True
def second():
if working == True:
b.widget.pack_forget()
working = False
canvas_width = 3000
canvas_height = 220
w = Canvas(bati, width=canvas_width,height=canvas_height)
w.pack()
y = int(canvas_height / 2)
w.create_line(0, y, canvas_width, y, fill="#476042", width='2')
v = IntVar()
v.set('L')
rb1 = Radiobutton(bati, text='Import A File', value=1, variable=v, command=first, font=("Comic Sans MS", 10, "bold"))
rb2 = Radiobutton(bati, text='Choose From Web', value=2, variable=v, command=second, font=("Comic Sans MS", 10, "bold"))
rb1.place(x='50',y='30')
rb2.place(x='50',y='50')
working = False
bati.mainloop()
Issues:
Local variables will not work for this - you need to remember the button state outside of first and second, so that you can use it the next time.
We show the button with .place, so we should similarly hide it with .place_forget instead of .pack_forget.
The .place position should be given with integers instead of strings. Similarly for the button's bd, i.e. border width (in pixels, i.e. a number of pixels).
Event handlers are supposed to receive an event parameter, even if you ignore it. The .widget you've written in your second command is presumably copied from some other code that tries to find out the widget to hide from the event data (e.g. here). But that .widget would be the one that sent the command, i.e. the Radiobutton, not the Button that you want to hide.
What we will do is create the button ahead of time, in a global variable (in a more serious project, you should consider using classes instead, and then you would use a class member to remember it). Since the button should start out not visible, we just don't .place it right away, but instead use .place in first and .place_forget in second. So:
b = Button(
bati, text='Import', activebackground='red', bd=3,
bg='gray', fg='yellow', font=("Times New Roman", 10, "bold"),
command=askfile
)
def first(event):
b.place(x=200,y=30)
def second():
b.place_forget()

Python, Tkinter how to give optionmenu its own windows when pressed

I have a drop down menu girded on my calculator and i have it set so that there is 3 menu items. What i want to happen is that when one of the menu items is selected it opens a toplevel window describing that item menu and each one is a different menu because they contain different things how can i code this to happen. Im stuck with setting it so that it opens different window for when a different one is slected.
def change_dropdown(*args):
top = Toplevel()
top.title("READ")
toplabel = Label(top,text= "Lmao", font = ("Helvetica", 13))
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = ("Helvetica", 10, "bold"), fg = "ghostwhite", bg = "black", width = "30", height = "2", command=top.destroy)
button.grid()
top.focus()
def popmenu():
global tkvar
tkvar = StringVar(master)
choices = {"About","Colour themes", "Contact",}
popupMenu = OptionMenu(master, tkvar, *choices)
popupMenu.grid(row = 0, column = 0, columnspan = 5, sticky=W+E+S+N)
tkvar.set("About")
tkvar.trace("w", change_dropdown)
As far as I can understand, you want something like this...
def change_dropdown(*args):
if tkvar.get() == "About":
# open About window
elif tkvar.get() == "Contact":
# open Contact window
...., etc
Complete example
Each Toplevel window is a window like the root window and you put widgets on it just like on master.
I changed the code a bit to make it more readable from my point of view; I lifted the main window (master) code from the function. I put font specs in the beginning to make the Labels and Buttons code shorter. I changed the Dict choices to a Tuple which feels more natural. I gave the OptionMenu a width to keep it from changing size with chosen selection.
from tkinter import *
master = Tk()
master.geometry('300x150+1000+50')
info = Label(master, text='Press "p" for popup menu')
info.pack()
# Fonts
H13 = ("Helvetica", 13)
H10B = ("Helvetica", 10, "bold")
def change_dropdown(*args):
top = Toplevel()
if tkvar.get() == "About": # About window
top.title("About")
toplabel = Label(top,text= "The About window", font = H13)
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = H10B,
fg = "ghostwhite", bg = "black", width = "30",
height = "2", command=top.destroy)
button.grid()
top.focus()
elif tkvar.get() == "Contact": # Contact window
top.title("Contact")
toplabel = Label(top,text= "Contact form", font = H13)
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = H10B,
fg = "ghostwhite", bg = "black", width = "30",
height = "2", command=top.destroy)
button.grid()
top.focus()
elif tkvar.get() == "Colour themes": # Color themes window
top.title("Colour themes")
toplabel = Label(top,text= "Choose color theme", font = H13)
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = H10B,
fg = "ghostwhite", bg = "black", width = "30",
height = "2", command=top.destroy)
button.grid()
top.focus()
tkvar = StringVar(master)
def popmenu(event):
top = Toplevel()
choices = ("About","Colour themes", "Contact") # Tuple or List instead of dict
popupMenu = OptionMenu(top, tkvar, *choices)
popupMenu.config(width=15) # Otherwise width varies with option
popupMenu.grid(row = 0, column = 0, columnspan = 5, sticky=W+E+S+N)
tkvar.set("Pick one")
tkvar.trace("w", change_dropdown)
master.bind('p', popmenu)
master.mainloop()
This is a very simple interface, but if you plan on making it more complex I strongly suggest you read up on Object Oriented Python. Keeping track of globals gets difficult pretty quick.

Categories

Resources