Automatically checking checkbox in Tkinter Python - python

Here I am trying to get the checkbox checked if every element of sensor input is 1. But somehow it's not happening. I used the same logic in another part of my code.
Here is my code.
from tkinter import *
sensors=[1,1,1,1,1]
def sensor_check():
var2=IntVar()
sensor_checkbox = Checkbutton(frame1, text="Sensors working?", variable=var2, state=DISABLED)
sensor_checkbox.pack()
error_list = [i+1 for i, v in enumerate(sensors) if v == 0]
if len(error_list) == 0:
var2.set(1)
else:
message = Label(frame1, text="Sensors "+error_list+" are not working properly")
message.pack(fill="x")
mainwindow = Tk()
mainframe=Frame(mainwindow,bg="red")
mainframe.pack(fill="both",expand=True)
frame1 = Frame(mainframe)
button = Button(frame1, text="Start",command=sensor_check)
button.pack()
frame1.pack(fill="x")
mainwindow.mainloop()

There are following issues in your code:
var2 is a local variable which is garbage collected after exiting the function, that is why the checkbox is not checked even though all sensors are 1
exception will be raised on text="Sensors "+error_list+" are not working properly" because you try to concatenate string with list
To solve the issues:
save a reference of var2
use f-string for the text option
def sensor_check():
var2=IntVar()
sensor_checkbox = Checkbutton(frame1, text="Sensors working?", variable=var2, state=DISABLED)
sensor_checkbox.pack()
sensor_checkbox.var = var2 # save a reference of var2
error_list = [i+1 for i, v in enumerate(sensors) if v == 0]
if len(error_list) == 0:
var2.set(1)
else:
message = Label(frame1, text=f"Sensors {error_list} are not working properly")
message.pack(fill="x")

Related

How to insert special characters in tkinter

