ttk checkbutton is not deselected by default - python

Please kick here to see the current output and expected output
I have a simple python program where i want to deselect the checkbutton by default. I want to see it the same way as when a user unchecks a tick box. Please let me know how to achieve it.
from tkinter import *
from tkinter import ttk
def urgentReq():
global box
state = box.state()
if(box.instate(['selected'])):
print ("--> Urgent: ",state)
else:
print ("--> Not Urgent:",state)
gui = Tk()
gui.title("GUI")
gui.geometry('200x150')
box = ttk.Checkbutton(gui, text ='Urgent Request', command=lambda: urgentReq())
box.grid(column=1, row=4, pady=40, sticky="N")
#write something here to unselect the box by default

box.state(['!alternate']) #box appear unchecked
box.state(['selected']) #box appear checked

Use the .invoke() method, but from what I read elsewhere is will also call the command, if one is associated. The instance I was trying to use this, my check button didn't have a command as a parameter, so this worked perfectly for me.
Hope this helps and good luck!

Somehow the initial state of the CheckButton = ('alternate',).
There is a workaround I found here: tkk checkbutton appears when loaded up with black box in it. If you apply it to your code like this, it seems to work:
checkVar = IntVar()
box = ttk.Checkbutton(gui, text ='Urgent Request', command=lambda: urgentReq(), variable=checkVar)

I think you can write box.deselect() to deselect it.
Edit: Oops, I just tested it, it's not working with ttk... Sorry. :)

Related

How do I bind the ListBox of a ComboBox in Python Tkinter

I am looking to make a bind that allows me to place a certain value depending on the key pressed by the user.
Here is an example code in which I do it:
from tkinter import *
from tkinter import ttk
v=Tk()
combo = ttk.Combobox(values=['item1','item2','item3','item4'], state='readonly')
combo.current(0)
combo.pack()
def function(Event):
if(Event.char in '1234'):
combo.set(f'item{Event.char}')
combo.bind('<Key>', function)
v.mainloop()
They will tell me "If that works, what are you doing asking this?"
Well it turns out that if the Combobox is deployed, the bind stops working.
How could the problem be solved?
I know that this part of the question should not be asked, since it has nothing to do with the problem in question. But I would like to ask that if something is wrong in this question, or misspelled, or whatever, be informed. The page of "how to ask a good question" does not serve me, since from my point of view, I do everything as they say there.
I did my best to make what is written here as detailed and understandable as possible.
Hope your understanding, thank you.
Based on what Henry Yik proposed and studying what was returned by Event.widget, I found the solution to the problem.
from tkinter import *
from tkinter import ttk
v=Tk()
# I create two test combobox
for _ in range(2):
combo = ttk.Combobox(values=['item1','item2','item3','item4'], state='readonly')
combo.current(0)
combo.pack()
# I create a test entry to test if the function correctly recognizes when it should be executed
entrada = Entry()
entrada.pack()
def function(Event):
"""
If Event.widget is a str and ends with ".popdown.f.l" I consider it to be the Listbox,
I get the path of the Combobox it belongs to and convert it to a widget.
Afterwards, I set the value of Event.widget to that of the supposed combobox.
"""
if(isinstance(Event.widget, str) and Event.widget.endswith(".popdown.f.l")):
Event.widget = v._nametowidget(Event.widget[:-len(".popdown.f.l")])
# If Event.widget is not a Combobox, it stops the execution of the function.
if(not isinstance(Event.widget, ttk.Combobox)):
return
if(Event.char in '1234'):
Event.widget.set(f'item{Event.char}')
v.bind_all('<Key>', function)
v.mainloop()

Python tkinter Checkbutton not appearing selected in Topframe window

When programming with tkinter I have found a very strange behaviour of the Checkbutton widget. I have re-created the bug with the code below:
import tkinter
from tkinter import *
def displayWelcomeScreen(root):
root2 = Toplevel(root)
root2.geometry('600x380')
root2.focus_set()
Checked = IntVar()
CheckButton1 = Checkbutton(root2, variable=Checked)
CheckButton1.place(relx=0.5, rely=0.5, anchor=CENTER)
CheckButton1.select()
# Create a dummy button that makes the Checkbutton appear checked to the user
#Button(root2, command= lambda event: Checked.get())
root = Tk()
root.geometry('700x400')
displayWelcomeScreen(root)
root.mainloop()
When a new window is created with Toplevel(root) and I put a Checkbutton inside it, it does not appear checked to the user even though I use the .select() method.
However, when I create a dummy button whose command mentions the IntVar associated with my Checkbutton, somehow it is initialised as checked properly. It's almost as if the compiler checks whether the Checkbutton will be useful and decides based on that whether it will display it as selected or not.
EDIT: The Checkbutton is definitely checked under the hood because if I run print(Checked.get()) before and after the CheckButton1.select() command, the value is changed, it just doesn't appear to the user.
Does anyone know why this happens?
EDIT 2: Thanks to jasonharper's explanation, I have added the line CheckButton1.intvar = Checked and it worked without needing the dummy button. When the function went out of scope, the Checked variable got lost so the Checkbutton had nowhere to store its state, therefore we needed to keep a reference to it so it didn't disappear.

Python Tkinter updating text-box content via a function

