I don't know what's wrong with the program - python

variable "code" doesn't change (str) when i check and if i put checkbox() above codeget() there will be no checkbox
how to fix there is code
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import *
#Window
window = Tk()
window.title("Register") #set window title
window.geometry('900x500')
code = 'None'
def codeget():
if (var1.get() == 1) and (var2.get() == 0):
code = 'Python'
elif (var1.get() == 0) and (var2.get() == 1):
code = 'C++'
elif (var1.get() == 0) and (var2.get() == 0):
code = 'None'
else:
code = 'Both'
var1 = IntVar()
var2 = IntVar()
c1 = Checkbutton(window, text='Python',variable=var1, onvalue=1, offvalue=0, command=codeget)
c1.place(x=650,y=120)
c2 = Checkbutton(window, text='C++',variable=var2, onvalue=1, offvalue=0, command=codeget)
c2.place(x=720,y=120)
def luu():
s=open("saveaccount", 'a+')
accountin4 = '\n' + 'Code: ' + code
s.write(accountin4)
message = Button(window,text = "Register", command = luu)
message.place(x = 500, y = 370)
mainloop()
if and else may not be related to my question so you can ignore it, even if I use = to assign " " to the code, the result will still be "None"

codeget() creates local variable code. You have to add global code inside this function to inform function that it has to assign value to global variable code instead of creating local variable code.
Minimal working code with small other changes.
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import messagebox
import tkinter.ttk as ttk
# --- functions --- # PEP8: all functions before main code
def get_code(): # PEP8: `lower_case_names` for functions and variables
global code # inform function to assign to global variable `code` instead of creating local variable `code`
if var1.get() == 0 and var2.get() == 0:
code = 'None'
elif var1.get() == 1 and var2.get() == 0:
code = 'Python'
elif var1.get() == 0 and var2.get() == 1:
code = 'C++'
else:
code = 'Both'
def register(): # PEP8: readable name
s = open("saveaccount", 'a+')
text = '\n' + 'Code: ' + code
s.write(text)
s.close() # better close file because system may keep data in buffer in RAM and write data when you close file
print(text)
# --- main ---
code = 'None' # it is global variable
window = tk.Tk()
var1 = tk.IntVar()
var2 = tk.IntVar()
c1 = tk.Checkbutton(window, text='Python', variable=var1, onvalue=1, offvalue=0, command=get_code)
c1.pack()
c2 = tk.Checkbutton(window, text='C++', variable=var2, onvalue=1, offvalue=0, command=get_code)
c2.pack()
message = tk.Button(window, text="Register", command=register)
message.pack()
window.mainloop()
PEP 8 -- Style Guide for Python Code
EDIT:
If you want to use more checkbuttons then you could use for-loop to create them, and StringVar to use string onvalue="Python" instead of integers 0/1
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import messagebox
import tkinter.ttk as ttk
# --- functions --- # PEP8: all functions before main code
def get_code():
global code # inform function to assign to global variable `code` instead of creating local variable `code`
selected = []
for v in string_vars:
if v.get():
selected.append(v.get())
if not selected:
code = 'None'
else:
code = ','.join(selected)
def register():
s = open("saveaccount", 'a+')
text = '\n' + 'Code: ' + code
print(text)
s.write(text)
s.close()
# --- main ---
code = 'None' # it is global variable
window = tk.Tk()
string_vars = []
for item in ['Python', 'C++', 'Java', 'PHP', 'Rust', 'Go']:
v = tk.StringVar(window)
c = tk.Checkbutton(window, text=item, variable=v, onvalue=item, offvalue='', command=get_code)
c.pack()
string_vars.append(v)
message = tk.Button(window, text="Register", command=register)
message.pack()
window.mainloop()

Related

Why exec function in python adds '.!' at the beginning of the text?