I'm creating a GUI with tkinter, in this GUI there are some entry widgets that the user has to fill in, and the inputs will be stored in a file.
The issue that I'm facing is that the user can't insert special characters like emojis in these entry widgets.
I found some ways to display them...:
converting a special character to the equivalent surrogate pair:
this '\U0001f64f'(🙏) to this '\ud83d\ude4f'
Python: Find equivalent surrogate pair from non-BMP unicode char
converting a special character to the equivalen javascript format:
this 😊 to this '\uD83D\uDE05'
Displaying emojis/symbols in Python using tkinter lib
... but I didn't find anything about my problem.
I thought about solving it by displaying near the entries a table with the emojis and the relative code to insert it in the entry instead of inserting the emoji directly, so something like this...:
1:🙏 2:😊 3:🔥 4:😃
...and have the user insert 1, 2, 3 or 4 instead of the emoji, but I don't think that this is a good way to solve the problem.
From my research, I understood that the problem is in the tkinter module and I was wondering if there was a way to overcome it.
# -*- coding: utf-8 -*-
from tkinter import *
def sumbit():
print(var.get())
root = Tk()
root.tk.call('encoding', 'system', 'utf-8')
var = StringVar()
entry = Entry(root, textvariable=var)
entry.pack()
button = Button(root, text="sumbit", command=sumbit)
button.pack()
root.mainloop()
This is an example of the problem, I have a window with an Entry widget where the user can insert an emoji, but if the user inserts an emoji, the code raises the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Users/mcara/PycharmProjects/1/python/1.py", line 5, in sumbit
print(var.get())
File "C:\Program Files\Python37-32\lib\tkinter\__init__.py", line 484, in get
value = self._tk.globalgetvar(self._name)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xed in position 0: invalid continuation byte
I'm working with Windows and Pyton 3.7
I have worked around this problem as this for now:
# -*- coding: utf-8 -*-
from tkinter import *
import tkinter.font as tkFont
# Dict with all the emojis
# it is made in this format --> EMOJI_NAME: EMOJI_SURROGATE_PAIR
emoji_dict = {
"GRINNING_FACE": '\ud83d\ude00',
"GRINNING_FACE_WITH_BIG_EYES": '\ud83d\ude03',
"GRINNING_FACE_WITH_SMILING_EYES": '\ud83d\ude04',
"BEAMING_FACE_WITH_SMILING_EYES": '\ud83d\ude01',
"GRINNING_SQUINTING_FACE": '\ud83d\ude06',
"GRINNING_FACE_WITH_SWEAT": '\ud83d\ude05',
"LAUGHING_ON_THE_FLOOR": '\ud83e\udd23',
"TEARS_OF_JOY": '\ud83d\ude02',
"SMILING_FACE_SLIGHTLY": '\ud83d\ude42',
"UPSIDE-DOWN_FACE": '\ud83d\ude43',
"WINKING_FACE": '\ud83d\ude09',
}
emoji_num_name = dict()
emoji_name_num = dict()
counter = 0
for key in emoji_dict:
emoji_num_name[counter] = key
emoji_name_num[key] = counter
counter += 1
def search(text):
for widget in emoji_frame.winfo_children():
if isinstance(widget, Button):
widget.destroy()
emoji_name_list = list(emoji_dict.keys())
emoji_name_list.sort()
if text == "" or text == " ":
creates_emojis()
else:
x = 10
y = 0
for emoji_name in emoji_name_list:
if emoji_name.startswith(text):
emoji_code = emoji_dict[emoji_name]
code_ = emoji_name_num[emoji_name]
emoji_button = Button(emoji_frame, text=emoji_code, borderwidth=0, font=customFont)
emoji_button.place(x=x, y=y)
emoji_button.bind("<Button-1>", lambda event, code=code_, var=sumbit_var: insert_emoji(var, ":-" + str(code) + "-:"))
if x <= 150:
x += 30
else:
x = 10
y += 30
emoji_frame.configure(widt=200, height=y+60)
def insert_emoji(var, code):
var.set(var.get() + code)
def creates_emojis():
x = 10
y = 0
for emoji_name in emoji_dict:
emoji_code = emoji_dict[emoji_name]
code_ = emoji_name_num[emoji_name]
emoji_button = Button(emoji_frame, text=emoji_code, borderwidth=0, font=customFont)
emoji_button.place(x=x, y=y)
emoji_button.bind("<Button-1>", lambda event, code=code_, var=sumbit_var: insert_emoji(var, ":-" + str(code) + "-:"))
if x <= 150:
x += 30
else:
x = 10
y += 30
emoji_frame.configure(widt=200, height=y+60)
def sumbit(text):
text = text.split(":-")
for index in range(len(text)):
word = text[index]
word = word.split("-:")
for index_ in range(len(word)):
little_word = word[index_]
if little_word.isdigit():
emoji_name = emoji_num_name[int(little_word)]
emoji = emoji_dict[emoji_name]
word[index_] = emoji
text[index] = "".join(word)
text = "".join(text)
text = text.encode('utf-16', 'surrogatepass').decode('utf-16')
print(text)
root = Tk()
root.tk.call('encoding', 'system', 'utf-8')
root.configure(width=500, height=500)
font = "Courier"
customFont = tkFont.Font(family=font, size=14)
emoji_frame = LabelFrame(text="emojis")
emoji_frame.place(x=10, y=60)
search_var = StringVar()
search_entry = Entry(root, textvariable=search_var)
search_entry.place(x=10, y=10)
search_button = Button(root, text="search", command=lambda: search(search_var.get().upper()))
search_button.place(x=10, y=30)
displat_all_button = Button(root, text="display all", command=lambda: creates_emojis())
displat_all_button.place(x=60, y=30)
sumbit_var = StringVar()
sumbit_entry = Entry(root, textvariable=sumbit_var)
sumbit_entry.place(x=200, y=10)
sumbit_button = Button(root, text="sumbit", command=lambda: sumbit(sumbit_var.get()))
sumbit_button.place(x=200, y=30)
creates_emojis()
root.mainloop()
This is a runnable example of what i made, I've created a kind of table where you can insert as many emojis as you want (by editing the emoji_dict and inserting the emoji that you want) and return an output in utf-8.
For find the emoji surrogate pair i've used the code
import re
_nonbmp = re.compile(r'[\U00010000-\U0010FFFF]')
def _surrogatepair(match):
char = match.group()
assert ord(char) > 0xffff
encoded = char.encode('utf-16-le')
return (
chr(int.from_bytes(encoded[:2], 'little')) +
chr(int.from_bytes(encoded[2:], 'little')))
def with_surrogates(text):
return _nonbmp.sub(_surrogatepair, text)
emoji_dict = {
"Grinning_Face": u'\ud83d\ude00',
"Grinning_Face_With_Big_Eyes": u'\ud83d\ude03',
"Grinning_Face_With_Smiling_Eyes": u'\ud83d\ude04',
"Beaming_Face_With_Smiling_Eyes": u'\ud83d\ude01',
"Grinning_Squinting_Face": u'\ud83d\ude06',
"Grinning_Face_With_Sweat": u'\ud83d\ude05',
"Laughing_on_the_Floor": u'\ud83e\udd23',
"Tears_of_Joy": u'\ud83d\ude02',
"Smiling_Face_Slightly": u'\ud83d\ude42',
"Upside-Down_Face": u'\ud83d\ude43',
"Winking_Face": u'\ud83d\ude09',
}
emoji_list =[ "😀", "😃", "😄", "😁", "😆", "😅", "🤣", "😂", "🙂", "🙃", "😉", ]
for emoji in emoji_list:
print(repr(_nonbmp.sub(_surrogatepair, emoji)))
you can found it at this question
Python: Find equivalent surrogate pair from non-BMP unicode char