Beginner programmer here, working on making a basic GUI as part of a tutorial I was following online, but none of them say how to get a Text box to update using the output of the other parts of your code.
I tried multiple other answers on the site, including one using StringVar's, which got me nowhere, another using a decorator, and the rest seemed way out of my depth.
Here's my code:
import tkinter as tk
import time
#Creating Root
root = tk.Tk()
#GUI TEMPLATE
frame =tk.Frame(root,
height = 100,
width = 400)
frame.pack()
v = StringVar()
colour = ["red","blue","green","white","yellow"]
labels = range(5)
#change number to change how many labels
for i in range(5):
l= tk.Label(root,
text = colour[i],
bg = colour[i])
l.place(x = 10 +i*70, y = 10, width=60, height=25)
T1 = tk.Text(root, height=2, width=40)
words = "Don't name your files after module names!"
T1.insert(tk.END, textvariable=v)
T1.place(x = 10, y= 40)
S = tk.Scrollbar(root)
S.config(command=T1.yview)
S.place(x = 340, y=40)
T1.config(yscrollcommand=S.set)
root.mainloop()
v.set("Something Else!")
Now, what it should output is a row of coloured labels, which works fine, and a text box with a scroll bar, which should instantly update to read 'Something Else!', which does not work fine.
Instead I get the following error:
NameError: name 'StringVar' is not defined
I know what this error means, it's just I've hit a wall when it comes to finding a solution that works for me, and doesn't need a doctorate to understand.
What I'm asking for is if someone can give me a solution that would work for this, and hopefully explain it!
Thanks in advance.
EDIT:
So after fixing the syntax error, and then finding out what I'm trying to do doesn't work, how would I go about this?
Could I use a label instead? Or is there another, better way?
Thanks again!
StringVar should accessed via tk:
v = tk.StringVar()
On another note, tk.Text.insert does not take a textvariable parameter, so the following won't work:
T1.insert(tk.END, textvariable=v)
# ^^^^^^^^^^^^??
From the docs:
Unlike for example the entry widget, text widgets don't support a
"textvariable" configuration option
Also see How can I connect a StringVar to a Text widget in Python/Tkinter? as to why this won't work.
I was experimenting with learning threading with Tkinter and have made something work to insert and update text in a Tkinter text box in Python3 which may be of help.
I found that by deleting the text I could then insert new text. Untill I deleted the existing text the instruction to insert text seamed to be ignored.
{ foo = input("Give me input: " )
self.T.delete("1.0", END) #Clear the text window so we can write.
self.T.insert(END,foo) #Write the new text.}

Buttons to remove themselves in Tkinter

I'm sorry if this has been asked already, but I haven't been able to find it. I'm also just starting to learn programming so feedback is appreciated. :)
My end goal is to create an 8 by "x" grid of buttons that change their own color when pushed. I want to use this to make a grid I can upload to the POV toy I've built. This code creates a column of 8 buttons each with a callback passing itself as an argument. The idea being the callback function can do things to the button like change it's color, or delete it.
import Tkinter
def unpack(i):
buttons[i].pack_forget()
print i
top = Tkinter.Tk() buttons = [] for i in range(0, 8):
buttons.append(Tkinter.Button(top, text='Hello', command=lambda: unpack(i)))
for button in buttons:
button.pack()
top.mainloop()
When I do this I get a windows with column of 8 buttons, and when I click on one one gets deleted. When I click on a second nothing happens. In my command prompt I get the number 7 printed no matter which button I press. I suspect the problem is in the for loop that creates the buttons, but I have no idea how to fix it.
Thanks!
Pass the button object to the callback function instead of the index, because the index is change after the item deletion in the list.
import Tkinter
top = Tkinter.Tk()
for i in range(0, 8):
btn = Tkinter.Button(top, text='Hello')
btn['command'] = lambda b=btn: b.pack_forget()
btn.pack()
top.mainloop()
NOTE: To prevent late binding problem, I used default parameter in the above code.

Good-styled console input

I'm writing a little Chatserver/-client to learn Python.
Now I want to make the consoleinput a little bit nicer, but I don't know how to do it...
Everytime I recieve a message from the socket, I do print() in the listening thread.
But then the text already entered to input() is over the printed message and the cursor is at the bottom.
What can I do, that is works like in Minecraft-Server, so the text already entered moves to the bottom?
Would be great if someone can help :)
You can't get that level of control with the console, but you can use python's default tkinter to make a simple UI. Below is an example (Python 3) that I whipped up in a few minutes. You can type in messages, press send, and they will appear in the box above.
from tkinter import *
from tkinter import ttk
def send(view, entry):
view.insert('1.0', entry.get() + "\n")
root = Tk()
msgview = Text(root, width=100, height=20)
msgview.grid(sticky=(N,E,S,W))
mymessage = StringVar(value="type here...")
msginput = Entry(root, textvariable=mymessage)
msginput.grid(sticky=(E,W))
sendbutton = ttk.Button(root, text="send",\
command=lambda: send(msgview, msginput))
sendbutton.grid()
root.mainloop()
I suggest looking at the tkdocs tutorial over the effbot one, since it is clearer, easier to follow and is more thorough in my opinion. New Mexico Tech also provides a great reference for tkinter here

Categories