I am currently working on a hangman game using tkinter in python.
When I click a button of the letter and it is in the word that we are guessing it should show the letter. But when I click the button this problem is popping up:
This example is only with one button. People say that this problem is because of the mainloop(), but i have no idea how to fix it.
from tkinter import *
from tkinter import messagebox
from generate_word import word
#DEFAULT VALUES
score = 0
count = 0
win_count = 2
WINDOW_BG = '#e5404e'
WINDOW_SIZE = '1200x870+300+80'
FONT = ('Arial', 40)
from tkinter import *
from tkinter import messagebox
from generate_word import word
#DEFAULT VALUES
score = 0
count = 0
win_count = 2
WINDOW_BG = '#e5404e'
WINDOW_SIZE = '1200x870+300+80'
FONT = ('Arial', 40)
#this is an example with only one button
buttons = [['b1','a',80,740]]
#Creating window and configurating it
window = Tk()
window.geometry(WINDOW_SIZE)
window.title('Hangman')
window.config(bg = WINDOW_BG)
#generates all of the labels for the word
def gen_labels_word():
label = Label(window, text = " ", bg = WINDOW_BG, font = FONT)
label.pack( padx = 40,pady = (500,100),side = LEFT)
label1 = Label(window, text = word[0], bg = WINDOW_BG, font = FONT)
label1.pack( padx = 41,pady = (500,100),side = LEFT)
x = 21
for var in range(1,len(word)):
exec('label{}=Label(window,text="_",bg=WINDOW_BG,font=FONT)'.format(var))
exec('label{}.pack(padx = {}, pady = (500,100), side=LEFT)'.format(var,x))
x += 1
exec('label{} = Label(window, text = "{}", bg = WINDOW_BG, font = FONT)'.format(len(word),word[-1]))
exec('label{}.pack( padx = {},pady = (500,100),side = LEFT)'.format(len(word), x+1))
# ---------------------------------------------------------------------------------------------------------------------------------------------------
gen_labels_word()
#----------------------------------------------------------------------------------------------------------------------------------------------------
#letters icons(images)
#hangman (images)
hangman = ['h0','h1','h2','h3','h4','h5','h6']
for var in hangman:
exec(f'{var}=PhotoImage(file="{var}.png")')
han = [['label0','h0'],['label1','h1'],['label2','h2'],['label3','h3'],['label4','h4'],['label5','h5'],['label6','h6']]
for p1 in han:
exec('{}=Label(window, bg = WINDOW_BG ,image={})'.format(p1[0],p1[1]))
exec('label0.place(x = 620,y = 0)')
for var in letters:
exec(f'{var}=PhotoImage(file="{var}.png")')
for var in buttons:
exec(f'{var[0]}=Button(window,bd=0,command=lambda: game_brain("{var[0]}","{var[1]}"),bg = WINDOW_BG,font=FONT,image={var[1]})')
exec('{}.place(x={},y={})'.format(var[0],var[2],var[3]))
def game_brain(button, letter):
global count,win_count,score
exec('{}.destroy()'.format(button))
if letter in word:
for i in range(1,len(word)):
if word[i] == letter:
win_count += 1
exec(f'label{i}.config(text="{letter}")')
if win_count == len(word):
score += 1
messagebox.showinfo('GOOD JOB, YOU WON!\n GOODBYE!')
window.destroy()
else:
count += 1
exec('label{}.destroy()'.format(count-1))
exec('label{}.place(x={},y={})'.format(count,620,0))
if count == 6:
messagebox.showinfo('GAME OVER','YOU LOST!\nGOODBYE!')
window.destroy()
def EXIT():
answer = messagebox.askyesno('ALERT','Do you want to exit the game?')
if answer == True:
window.destroy()
e1 = PhotoImage(file = 'exit.png')
ex = Button(window,bd = 0,command = EXIT,bg = WINDOW_BG,font = FONT,image = e1)
ex.place(x=1050,y=20)
#-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
window.mainloop()
Why exec function in python adds '.!' at the beginning of the text?
The exec function isn't doing that. Tkinter by default names all of its widgets with a leading exclamation point. When you print out a widget, it has to be converted to a string. For tkinter widgets, the result of str(some_widget) is the widget's name.
You can see this quite easily without exec:
import tkinter as tk
root = tk.Tk()
label = tk.Label(root)
print(label)
The above will print something like .!label. If you create a second label it will be .!label2, a third will be .!label3 and so on.
On an unrelated note, you shouldn't be using exec to create widgets. It makes the code very hard to understand and debug. If you want to create widgets in a loop, add them to a dictionary or list instead of dynamically creating variables with exec.
For example:
labels = {}
for var in range(1,len(word)):
label = Label(window,text="_",bg=WINDOW_BG,font=FONT)
label.pack(padx=500, pady=100)
labels[var] = label
With that, you can later reference the widgets as labels[1], labels[2], etc.
You should do the same thing with the images, or anything else that you create in a loop and want to keep track of.

I'm unable to get a string out of tkinter entrybox