Python GUI EntryButtons

I'm making a small GUI application that deals with grades and whatnot and outputs the highest grades and etc.
Here's a part of the code:
root = Tk()
gradeList = []
def addGradeObject(name, percentage):
gradeList.append(Grade(name, percentage))
updateOutput()
print(gradeList)
def undoAdd():
try:
gradeList.pop(len(gradeList) - 1)
updateOutput()
print(gradeList)
except Exception:
pass
def updateOutput():
highestGrade.setText(highest_grade(gradeList))
lowestGrade.setText(lowest_grade(gradeList))
numFailed.setText(num_failed(gradeList))
addButton = Button(text = "Add Grade", command = lambda: addGradeObject (entryA.get(), entryB.get())).grid(row = 1, column = 4)
undoButton = Button(text = "Undo", command = undoAdd).grid(row = 2, column = 4)
entryA = Entry()
entryA.grid(row = 1, column = 1)
entryB = Entry()
entryB.grid(row = 1, column = 2)
highestGrade = Entry()
highestGrade.grid(row = 2, column = 1)
lowestGrade = Entry()
lowestGrade.grid(row = 3, column = 1)
numFailed = Entry()
numFailed.grid(row = 4, column = 1)
root.title("Grade Checker")
root.mainloop()
The problem is I'm getting this error:
AttributeError: 'Entry' object has no attribute 'setText'
I don't understand. When you create an Entry box, doesn't the object of class "Entry" have an attribute/method that allows you to set text to it? I really don't know why it's not working
Entry methods can be found here. As far as I can tell, there is no setText method. There is however an insert method that you could use to set the text (though you might wand to delete the current text first).
def set_text(entry, text):
entry.delete(0, tkinter.END)
entry.insert(0 text)
Alternatively, you can hook the entry up to a StringVar and use it's .set() and .get() methods. e.g. (from the linked docs above):
v = StringVar()
e = Entry(master, textvariable=v)
e.pack()
v.set("a default value")
s = v.get()

TypeError: unorderable types: str() < int()

Need help with this error.
my code:
from tkinter import *
def shouldIEat():
if calories.get() < 1523 :
answer.set("Eat food as soon as possible")
elif calories.get() > 1828 :
answer.set("Stop eating")
else:
answer.set("You can eat something, but don't go over 1828")
window = Tk()
answer = StringVar()
calories = IntVar()
calories.set(0)
caloriesLabel = Label(window, text = "How many calories have you consumed?")
caloriesLabel.grid( row = 1)
calories = Entry(width = 10)
calories.grid (row = 1, column = 1)
eatButton = Button(window, text = "Should I eat?" , command=shouldIEat).grid( row = 2 , column = 1)
quitButton = Button(window, text = "Quit" , command=window.quit).grid( row = 2 , column = 2)
window.mainloop()
My error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1487, in __call__
return self.func(*args)
File "D:/My Documents/School/Scripting Lang/Project", line 8, in shouldIEat
if calories.get() < 1523 :
TypeError: unorderable types: str() < int()
Your code sets up calories as a Tkinter IntVar, but then it clobbers it by creating an Entry with the same name. You need to give the Entry a different name, and then attach the calories IntVar using the textvariable argument in the Entry constructor.
Also, you never created a widget to display the answer.
from tkinter import *
def shouldIEat():
if calories.get() < 1523 :
answer.set("Eat food as soon as possible")
elif calories.get() > 1828 :
answer.set("Stop eating")
else:
answer.set("You can eat something, but don't go over 1828")
window = Tk()
answer = StringVar()
calories = IntVar()
calories.set(0)
#answer.set('')
caloriesLabel = Label(window, text = "How many calories have you consumed?")
caloriesLabel.grid(row = 1, column = 0)
caloriesEntry = Entry(width = 10, textvariable=calories)
caloriesEntry.grid(row = 1, column = 1)
Button(window, text = "Should I eat?", command=shouldIEat).grid(row = 2, column = 1)
Button(window, text = "Quit" , command=window.quit).grid(row = 2, column = 2)
answerLabel = Label(window, textvariable=answer)
answerLabel.grid(row = 2, column = 0)
window.mainloop()
We don't really need to initialise answer, but it is neater to do so. And you could use it to display some simple instructions, if you want.
There's another minor problem with your code that I should mention.
eatButton = Button(window, text = "Should I eat?" , command=shouldIEat).grid( row = 2 , column = 1)
This creates a Button object and then calls its .grid() method. That's fine, but the .grid() method returns None, it does not return the Button object, so saving that return value to eatButton is pointless. You don't need to keep a reference to that button for this program, which is why I changed it to
Button(window, text = "Should I eat?", command=shouldIEat).grid(row = 2, column = 1)
in my version. But when you do need to keep a reference to the widget you should construct it on one line and then apply the .grid() (or .pack()) method on a separate line, like you did with caloriesLabel.
BTW, in Python, names of the form calories_label are preferred over caloriesLabel. See PEP-008 for further details.
As you can see in the TypeError, you are comparing a string with an integer.
Cast your string to an integer before doing your comparison.

