How to stop the button's command by clicking another button - python

Let's say I have button1 which repeatedly changes its position randomly when clicked. I want to have button2 which will stop button1's action, but I haven't found any helpful method for that
from tkinter import *
def move():
# my code
def stop():
#???
master = Tk()
Button1 = Button(master, #some options, command = move).pack()
Button2 = Button(master,#some options, command = stop).pack()
master.mainloop()

So this code I am going to introduce after my research will hopefully satisfy what you need. So first of all, you need a function to move buttons around and secondly, another function to stop the working of the first one's function (i.e., to prevent its movement).
So one way of doing this is to set the state of the other Buttons to DISABLED to grey them out and prevent clicks. So the one I have shown below uses this method.
# Importing tkinter module
from tkinter import *
# Importing random module
import random
# Creating a tkinter window
root = Tk()
# Initialize tkinter window with dimensions 300 x 250
root.geometry('300x250')
# Stop other function
def stop():
btn.config(state=DISABLED)
# Defining func to move on click
def move():
x = random.randint(50,250)
y = random.randint(50,200)
btn.place(x=x, y=y)
# Creating a moving Button
btn = Button(root, text = 'Click me!',command=move)
btn.pack()
# Creating an end movement Button
endbtn = Button(root, text = 'Stop movement!', command=stop).pack()
root.mainloop()
Now coming to the second method, you can use another function that does nothing to modify the movement button's function. An example of this is given below:
# Importing tkinter module
from tkinter import *
# Importing random module
import random
# Creating a tkinter window
root = Tk()
# Initialize tkinter window with dimensions 300 x 250
root.geometry('300x250')
# Stop other function
def stop():
btn.config(command=donothing)
# A function to do nothing
def donothing():
pass
# Defining method on click
def move():
x = random.randint(50,250)
y = random.randint(50,200)
btn.place(x=x, y=y)
# Creating a moving Button
btn = Button(root, text = 'Click me!',command=move)
btn.pack()
# Creating an end movement Button
endbtn = Button(root, text = 'Stop movement!', command=stop).pack()
root.mainloop()
And the last method is to destroy the whole button. You can use the second button to destroy the first button. An example is given for your reference.
# Importing tkinter module
from tkinter import *
# Importing random module
import random
# Creating a tkinter window
root = Tk()
# Initialize tkinter window with dimensions 300 x 250
root.geometry('300x250')
# Destroy the other button
def stop():
btn.destroy()
# Defining method on click
def move():
x = random.randint(50,250)
y = random.randint(50,200)
btn.place(x=x, y=y)
# Creating a moving Button
btn = Button(root, text = 'Click me!',command=move)
btn.pack()
# Creating an end movement Button
endbtn = Button(root, text = 'Stop movement!', command=stop).pack()
root.mainloop()

Related

Button not showing up while opening new page (python tkinter)

I want to use the listbox in tkinter in order to open a new window with a button, but when I'm pressing a message it only opens the window, without the button.
from tkinter import *
from playsound import playsound
import os
# create a window as root using Tk() function
root = Tk()
root.geometry("200x200")
# create a changecolor function
# to change background color of window
def new_win():
top2 = Toplevel(root)
top2.geometry('200x200')
top2.title("display Window")
# photo2 = PhotoImage(file=r"hearing.png")
button = Button(text='wtf')
def changecolor(event):
# get selected list box color item
new_win()
# create listbox
listbox = Listbox(root , font=('times 20 bold'), height=5,width=10)
# insert color items into listbox
listbox.insert(1, 'first')
listbox.insert(2, 'second')
listbox.insert(3, 'third')
listbox.insert(4, 'forth')
listbox.pack(pady=20)
# bind the click event with listbox and
# call changecolor() function
listbox.bind('<<ListboxSelect>>', changecolor)
root.mainloop()
Any suggestion would be very helpful.
You can change the line 16
button = Button(text='wtf')
to
button = Button(top2,text='wtf')
button.pack()

on a button click, copy whats inside entry() and store it to a variable (tkinter)

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()

How do i check the state of bind() function in tkinter? (Python 3.8)

The goal of the program was to create a never-ending game of clicking the button. Every time the mouse pointer hovered over the button btn, it would move randomly across the window. But I can't seem to get the status of when the mouse hovers over the button. pardon any mistakes and feel free to correct them, I'm just a beginner. Heres the code -
from tkinter import *
import time
import random
window = Tk()
window.geometry("500x500")
lbl = Label(window, text = "Try to click the button")
lbl.pack()
def move_btn():
global btn
if btn.bind("<Enter>") == True:
wi = random.randint(0, 500)
hi = random.randint(0, 500)
btn.place(x = hi, y = wi)
btn = Button(window, text = "Click ME!",command = move_btn)
btn.pack()
window.mainloop()

Python/Tkinter - How can I create infinite copies of a window?

I want to make a window that is constantly created making many copies of its-self.
I have tried making an infinite loop that calls the function every time but that doesn't work. I also tried making one within the function but it just recreates the window after I close the old one. Does this mean that the window can't be duplicated?
import tkinter
import os
def win():
A = True
while A == True:
window = tkinter.Tk()
window.title('WHOOPS')
window.geometry('100x100')
window.configure(background= "green")
lbl = tkinter.Label(window, text= 'whoops', bg= 'red')
window.mainloop()
quit = False
while quit == False:
win()
Can someone show me how to duplicate a window without hard-coding a whole new block, for example, a new function for each of win2() and win3()?
The user should be able to see a practically infinite stream of windows that can only be stopped by using the KeyboardInterrupt or by closing the shell/interpreter.
If you create windows in a infinite loop you are never going to return control to the main_loop. You can follow one of the followings:
#1 You can initialize an integer to 0 and after a specific count update root and then again continue creating windows and after a specific count update root again and it goes on ...
import tkinter as tk
import time
def startInfiniteLoop():
i = 0
otherFrame = []
while True:
otherFrame.append(tk.Toplevel())
i += 1
if i%1000 == 0:
time.sleep(1)
root.update()
root = tk.Tk()
button_one = tk.Button(root, text="Infinite Window !", command=startInfiniteLoop)
button_one.grid(row=0, column=0)
root.mainloop()
#2 You can write a function that creates a window and from inside of that function call itself after specific time again and again.
import tkinter as tk
def startInfiniteLoop():
otherFrame = tk.Toplevel()
root.after(1000, startInfiniteLoop)
root = tk.Tk()
button_one = tk.Button(root, text="Infinite Window !", command=startInfiniteLoop)
button_one.grid(row=0, column=0)
root.mainloop()

How to create a tkinter toggle button?

I've been working on a text editor using Tkinter in Python 2.7.
A feature that I'm trying to implement is the Night Mode, where the user can toggle between a black background and a light one, that switches from light to dark with a click of the toggle button.
from Tkinter import *
from tkSimpleDialog import askstring
from tkFileDialog import asksaveasfilename
from tkFileDialog import askopenfilename
from tkMessageBox import askokcancel
Window = Tk()
Window.title("TekstEDIT")
index = 0
class Editor(ScrolledText):
Button(frm, text='Night-Mode', command=self.onNightMode).pack(side=LEFT)
def onNightMode(self):
if index:
self.text.config(font=('courier', 12, 'normal'), background='black', fg='green')
else:
self.text.config(font=('courier', 12, 'normal'))
index = not index
However, on running the code, it is always in the night mode and the toggle doesn't work. Help.
Source Code: http://ideone.com/IVJuxX
You can import tkinter library (Use capital letter for python 2.7):
import Tkinter
Create tkinter objects...
root = tk.Tk()
...and tkinter button
toggle_btn = tk.Button(text="Toggle", width=12, relief="raised")
toggle_btn.pack(pady=5)
root.mainloop()
Now create a new command button called "toggle" in order to create the effect of "toggle" when you press playing on the relief property (sunken or raised) :
def toggle():
if toggle_btn.config('relief')[-1] == 'sunken':
toggle_btn.config(relief="raised")
else:
toggle_btn.config(relief="sunken")
At the end apply this behaviour on your button:
toggle_btn = tk.Button(text="Toggle", width=12, relief="raised", command=toggle)
The background and fg are set only in the if-clause. You need to set them also in the else clause:
def onNightMode(self):
if index:
self.text.config(font=('courier', 12, 'normal'), background='black', fg='green')
else:
self.text.config(font=('courier', 12, 'normal'))
index = not index
i.e.,
else:
self.text.config(font=('courier', 12, 'normal'), background='green', fg='black')
Here's a code snippet that will help you with the toggle button animation if you would like to. You only need to add the functions that you want to execute when clicking of course, that's up to you.
'''
import tkinter as tk
# --- functions ---
def move(steps=10, distance=0.1):
if steps > 0:
# get current position
relx = float(frame.place_info()['relx'])
# set new position
frame.place_configure(relx=relx+distance)
# repeate it after 10ms
root.after(10, move, steps-1, distance)
def toggle(event):
if button["text"] == "Yes":
move(25, 0.02) # 50*0.02 = 1
button["text"] = "No"
print("Clicked on yes")
elif button["text"] == "No":
move(25, -0.02)
button["text"] = "Yes"
print("Clicked on no")
# --- main --
root = tk.Tk()
frame = tk.Frame(root, background='red')
frame.place(relx=0, rely=0, relwidth=0.5, relheight=1)
# to center label and button
#frame.grid_columnconfigure(0, weight=1)
#frame.grid_rowconfigure(0, weight=1)
#frame.grid_rowconfigure(3, weight=1)
button = tk.Button(frame, text='Yes',width=5,height=1)
button.place(relx=0.25,rely=0.5,relwidth=0.5, relheight=0.1)
button.bind("<Button-1>",toggle)
root.mainloop()
Albe's answer is good but it has some bad coding practices.
Following the same steps:
Import Tkinter as tk
top = tk.TK()
Define your function here and make it work for any button, not hard coded to the specific button you might use.
def toggle(button: tk.Button):
if button.config('relief')[-1] == 'sunken':
button.config(relief="raised")
else:
button.config(relief="sunken")
Then create and pack all the toggle buttons you want.
toggleButton = tk.Button(text="Toggle", width=12, relief="sunken",
command =lambda:toggle(toggleButton))
toggleButton.pack(pady=5)
top.mainloop()
This is better for two reasons. Creating the button object twice is redundant and will lead to buggy code. Hard coding the button to a specific toggle function is unscalable. This solution makes the code reusable and simple to add to. For example, replace that last block with:
for _ in range(4):
b = tk.Button(text="Toggle", width=12, relief="sunken")
b['command']= lambda a=b:toggle(a)
b.pack(pady=5)
And now you get 4 toggling buttons without any additional functions or copy/paste

Categories

Resources