Related
I'm making GUI the first time with tkinter(python), and I want to show the results in the same place, where they are at the beginning.
When I run this code the functions are fully working, but I cannot show the results in my label.
The button have to take data from Entries and give it to the function with data from drop-down list.
The results should overwrite the list as1, as2 = [0, 0] and then show the results on the label result_1, result_2
I've tried to add "master" parameter to the function - onclick, but then the GUI was running without clicking the button.
# coding=utf-8
from tkinter import *
def function_1(h, eta_bet):
print(h, eta_bet)
return h, eta_bet
def calculated_value_concrete(class_concrete): # could be 20/25
eta_bet = class_concrete
return eta_bet
class Menu:
def __init__(self, master):
container = Label(master, bg="#003366")
container.pack()
menu_bg = Label(container, bg="#003366", fg="white", pady=15)
countings_bg = Label(container)
self.button1 = Button(menu_bg, text="Zbrojenie symetryczne", command=lambda: self.onclick(1, countings_bg),
width=20)
menu_bg.pack(side=LEFT, fill=Y)
self.button1.pack()
def onclick(self, args, countings_bg):
if args == 1:
countings_bg.pack()
ZbrojenieSymetryczne(countings_bg)
class ZbrojenieSymetryczne:
def __init__(self, master):
self.desc_1 = Label(master, text="Wysokość przekroju h [cm]")
self.desc_7 = Label(master, text="Wybór betonu")
self.data_1 = Entry(master, width=6)
var = StringVar()
var.set("Klasa")
self.data_7 = OptionMenu(master, var, "1", "2", command=self.option_menu)
self.data_7.config(width=10)
self.desc_1.grid(row=1, sticky=E)
self.desc_7.grid(row=7, sticky=E)
self.data_1.grid(row=1, column=1)
self.data_7.grid(row=7, column=1, stick="ew")
self.button5 = Button(master, text="Count", command=self.onclick)
self.button5.grid(row=9, columnspan=2, pady=10)
as1, as2 = [0, 0]
self.result_1 = Label(master, text=f"A_s1 = {as1} [cm^2]")
self.result_1.grid(row=12, sticky=E)
self.result_2 = Label(master, text=f"A_s2 = {as2} [cm^2]")
self.result_2.grid(row=13, sticky=E)
def option_menu(self, selection):
self.eta_bet = calculated_value_concrete(selection)
print(self.eta_bet)
def onclick(self):
h = float(self.data_1.get().replace(',', '.')) * 10 ** -2
as1, as2 = function_1(h, self.eta_bet)
self.result_1 = Label(master, text=f"A_s1 = {as1} [cm^2]")
self.result_1.grid(row=12, sticky=E)
self.result_2 = Label(master, text=f"A_s2 = {as2} [cm^2]")
self.result_2.grid(row=13, sticky=E)
root = Tk()
root.title("Obliczanie zbrojenia")
Menu(root)
root.mainloop()
I want the results in the same label as it is in the beginning (under the button)
If you want to update the text of an existing label there are many ways to do this but perhaps consider doing this inside your onclick function rather than creating new buttons.
def onclick(self):
h = float(self.data_1.get().replace(',', '.')) * 10 ** -2
as1, as2 = function_1(h, self.eta_bet)
self.result_1['text'] = f"A_s1 = {as1} [cm^2]"
self.result_2['text'] = f"A_s2 = {as2} [cm^2]"
This should set the text of result_1 and result_2 as per the f-string.
The code I show hereunder has got some if statements which make different variables which all involve money. When I run the code I can select how many of any drink and if it is takeaway or not.
IF it iss takeaway it adds 5% to the cost and if there are more than 3 drinks it takes 10% off the invoice.
Could anyone help me add a +$ for the takeaway on the output area of gui and a -$ for the discount.
Any help would be appreciated.
If anyone wants to see the entire code, it is visible in this gist
import tkinter as tk
import time
import random
root = tk.Tk()
root.geometry("1600x8000")
root.title("Cafe au Lait")
tops = tk.Frame(root, width=1600, relief="sunken")
tops.pack(side="top")
f1 = tk.Frame(root, width=800, height=700, relief="sunken")
f1.pack(side="left")
latte = tk.DoubleVar()
double_expresso = tk.DoubleVar()
iced = tk.DoubleVar()
cost = tk.DoubleVar()
cappacuino = tk.DoubleVar()
expresso = tk.DoubleVar()
flat_white = tk.DoubleVar()
total = tk.DoubleVar()
takeaway_var = tk.StringVar()
rand = tk.IntVar()
discount = tk.DoubleVar()
takeaway = tk.DoubleVar()
def ref(even=None):
x=random.randint(10000,99999)
randomRef=str(x)
rand.set(randomRef)
global total, cost
if latte.get() == "":
col = 0
else:
col = latte.get()
if iced.get() == "":
coi = 0
else:
coi = iced.get()
if flat_white.get() == "":
cofw = 0
else:
cofw = flat_white.get()
if double_expresso.get() == "":
code = 0
else:
code = double_expresso.get()
if cappacuino.get() == "":
coc = 0
else:
coc = cappacuino.get()
if expresso.get() == "":
coe = 0
else:
coe = expresso.get()
costoflatte = col * 3.5
costoficed = coi * 2.5
costofflat_white = cofw * 3.75
costofdouble_expresso = code * 4.25
costofcappacuino = coc * 3.75
costofexpresso = coe * 3
total.set('{}'.format(cost.get() + costoflatte + costoficed + costofflat_white + costofdouble_expresso + costofcappacuino + costofexpresso))
cost.set('{}'.format(cost.get() + costoflatte + costoficed + costofflat_white + costofdouble_expresso + costofcappacuino + costofexpresso))
if txt_takeaway.get() in ['Yes', 'yes', 'y', 'Y']:
w = total.get()
takeaway.set(w * 0.05)
if txt_takeaway.get() in ['Yes', 'yes', 'y', 'Y']:
x = total.get()
total.set((x * 0.05) + x)
if (coc + col + coi + cofw + code + coe) >=3:
z = total.get()
discount.set(z * 0.1)
if (coc + col + coi + cofw + code + coe) >=3:
y = total.get()
total.set(y * 0.9)
The code above sets it all up so that the code below outputs corrdctly. It is needed to run. The first 2 buttons below are the ones that need the +$ and -$ added to.
lbl_takeaway= tk.Label(f1, font=('arial', 16, 'bold'),text="Takeaway",bd=16,anchor="w").grid(row=2, column=2)
txt_takeaway=tk.Entry(f1, font=('arial',16,'bold'),textvariable=takeaway,bd=10,insertwidth=4,bg="powder blue",justify='right')
txt_takeaway.grid(row=2,column=3)
lbl_discount= tk.Label(f1, font=('arial', 16, 'bold'),text="Discount",bd=16,anchor="w").grid(row=3, column=2)
txt_discount=tk.Entry(f1, font=('arial',16,'bold'),textvariable=discount,bd=10,insertwidth=4,bg="powder blue",justify='right')
txt_discount.grid(row=3,column=3)
tk.Label(f1, font=('arial', 16, 'bold'),text="Order Number",bd=16,anchor="w").grid(row=0, column=2)
txt_order=tk.Entry(f1, font=('arial',16,'bold'),textvariable=rand,bd=10,insertwidth=4,bg="powder blue",justify='right')
txt_order.grid(row=0,column=3)
tk.Label(f1, font=('arial', 16, 'bold'), text="Takeaway", bd=16, anchor="w").grid(row=6, column=0)
txt_takeaway = tk.Entry(f1, font=('arial',16,'bold'),textvariable=takeaway_var, bd=10, insertwidth=4, bg="powder blue", justify='right')
txt_takeaway.grid(row=6, column=1)
tk.Label(f1, font=('arial', 16, 'bold'), text="Cost of Order", bd=16, anchor="w").grid(row=1, column=2)
txt_cost = tk.Entry(f1, font=('arial',16,'bold'), textvariable=cost,bd=10, insertwidth=4, bg="powder blue", justify='right')
txt_cost.grid(row=1, column=3)
tk.Label(f1, font=('arial', 16, 'bold'), text="Total Cost", bd=16, anchor="w").grid(row=5, column=2)
txt_totalcost = tk.Entry(f1, font=('arial',16,'bold'), textvariable=total, bd=10, insertwidth=4, bg="powder blue", justify='right')
txt_totalcost.grid(row=5, column=3)
tk.Label(f1, font=('arial', 16, 'bold'),text="Latte",bd=16,anchor="w").grid(row=1, column=0)
txt_latte=tk.Entry(f1, font=('arial',16,'bold'),textvariable=latte,bd=10,insertwidth=4,bg="powder blue",justify='right')
txt_latte.grid(row=1,column=1)
btnTotal=tk.Button(f1,padx=16,pady=8,bd=16,fg="black",font=('arial',16,'bold'),width=10,text="Total",bg="powder blue",command=ref).grid(row=7,column=1)
root.bind("<Return>", ref)
root.mainloop()
You can insert a default value in the entry field; here is a little example that subclasses tk.Entry, that you can reuse in your own project:
import tkinter as tk
class EntryBoxWithNegativeDollarSign(tk.Entry):
def __init__(self, master, *args, **kwargs):
self.master = master
super().__init__(self.master, *args, **kwargs)
self.default = '-$'
self.insert(0, self.default)
self.pack()
def set_default(self):
self.delete('0',tk.END)
self.insert(0, self.default)
def get(self):
value = - float(super().get()[2:])
self.set_default()
print(value)
return value
root = tk.Tk()
app = tk.Frame(root)
app.pack()
entry = EntryBoxWithNegativeDollarSign(app)
tk.Button(app, text='get value', command=entry.get).pack()
root.mainloop()
I have already written a script, that should calculate an intersected point (xp, yp) based on different variables (xa, ya, xb, yb, xc, yc, xd, yd) and draw segments with points in coordinate system. Generaly it works, but there is one problem. I would like to show my result (xp, yp) in window Tkinter after clickig button "Oblicz", but after implement self.xp.set(XP) I get an error AttributeError: Entry instance has no attribute 'set'. What is wrong with it? How can I amend it?
from Tkinter import *
import matplotlib.pyplot as plt
import numpy as np
import itertools
class Calculator:
def __init__(self, master):
self.master = master
master.title("Przecinanie prostych")
vcmd = master.register(self.validate) # we have to wrap the command
self.entry = Entry(master, validate="key", validatecommand=(vcmd,
'%P'))
self.zamknij_button = Button(master,
text='Zamknij',command=master.quit)
#draw result**
self.rysuj_button = Button(master, text=' Rysuj ',
command=lambda:self.draw())
#show result**
self.oblicz_button = Button(master, text=' Oblicz ',
command=lambda:self.update())
# LAYOUT ONLY
self.xp = DoubleVar()
self.yp = DoubleVar()
self.xa_label = Label(master, text="XA")
self.xa_label.grid(row=0)
self.ya_label = Label(master, text="YA")
self.ya_label.grid(row=1)
self.xb_label = Label(master, text="XB")
self.xb_label.grid(row=2)
self.yb_label = Label(master, text="YB")
self.yb_label.grid(row=3)
self.xc_label = Label(master, text="XC")
self.xc_label.grid(row=4)
self.yc_label = Label(master, text="YC")
self.yc_label.grid(row=5)
self.xd_label = Label(master, text="XD")
self.xd_label.grid(row=6)
self.yd_label = Label(master, text="YD")
self.yd_label.grid(row=7)
self.e7_label = Label(master, text="XP")
self.e7_label.grid(row=9)
self.e7 = Entry(master, textvariable = self.xp)
self.e7.grid(row = 9, column = 1)
self.e8_label = Label(master, text="YP")
self.e8_label.grid(row=10)
self.e8 = Entry(master, textvariable = self.yp)
self.e8.grid(row = 10, column = 1)
self.zamknij_button.grid(row=11, column=1, sticky=W, pady=5)
self.oblicz_button.grid(row=8, column=1, sticky=W, pady=4)
self.rysuj_button.grid(row=11, column = 2, sticky=W, pady=4)
self.xa = Entry(master)
self.ya = Entry(master)
self.xb = Entry(master)
self.yb = Entry(master)
self.xc = Entry(master)
self.yc = Entry(master)
self.xd = Entry(master)
self.yd = Entry(master)
self.xp = Entry(master)
self.yp = Entry(master)
self.xa.grid(row=0, column=1)
self.ya.grid(row=1, column=1)
self.xb.grid(row=2, column=1)
self.yb.grid(row=3, column=1)
self.xc.grid(row=4, column=1)
self.yc.grid(row=5, column=1)
self.xd.grid(row=6, column=1)
self.yd.grid(row=7, column=1)
self.xp.grid(row=9, column=1)
self.yp.grid(row=10, column=1)
self.xa.insert(10, 0)
self.ya.insert(10, 0)
self.xb.insert(10, 10)
self.yb.insert(10, 10)
self.xc.insert(10, 0)
self.yc.insert(10, 10)
self.xd.insert(10, 10)
self.yd.insert(10, 0)
def validate(self, new_text):
if not new_text: # the field is being cleared
self.xp.set(0)
return True
try:
self.xp.set(int(new_text))
return True
except ValueError:
return False
def update(self):
xa = float(self.xa.get())
ya = float(self.ya.get())
xb = float(self.xb.get())
yb = float(self.yb.get())
xc = float(self.xc.get())
yc = float(self.yc.get())
xd = float(self.xd.get())
yd = float(self.yd.get())
dXAB = xb - xa
dXCD = xd - xc
dXAC = xc - xa
dYAB = yb - ya
dYCD = yd - yc
dYAC = yc - ya
mian = dXAB * dYCD - dYAB * dXCD
t1 = (dXAC * dYCD - dYAC * dXCD) / mian
if mian == 0:
raise Exception('Brak przeciec')
XP = xa + t1 * dXAB
self.xp.set(XP)
print XP
YP = ya + t1 * dYAB
self.yp.set(YP)
print YP
def draw(self):
xa = float(self.xa.get())
ya = float(self.ya.get())
xb = float(self.xb.get())
yb = float(self.yb.get())
xc = float(self.xc.get())
yc = float(self.yc.get())
xd = float(self.xd.get())
yd = float(self.yd.get())
fig = plt.figure()
ax = fig.add_subplot(111)
plt.axis([-2, xd + 2, -2, yb + 2])
t1 = [[xa, ya], [xb, yb]]
t2 = [[xc, yc], [xd, yd]]
plt.plot(
*zip(*itertools.chain.from_iterable(itertools.combinations(t1, 2))),
color='blue', marker='o')
plt.plot(
*zip(*itertools.chain.from_iterable(itertools.combinations(t2, 2))),
color='green', marker='o')
ax.annotate('A', xy=(xa, ya), xytext=(xa-0.7, ya), fontsize=18)
ax.annotate('B', xy=(xb, yb), xytext=(xb - 0.7, yb), fontsize=18)
ax.annotate('C', xy=(xc, yc), xytext=(xc - 0.7, yc), fontsize=18)
ax.annotate('D', xy=(xd, yd), xytext=(xd + 0.3, yd), fontsize=18)
plt.show()
root = Tk()
my_gui = Calculator(root)
root.mainloop()
The problem appears to be that you are initially creating self.xp and self.yp as DoubleVar objects:
self.xp = DoubleVar()
self.yp = DoubleVar()
However, you later replace them with Entry widgets:
self.xp = Entry(master)
self.yp = Entry(master)
What you probably wanted to do was to create separate objects for the Entry widgets, and wire them up to self.xp and self.yp, by replacing the last two lines above with the following:
self.xp_entry = Entry(master, textvariable=self.xp)
self.yp_entry = Entry(master, textvariable=self.yp)
You would also need to replace the calls to self.xp.grid and self.yp.grid with the equivalent calls on self.xp_entry.grid and self.yp_entry.grid, i.e.:
self.xp_entry.grid(row=9, column=1)
self.yp_entry.grid(row=10, column=1)
Once I had made these changes to your code it appeared to work, in that I could click the 'Oblicz' button and it would do some calculations and change the value of the XP and YP text fields instead of raising an exception.
I have this code and basically what I want to do is I want that on pressing the button the balance at the button is updated with the amount. If the balance is currently 15, and I add 10, I want it to add 10 to it.
from tkinter import *
def bal():
ans = int (input1.get ())
total = IntVar ()
tot = int (total.get ())
tot = tot + ans
res.set(tot+ans)
root = Tk()
root.geometry("1280x720")
upper = Frame(root)
upper.pack()
Label(upper, text ="Sum:", font = ('raleway', 15), ).grid(row=0, column = 0)
Label(root, text ="Balance:", font = ('raleway', 15)).place(rely=1.0, relx=0, x=0, y=0, anchor=SW)
res = StringVar()
input1 = Entry(upper)
num2 = Entry(root)
result = Label(root, textvariable = res,font = ('raleway',13))
result.place(rely=1.0, relx=0, x=80, y=-2, anchor=SW)
input1.grid(row=0,column=2)
Button(upper, text ="Add Funds", command = bal).grid(row=4, column=2, ipadx = 65)
mainloop()
root.mainloop()
I tried to have a total that constantly updates in the function bal but it doesn't update for some reason. I am a python beginner, by the way :D
Thanks for your help!
In the bal() command function, all you need to do is retrieve the current input value and running total (balance), add them together, and then update the running total:
from tkinter import *
def bal():
ans = input1.get()
ans = int(ans) if ans else 0
tot = int(res.get())
tot = tot + ans
res.set(tot)
root = Tk()
root.geometry("1280x720")
upper = Frame(root)
upper.pack()
Label(upper, text="Sum:", font=('raleway', 15)).grid(row=0, column=0)
Label(root, text="Balance:", font=('raleway', 15)).place(rely=1.0, relx=0,
x=0, y=0, anchor=SW)
res = StringVar()
res.set(0) # initialize to zero
input1 = Entry(upper)
result = Label(root, textvariable=res, font=('raleway', 13))
result.place(rely=1.0, relx=0, x=80, y=-2, anchor=SW)
input1.grid(row=0,column=2)
Button(upper, text="Add Funds", command=bal).grid(row=4, column=2, ipadx=65)
root.mainloop()
You created a new IntVar and you are using .get on this. Instead you want to be use get on num2 to get the current number that is stored in there adding the input to this and updating the var.
from tkinter import *
window = Tk()
ia_answers= "trolol"
input_frame = LabelFrame(window, text="User :", borderwidth=4)
input_frame.pack(fill=BOTH, side=BOTTOM)
input_user = StringVar()
input_field = Entry(input_frame, text=input_user)
input_field.pack(fill=BOTH, side=BOTTOM)
ia_frame = LabelFrame(window, text="Discussion",borderwidth = 15, height = 100, width = 100)
ia_frame.pack(fill=BOTH, side=TOP)
user_says = StringVar()
user_text = Label(ia_frame, textvariable=user_says, anchor = NE, justify = RIGHT, bg="white")
user_text.pack(fill=BOTH, side=TOP)
ia_says = StringVar()
ia_text = Label(ia_frame, textvariable=ia_says, anchor = W, justify = LEFT, bg="white")
ia_text.pack(fill=BOTH, side=BOTTOM)
def Enter_pressed(event):
"""Took the current string in the Entry field."""
input_get = input_field.get()
input_user.set("")
user_says.set(input_get + "\n\n")
ia_says.set(ia_answers)
input_field.bind("<Return>", Enter_pressed)
window.mainloop()
Hi, i am trying to build a discussion Bot.
When I execute the code, the question in the input field and the answer get displayed correctly.
The problem is after entering the next sentence, the previous question/answer gets removed. Here is an example:
Hello Bot
Hello User
(then the text disappears)
How are you
Fine thank you
What i want :
Hello Bot
Hello User
(then the text stays in the frame)
How are you
Fine thank you
The issue occurs in line -
user_says.set(input_get + "\n\n")
ia_says.set(ia_answers)
You are replace users_says.set() and ia_says.set() resets the complete Labels , with the new value. Instead you should get the old value and append the new value to it and set it back, Example -
user_says.set(user_says.get() + input_get + "\n")
ia_says.set(ia_says.get() + ia_answers + "\n")
Or you can also create a new label for each new event and add it to the LabelFrame . Example -
from tkinter import *
window = Tk()
ia_answers= "trolol\n"
input_frame = LabelFrame(window, text="User :", borderwidth=4)
input_frame.pack(fill=BOTH, side=BOTTOM)
input_user = StringVar()
input_field = Entry(input_frame, text=input_user)
input_field.pack(fill=BOTH, side=BOTTOM)
ia_frame = LabelFrame(window, text="Discussion",borderwidth = 15, height = 100, width = 100)
ia_frame.pack(fill=BOTH, side=TOP)
user_says = StringVar()
user_text = Label(ia_frame, textvariable=user_says, anchor = NE, justify = RIGHT,
bg="white")
user_text.pack(fill=X)
ia_says = StringVar()
ia_text = Label(ia_frame, textvariable=ia_says, anchor = NW, justify = LEFT, bg="white")
ia_text.pack(fill=X)
user_texts = []
ia_texts = []
user_says_list = []
ia_says_list = []
def Enter_pressed(event):
"""Took the current string in the Entry field."""
input_get = input_field.get()
input_user.set("")
user_says1 = StringVar()
user_says1.set(input_get + "\n")
user_text1 = Label(ia_frame, textvariable=user_says1, anchor = NE, justify = RIGHT,
bg="white")
user_text1.pack(fill=X)
user_texts.append(user_text1)
user_says_list.append(user_says1)
ia_says1 = StringVar()
ia_says1.set(ia_answers)
ia_text1 = Label(ia_frame, textvariable=ia_says1, anchor = NW, justify = LEFT,
bg="white")
ia_text1.pack(fill=X)
ia_texts.append(ia_text1)
ia_says_list.append(ia_says1)
input_field.bind("<Return>", Enter_pressed)
window.mainloop()