Entries in Tkinter

I'd like to make a program which takes an integer from user and makes as many entries in a Tkinkter window. Then It'll make a graph base on them but for now I do not know how to make as many entries in my window. I tried something like this below but It does not work. Please help.. edit: oh and It's PyDev for Eclipse python 2.75
# -*- coding: utf-8 -*-
#import matplotlib.pyplot as mp
import Tkinter as T, sys
def end():
sys.exit()
def check():
z = e.get()
try:
z = int(z)
e.config(bg = 'green')
e.after(1000, lambda: e.config(bg = 'white'))
x = []
for i in (0,z):
x.append(e = T.Entry(main, justify = 'center'))
x[i].pack()
except:
e.config(bg = 'red')
e.after(1000, lambda: e.config(bg = 'white'))
z = 0
main = T.Tk()
main.title('something')
main.geometry('600x600')
main.config(bg = "#3366ff")
e = T.Entry(main,justify = 'center')
l = T.Label(main,text = 'Give me an N =',bg = '#3366ff')
b1 = T.Button(main, text = 'OK', command = check)
b = T.Button(main,text = 'Zakończ', command = end)
l.pack()
e.pack()
b1.pack()
b.pack()
main.mainloop()
Make youre for-loop look like this:
for i in range(0,z):
x.append( T.Entry(main, justify = 'center'))
x[i].pack()
you need to use range because when you dont it is only iterating through twice because it thinks its iterationg through a 2 item tuple instead of a list of numbers
also get rid of the e = so that it is just appending a new entry each time

Passing extra arguments with Tkinter Bindings

I'm trying to bind an extra argument opt to the following radiobuttons below. I'm trying to make it so that when WSRB_UD is triggered I can know which radiobutton triggered it. How do I go about this?
Snippet:
self.WS.SW.SearchFrame = []
self.WS.SW.SearchRB = []
self.WS.RBvar = Tkinter.IntVar()
i = 0
while i < 6 :
Frame = Tkinter.Frame(self.WS.SW.OptFrame, width=125, height=22, bd=1,
bg=self.WSbg)
Frame.grid(column=0, row=4 + i)
Frame.grid_propagate(0)
self.WS.SW.SearchFrame.append(Frame)
RB = Tkinter.Radiobutton(self.WS.SW.SearchFrame[i], value=i,
variable=self.WS.RBvar, indicatoron=0, font=self.WSfo,
fg=self.WSfg, activeforeground=self.WSfg, bg=self.WSbg, activebackground=self.WSbg,
selectcolor=self.WSbg, bd=self.WSbw)
RB.grid()
RB.bind( "<Enter>", self.WSRB_UD, i)
print i
self.WS.SW.SearchRB.append(RB)
i = i + 1
self.QuickLinkList= []
self.WS_timer_count = 0
def WSRB_UD(self, event, opt):
print self.WS.RBvar.get()
You can use lambda to define an anonymous partial function:
RB.bind( "<Enter>", lambda event: self.WSRB_UD(event, i) )
You could also use functools.partial if you don't like the lambda syntax.

Categories

Resources