import random
import tkinter as tk
frame = tk.Tk()
frame.title("koeweils baldadige encyptor")
frame.geometry('400x200')
printButton = tk.Button(frame,text = "Print", command = lambda: zandkasteel())
printButton.pack()
freek = tk.Text(frame,height = 5, width = 20)
freek.pack()
input_a = freek.get(1.0, "end-1c")
print(input_a)
fruit = 0
fad = input_a[fruit:fruit+1]
print(fad)
schepje = len(input_a.strip("\n"))
print(schepje)
def zandkasteel():
lbl.config(text = "Ingevulde string: "+input_a)
with open("luchtballon.txt", "w") as chocoladeletter:
for i in range(schepje):
n = random.randint()
print(n)
leuk_woord = ord(fad)*n
print(leuk_woord)
chocoladeletter.write(str(leuk_woord))
chocoladeletter.write(str(n))
chocoladeletter.write('\n')
lbl = tk.Label(frame, text = "")
lbl.pack()
frame.mainloop()
I need to get the string that was entered into the text entry field freek. I have tried to assign that string to input_a, but the string doesn't show up.
Right now, input_a doesn't get anything assigned to it and seems to stay blank. I had the same function working before implementing a GUI, so the problem shouldn't lie with the def zandkasteel.
To be honest I really don't know what to try at this point, if you happen to have any insights, please do share and help out this newbie programmer in need.
Here are some simple modifications to your code that shows how to get the string in the Text widget when it's needed — specifically when the zandkasteel() function gets called in response to the user clicking on the Print button.
import random
import tkinter as tk
frame = tk.Tk()
frame.title("koeweils baldadige encyptor")
frame.geometry('400x200')
printButton = tk.Button(frame, text="Print", command=lambda: zandkasteel())
printButton.pack()
freek = tk.Text(frame, height=5, width=20)
freek.pack()
def zandkasteel():
input_a = freek.get(1.0, "end-1c")
print(f'{input_a=}')
fruit = 0
fad = input_a[fruit:fruit+1]
print(f'{fad=}')
schepje = len(input_a.strip("\n"))
print(f'{schepje=}')
lbl.config(text="Ingevulde string: " + input_a)
with open("luchtballon.txt", "w") as chocoladeletter:
for i in range(schepje):
n = random.randint(1, 3)
print(n)
leuk_woord = ord(fad)*n
print(leuk_woord)
chocoladeletter.write(str(leuk_woord))
chocoladeletter.write(str(n))
chocoladeletter.write('\n')
lbl = tk.Label(frame, text="")
lbl.pack()
frame.mainloop()

"name is not defined" inside function inside condition

