Python-Tkinter: Trying to unpack a button with an if statement - python

I know there are better ways about this, but I cant figure out what's
wrong about this code, or at least, why it wont function the way I want it. Currently I made a simple test program to try my concept away from my
main code.
from tkinter import *
root = Tk()
test = True
def click():
global test
print("working")
test = False
button = Button(root, text="Hi", command=click)
if test:
button.pack()
root.mainloop()
Everything runs fine but when I press the button all I get is the message "working" without the button going away.

In your code python checks if test is True and as it is, it packs the button and moves on. What you need to use is <tkinter widget>.pack_forget(). It removes the widget from the screen without destroying it. If you later call pack it should put it back in its original place. This is your code with the pack_forget:
from tkinter import *
root = Tk()
def click():
print("working")
button.pack_forget()
button = Button(root, text="Hi", command=click)
button.pack()
root.mainloop()

Related

Tkinter button issue

import tkinter
win=tkinter.Tk()
win.configure(background='grey')
k=False
def g():
k=True
v=tkinter.Button(win, text='click', command=g)
v.pack()
while k==True:
win.configure(background='black')
win.mainloop()
There's no reason why that while loop would run after the button is clicked, since (as you know) your program is run "from top to bottom", and control remains in win.mainloop() until the window is closed. (You can find that out by adding print("bye!") after that call.)
You might want to just directly call .configure(). (I gave the button some padding here so you can see the background change; otherwise the button may take up the entirety of the window and you won't see a change.)
import tkinter
win = tkinter.Tk()
def change_color():
win.configure(background='black')
button = tkinter.Button(win, text='click', command=change_color)
button.pack(padx=10, pady=10)
win.mainloop()

Tkinter winfo_ismapped() method not working

I have a program in python which in which I use Listboxes, buttons and labels. So today I came conflicting with a problem. I wanted to make my listbox appear when a button is clicked and disappear when the same button is clicked again. How can I achieve this? I tried using the winfo_ismapped() method but didnt seem to work. I think I might have done something crazy. If so, please point it out and give me a corrected answer. Else please tell me a better way to do it.
My Code:
import tkinter as tk
from tkinter import *
root = tk.Tk()
root.geometry('500x500')
def showMenu():
overlay = Listbox(root, bg="green", height=22, width=58)
if overlay.winfo_ismapped() == 0:
overlay.place(x=0,y=35)
else:
overlay.placeforget()
button = tk.Button(root,text="place/remove", command=showMenu)
button.place(x=0,y=0)
root.mainloop()
Actually it comes when I press the button but hide after I press it again.
In the same way I have another issue with these labels too.
CODE:
import tkinter as tk
root = tk.Tk()
def placeFun():
successtext = tk.Label(root, text="Success", anchor='nw', bg="#212121", fg="#ff3300",font=("Consolas", 15, "bold"))
if successtext.winfo_ismapped() == 0:
successtext.place(x=0,y=50)
else:
succestext.forget()
button = tk.Button(root, text='place/rem', width=25, command=placeFun)
button.place(x=0,y=0)
root.mainloop()
Please Note: I want a professional way to handle this, I said it because, I know a way in which we use variables like:
globalvartimes = 0
def somefunc():
if times % 2 == 0:
show the listbox
global times
times += 2
else:
remove the listbox
times += 1
*This shows the listbox when times is even and remove it when it's odd.
These makes the code look non-professional and long.
The problem is every time showMenu() is called another Listbox is created. To fix that, create the Listbox outside of the function (so it's a global).
(I also noticed you misspelled the name of place_forget() method.)
import tkinter as tk
from tkinter import *
root = tk.Tk()
root.geometry('500x500')
def showMenu():
if overlay.winfo_ismapped(): # Placed?
overlay.place_forget()
else:
overlay.place(x=0,y=35)
overlay = Listbox(root, bg="green", height=22, width=58)
button = tk.Button(root,text="place/remove", command=showMenu)
button.place(x=0,y=0)
root.mainloop()
This looks like it is what is wrong with your Label example, too.
Note: If you want to write "professional" code, I suggest you read (and start following) the
PEP 8 - Style Guide for Python Code.

How can I combine this tkinter label and string into one window?

In a program I am working on there is a tkinter label/button which starts the card game (the program I am using) and a other window that has a string stating 'Welcome to the card game'.
Here is the tkinter section of the code:
import tkinter
window = tkinter.Tk()
print()
from tkinter import *
def quit():
global root
root.quit()
root = Tk()
while True:
label = tkinter.Label(window, text = "Welcome to the card game! (During name registration only use characters)").pack()
Button(root, text="Start Game", command=quit).pack()
root.mainloop()
However when I run the program they each appear in their own window screens when it would be more convenient for the user to have the options in one single window.
Is there anyway to merge them?
EDIT - (Having the button and text using root has fixed the problem.)
There is a lot going on here that should not be in such a small set of code.
Lets break it down.
First your imports. You are importing from tkinter multiple times. You only need to import once and you can use everything with the proper prefix. The preferred method is import tkinter as tk this way you don't overwrite any other imports or built in methods.
Next we need to get rid of one of your instances of Tk() as tkinter should only ever have one. For other windows use Toplevel().
In your quit function you do not need to define global as you are not assigning values here so the function will look in the global namespace for root.
Next Lets delete the empty print statement.
Next make sure both your label and button have the same container assigned to them. This is the reason why you are seeing them in different windows.
Next rename your function as quit is a built in method and should not be overwritten.
Lastly we remove the while statement as the mainloop() is already looping the Tk instance. You do not need to manage this yourself.
Here is what your code should look like (a 2nd window serves no purpose here):
import tkinter as tk
def root_quit():
root.quit()
root = tk.Tk()
tk.Label(root, text="Welcome to the card game! (During name registration only use characters)").pack()
tk.Button(root, text="Start Game", command=root_quit).pack()
root.mainloop()
Here is an example using Toplevel just so you can get an idea of how it is used.
import tkinter as tk
def root_quit():
root.quit()
def game_window():
top = tk.Toplevel(root)
tk.Button(top, text='exit', command=root_quit).pack()
root = tk.Tk()
tk.Label(root, text="Welcome to the card game! (During name registration only use characters)").pack()
tk.Button(root, text="Start Game", command=game_window).pack()
root.mainloop()

Python Tkinter Keybinds and Buttons blocking each other?

I've got a piece of code similar to this:
def create_main(self):
self.bind("<Left>", lambda e:self.function())
self.button1 = Button(self, ...)
self.button1.grid(row=0, column =0)
#furtherbuttons...
def function(self):
print('test')
The Problem I've got with this code is that the function never gets called if I press left. I tried it with different buttons and the mouse, mouse buttons always work just fine but the keyboard does nothing.
I read something about buttons blocking the bind action, but no solution to this problem.
Here is an MCVE that works with 3.6.1 on Win10.
import tkinter as tk
root = tk.Tk()
def handle(event=None):
print(event)
return 'break'
root.bind('<Left>', handle)
tk.Button(root, text='button', command=handle)
root.mainloop()
Both <-- and left click print event arg. No interference or blocking.

python label not changing dynamically

I want to see continuously changing value of label in tkinter window. But I'm not seeing any of it unless I make a keyboard interrupt in MS-CMD while running which shows me the latest assigned value to label. Plz tell me ..What's going on & what's the correct code ??
import random
from Tkinter import *
def server() :
while True:
x= random.random()
print x
asensor.set(x)
app=Tk()
app.title("Server")
app.geometry('400x300+200+100')
b1=Button(app,text="Start Server",width=12,height=2,command=server)
b1.pack()
asensor=StringVar()
l=Label(app,textvariable=asensor,height=3)
l.pack()
app.mainloop()
The function server is called when you click the button, but that function contains an infinite loop. It just keep generating random numbers and sending these to asensor. You are probably not seeing any of it because the server function is run in the same thread as the GUI and it never gives the label a chance to update.
If you remove the while True bit from your code, a new number will be generate each time you click the button. Is that what you wanted to do?
Edit after comment by OP:
I see. In that case your code should be changed as follows:
import random
from Tkinter import Tk, Button, Label, StringVar
def server():
x = random.random()
print x
asensor.set(x)
def slowmotion():
server()
app.after(500, slowmotion)
app = Tk()
app.title("Server")
app.geometry('400x300+200+100')
b1 = Button(app, text="Start Server", width=12, height=2, command=slowmotion)
b1.pack()
asensor = StringVar()
asensor.set('initial value')
l = Label(app, textvariable=asensor, height=3)
l.pack()
app.mainloop()
I also introduced a new function, slowmotion, which does two things: 1) calls server, which updates displays the value, and 2) schedules itself to be executed again in 500ms. slowmotion is first ran when you first click the button.
The problem with your code was that it runs an infinite loop in the main GUI thread. This means once server is running, the GUI will not stop and will not get a chance to display the text you asked it to display.

Categories