When I run the code below, and press the 'go' button, I get the error:
NameError: name 'be' is not defined
...on the following line in the countdown function:
if be >= 0:
Even if I add global be in the function countdown, I get the same error.
import tkinter as tk
def set1():
global be
if be1 is not '':
be = int(en.get())
def countdown():
global be
if be >= 0:
mins, secs = divmod(be, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
label['text'] = timer
root.after(1000, countdown)
be -= 1
root = tk.Tk()
label = tk.Label(root, text = '00:00', font = 'Helvetica 25')
label.pack()
en = tk.Entry(root)
en.pack()
be1 = en.get()
tk.Button(root, text = 'set', height = 3, width = 20, command = lambda: set1()).pack()
tk.Button(root, text = 'go', height = 3, width = 20, command = lambda: countdown()).pack()
root.mainloop()
Why doesn't global be resolve the problem?
The reason is clear from the error message: you need to define be as a global variable. Note that the global statement does not define the variable, it merely links the local references to that name with an existing global variable. But if it doesn't exist, there is nothing to match it with.
So you should define be as a global variable, like:
be = 0
There are a few other issues and things to improve:
be1 is read from the input only once, when the script starts, not when the user clicks a button. So its value will always remain the empty string. Instead, you should read the input into be1 when the "set" button is clicked, and so the variable be1 can just be a local variable in that set1 function, not global as it is now.
Don't use is not (or is) when comparing a variable with a string literal. So you should have:
if be1 != '':
It is better to already display the updated start-time when the user clicks the "set" button, even before the user clicks "go" -- otherwise they don't see the effect of clicking "set".
Since you already have code for displaying the timer in the countdown function, it would be good to avoid code duplication and make a new function just for doing the displaying.
So taking all that together you would get:
import tkinter as tk
be = 0 # define as global here
def display(): # new function to avoid code repetition
global be
mins, secs = divmod(be, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
label['text'] = timer
def set1():
global be
be1 = en.get() # local variable, reading fresh input value
if be1 != '': # don't use "is not" with a literal
be = int(be1)
display()
def countdown():
global be
if be >= 0:
display()
root.after(1000, countdown)
be -= 1
root = tk.Tk()
label = tk.Label(root, text = '00:00', font = 'Helvetica 25')
label.pack()
en = tk.Entry(root)
en.pack()
tk.Button(root, text = 'set', height = 3, width = 20, command = lambda: set1()).pack()
tk.Button(root, text = 'go', height = 3, width = 20, command = lambda: countdown()).pack()
root.mainloop()

My variable will not change in function

My variable is not changing and I know it's not changing because "1" is printed to the console.
I'm trying to make the label increment when i press the button. However when I press the button, the variable stays at 1.
What am I doing wrong?
I've looked online for an answer but I cannot really find one that I can understand.
num = 0
import tkinter
box = tkinter.Tk()
v = tkinter.StringVar()
labels = tkinter.Label(box, textvariable = v)
labels.pack()
def numberz(num,v):
num += 1
v.set(num)
print(num)
class MainWindow():
box.title("My Stupid Program")
buddon = tkinter.Button(box, text='PRESS ME', command = lambda:numberz(num,v))
buddon.pack()
box.mainloop()
num = 0
import tkinter
box = tkinter.Tk()
v = tkinter.StringVar()
labels = tkinter.Label(box, textvariable = v)
labels.pack()
def numberz(num,v):
num += 1
v.set(num)
print(num)
class MainWindow():
box.title("My Stupid Program")
buddon = tkinter.Button(box, text='PRESS ME', command = lambda:numberz(num,v))
buddon.pack()
box.mainloop()
You are changing the parameter num and not the global variable num
To change the global you need to specifically reference it. Notice how num is not passed in the lambda and now there is a global num in you function.
num = 0
import tkinter
box = tkinter.Tk()
v = tkinter.StringVar()
labels = tkinter.Label(box, textvariable = v)
labels.pack()
def numberz(v):
global num
num += 1
v.set(num)
print(num)
class MainWindow():
box.title("My Stupid Program")
buddon = tkinter.Button(box, text='PRESS ME', command = lambda:numberz(v))
buddon.pack()
box.mainloop()
In any case, using globals should be restricted to very specific cases and not be of general use.

StringVar DoubleVar and others

I am very new on Python and I have a problem.
I try to read my temperature sensor and set the Value in to my Tkinter GUI.
I don't know how to update my label LT with the new value if I update it with my Button B1.
I have tried everything from StringVar to get() and this stuff.
I hope you can help me to find my failure.
Here is my code:
from tkinter import *
import os
Main = Tk()
Main.title("Hauptmenü")
Main.geometry("500x400")
class Fenster():
def Credit():
messagebox.showinfo(title="Credits",message="created by T.N v0.1")
return
def Beenden():
pExit = messagebox.askyesno(title="Beenden",message="Möchten Sie\n wirklich beenden?")
if pExit > 0:
Main.destroy()
return
def auslesen(event):
file = open("/sys/bus/w1/devices/28-041635ad4cff/w1_slave")
inhalt = file.read()
trennwoerter = inhalt.split(" ")
Wert = (trennwoerter[20])
Temp = (Wert[2:4])
file.close()
labelauslesen = Label(Main,text="Aktuelle Temperatur :")
labelauslesen.pack()
LT = Label(Main,text=Inhalt)
LT.pack()
B1 = Button(Main,text="Temperatur auslesen")
B1.pack()
B1.bind("<Button-1>",auslesen)
menubar=Menu(Main)
filemenu = Menu(menubar)
filemenu.add_command(label="Sensoren auslesen")
filemenu.add_command(label="Diagram anzeigen")
filemenu.add_command(label="Credits",command = Credit)
filemenu.add_command(label="Beenden",command = Beenden)
menubar.add_cascade(label="Datei",menu=filemenu)
Main.config(menu=menubar)
mainloop()
A minimal example that you can adapt to your code.
import tkinter as tk
root=tk.Tk()
temp = 10.0
def update_temp():
global temp
temp += 1.3
tlabel['text'] = '%s degrees C' % round(temp, 1)
tlabel = tk.Label(root, text='unknown')
tbutton = tk.Button(root, text='new temp', command=update_temp)
tlabel.pack()
tbutton.pack()
root.mainloop()

Categories