I have the following block of code.
class ChooseBook():
bookprice=2
def getqty(self, sv):
if self.txtbookqty.get()=="":
self.qty=0
else:
self.qty=int(self.sv.get())
self.txtbookprice.delete(0,END)
#print(self.qty)
self.txtbookprice.insert(0,self.qty*self.bookprice)
def on_CPOname_change(self,value,op,op2):
stname=self.comboBookname.get()
name=stname[1:-1]
book_data=Fun_Select("SELECT book_price FROM book_record WHERE book_name='"+name+"'")
#print(book_data)
self.bookprice=int(book_data[0][0])
def on_date_change(self,day):
if self.txtdaysborrowed.get()=="":
self.dayadd=0
else:
self.dayadd=int(self.day.get())
date=self.txtborrowdate.get()
self.dayindate=int(date[8:10])
self.yearindate=int(date[0:4])
self.monthindate=int(date[5:7])
if self.dayindate+self.dayadd > 31:
self.monthindate=self.monthindate+1
if self.monthindate > 12:
self.yearindate+=1
self.txtrd.insert(0,self.dayindate+'-'+self.monthindate+'-'+self.yearindate)
def __init__(self):
today_date=datetime.date.today()
win=Tk()
win.title("Choose book type")
win.geometry("600x800")
v=StringVar()
d=StringVar()
v.trace('w', self.on_CPOname_change)
self.day=StringVar()
self.day.trace('w',lambda name, index, mode, day=self.day: self.on_date_change(day))
self.sv = StringVar()
self.sv.trace("w", lambda name, index, mode, sv=self.sv: self.getqty(sv))
Label(win,text="Choose Book Name").grid(row=0,column=0,padx="1.5c",pady="1c")
Label(win,text="Enter Book Quantity").grid(row=1,column=0,padx="1.5c",pady="1c")
Label(win,text="Total Book Price").grid(row=2,column=0,padx="1.5c",pady="1c")
Label(win,text="Borrowed Date").grid(row=3,column=0,padx="1.5c",pady="1c")
Label(win,text="Days borrowed").grid(row=4,column=0,padx="1.5c",pady="1c")
Label(win,text="Return Date").grid(row=5,column=0,padx="1.5c",pady="1c")
Label(win,text="Choose Employee Name").grid(row=6,column=0,padx="1.5c",pady="1c")
Label(win,text="Choose Customer Name").grid(row=7,column=0,padx="1.5c",pady="1c")
#bookname
self.comboBookname=ttk.Combobox(win, textvar=v)
self.comboBookname["values"]=Fun_Select("SELECT book_name FROM book_record")
self.comboBookname.grid(row=0,column=1,pady="1c")
#bookqty
self.txtbookqty=Entry(win,textvariable=self.sv)
self.txtbookqty.grid(row=1,column=1,pady="1c")
#bookprice
self.txtbookprice=Entry(win)
self.txtbookprice.grid(row=2,column=1,pady="1c")
#borrowdate
self.txtborrowdate=Entry(win,textvariable=d,state=DISABLED)
d.set(today_date)
self.txtborrowdate.grid(row=3,column=1,pady="1c")
#daysborrowed
self.txtdaysborrowed=Entry(win,textvariable=self.day)
self.day.set(0)
self.txtdaysborrowed.grid(row=4,column=1,pady="1c")
#returndate
self.txtrd=Entry(win)
self.txtrd.grid(row=5,column=1,pady="1c")
#employeename
self.comboEmployeename=ttk.Combobox(win)
self.comboEmployeename["values"]=Fun_Select("SELECT employee_name FROM employees")
self.comboEmployeename.grid(row=6,column=1,pady="1c")
#customername
self.comboCustomername=ttk.Combobox(win)
self.comboCustomername["values"]=Fun_Select("SELECT customer_name FROM customers")
self.comboCustomername.grid(row=7,column=1,pady="1c")
Button(win,text="Exit",width=10,command=win.destroy).grid(row=8,column=0,padx="1.5c",pady="1c")
Button(win,text="Save",width=10,command=None).grid(row=8,column=1,padx="1.5c",pady="1c")
win.mainloop()
ChooseBook()
But I get always error which says: AttributeError: 'ChooseBook' object has no attribute 'txtrd'. It seems that problem is somewhere at self.txtrd.insert(0,self.dayindate+'-'+self.monthindate+'-'+self.yearindate)
Also i'm quite new so my code might be very messy.
Here is a quick fix to THIS problem, just move the declaration of self.txtrd above self.day.set(0).
def __init__(self):
....#same bunch of code
self.txtrd=Entry(win)
self.txtrd.grid(row=5,column=1,pady="1c")
....#same bunch of code
self.day.set(0)
....#same bunch of code
You are using trace with self.day which means whenever you change the value of StringVar() it triggers the function, and later in code you are saying self.day.set(0)(value changing) so the trace becomes active and the function is called, before the self.txtrd is defined and hence the error.
Though after solving this error you will get a ValueError at:
self.txtrd.insert(0,self.dayindate+'-'+self.monthindate+'-'+self.yearindate)
To fix that do simple type casting like:
self.txtrd.insert(0,str(self.dayindate)+'-'+str(self.monthindate)+'-'+str(self.yearindate))
Though I highly doubt if you might get another error(unexpected behavior) over setting the values for the Combobox, anyway that can be asked as a new post, as one post should only focus around one problem.
Related
I'm trying to create a GUI, in the nav menu you can click a cascade option to open another window where you can click roll to generate a set of numbers. It comes up with error. I think it's because the function is called from another function I just don't know how to get that function to call it/ if there is any other ways to fix this. I've tried global functions and looking it up but haven't found anything other than using classes so far, which I don't know how to do.
line 147, in totalRolls
txtresultsOut.set(totalRollResults)
NameError: name 'txtresultsOut' is not defined
Here is the code that is relevant to it. I've called the function to skip having to input all the other code for the main gui window.
def rollSix():
s = 0
numbers = [0,0,0,0]
for i in range(1,5):
numbers[s] = randrange(1,7)
s += 1
numbers.remove(min(numbers))
Result = sum(numbers)
totalRollResults.append(Result)
def totalRolls():
rollOne()
rollTwo()
rollThree()
rollFour()
rollFive()
rollSix()
txtresultsOut.set(totalRollResults)
def rollw():
rollWindow = tix.Tk()
rollWindow.title("Dice Rolls")
diceLabel = Label(rollWindow, text = "Click Roll for your Stats")
diceLabel.grid(row = 0, column = 0)
rollBtn = Button(rollWindow, text = "Roll Stats", command = totalRolls)
rollBtn.grid(row = 1, column = 0)
txtresultsOut = StringVar()
resultsOut = Entry(rollWindow, state = "readonly", textvariable = txtresultsOut)
resultsOut.grid(row = 2, column = 0)
rollw()
first of all I would NOT recommend using StringVar(). You can use the .get() method of Entry to obtain the value inside the same. Try this way and make a global declaration of the Entry whose values you want to get in other functions.
EDIT------------
#you can use the following code to make your entry active to be edited.
entry.configure(state='normal')
# insert new values after deleting old ones (down below)
entry.delete(0,END)
entry.insert(0, text_should_be_here)
# and finally make its state readonly to not let the user mess with the entry
entry.configure(state='readonly')
I have two Scripts. Script 1 is titled schemeDetails.The second script is a test script called temporaryFile that creates a schemeSetup object using the schemeSetup class which is within schemeDetails. Everything is hunky dory up to the point where I try to acess the method insertScheme which is within the schemeSetup Class.
I have imported the schemeDetails script using the following:
import schemeDetails
reload(schemeDetails)
from schemeDetails import *
I can create the schemeDetails Object and access its attributes
d = schemeDetails.schemeSetup() -- fine
print(d.scheme) -- fine
d.insertScheme() -- throws error
but trying to call the insertScheme function throws an error
I don't know why this is happening as the import statement looks above board to me. Any advice appreciated
from sikuli import *
import os
class schemeSetup(object):
#Uses default values
def __init__(
self,
scheme = "GM",
cardNumber = "1234567A",
month = "December",
year = "2015",
setSchemeAsDefault = True):
#Provide default values for parameters
self.scheme = scheme
self.cardNumber = cardNumber
self.month = month
self.year = year
self.setSchemeAsDefault = setSchemeAsDefault
#schemeDetails is not a sub
# class of patient. It is simply defined within the patient class
# - there is a huge difference.
#====================================================#
#schemeDetails Function
def insertScheme(self):
print("insertScheme Works")
#r = Regions()
#r.description("Patient Maintenance", "schemeDetails")
#myRegion = r.createRegion()
#myRegion.highlight(1)
#click(myRegion.find(insertSchemeButton))
#click(myRegion.find(blankSchemeEntry))
#type(self.scheme + Key.ENTER + Key.ENTER)
#type(self.cardNumber + Key.ENTER)
#type(self.month + Key.ENTER)
#type(self.year + Key.ENTER)
#type(" ")
#unticks HT link, HT linking should be in a separate function
#====================================================#
#schemeDetails Function
def editScheme(self):
print("editScheme Works")
#====================================================#
def deleteScheme(self):
pass
#====================================================#
It may be of importance that calling either of the bottom functions does not produce an error. If I put print("Hello") under editScheme, and call that method using s.editScheme the program compiles but I get no output. If I run print(s.editScheme) it returns None
Well it seems to be fixed now after changing the import format to this
import schemeDetails
from schemeDetails import schemeSetup
s = schemeDetails.schemeSetup()
Good Afternoon all,
I've been working on a contact-book program for a school project. I've got all of the underlying code complete. However I've decided to take it one step further and implement a basic interface. I am trying to display all of the contacts using the code snippet below:
elif x==2:
phonebook_data= open(data_path,mode='r',encoding = 'utf8')
if os.stat(data_path)[6]==0:
print("Your contact book is empty.")
else:
for line in phonebook_data:
data= eval(line)
for k,v in sorted(data.items()):
x= (k + ": " + v)
from tkinter import *
root = Tk()
root.title("Contacts")
text = Text(root)
text.insert('1.0', x)
text.pack()
text.update()
root.mainloop()
phonebook_data.close()
The program works, however every contact opens in a new window. I would like to display all of the same information in a single loop. I'm fairly new to tkinter and I apologize if the code is confusing at all. Any help would be greatly appreciated!!
First of all, the top of the snippet could be much more efficient:
phonebook_data= open(data_path,mode='r',encoding = 'utf8') should be changed to
phonebook_data = open(data_path).
Afterwards, just use:
contents = phonebook_data.read()
if contents == "": # Can be shortened to `if not contents:`
print("Your contact book is empty.")
And by the way, it's good practice to close the file as soon as you're done using it.
phonebook_data = open(data_path)
contents = phonebook_data.read()
phonebook_data.close()
if contents == "":
print("Your contact book is empty.")
Now for your graphics issue. Firstly, you should consider whether or not you really need a graphical interface for this application. If so:
# Assuming that the contact book is formatted `Name` `Number` (split by a space)
name_number = []
for line in contents.split("\n"): # Get each line
name, number = line.split()
name_number.append(name + ": " + number) # Append a string of `Name`: `Number` to the list
name_number.sort() # Sort by name
root = Tk()
root.title("Contact Book")
text = Text(root)
text.pack(fill=BOTH)
text.insert("\n".join(name_number))
root.mainloop()
Considering how much I have shown you, it would probably be considered cheating for you to use it. Do some more research into the code though, it didn't seem like the algorithm would work in the first place.
I'm new to Python/programming, so please be gentle! I've been fairly good at figuring stuff out for myself (or finding answers here!) so far, but i've been struggling with this for a while now..
Using Tkinter, I want a label to print the sum of two entry fields, updating automatically after each entry input. This is where I've got to:
from Tkinter import *
import ttk
root = Tk()
first_var = IntVar()
second_var = IntVar()
total_var = IntVar()
para = [0, 0]
def totalupdate(*args):
global para
para[0] = first_var.get()
para[1] = second_var.get()
newtotal = sum(para)
total_var.set(newtotal)
first_var.trace('w', totalupdate)
second_var.trace('w', totalupdate)
first = ttk.Entry(root, textvariable=first_var)
second = ttk.Entry(root, textvariable=second_var)
total = ttk.Label(root, textvariable=total_var)
first.grid()
second.grid()
total.grid()
root.mainloop()
So, this seems to work fine within the Tk window, but it throws up
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__
File "para.py", line 15, in totalupdate
para[1] = second_var.get()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 283, in get
ValueError: invalid literal for int() with base 10: ''
in the terminal window any time I use .get() within a trace callback function. I've tried multiple ways of getting around this to no avail. I'm sure there's a pretty simple solution, and it doesn't seem to affect the program but its bugging me! Any help much appreciated, as well as any comments concerning a better way to achieve what I'm trying to do. Many thanks!
Whenever your first variable changes, the trace is triggered, but the second value is still empty. An empty string is not an integer, and the exception is thrown.
In this case, I'd catch that exception and simply return, until both variables hold proper integers:
def totalupdate(*args):
global para
try:
para[0] = first_var.get()
para[1] = second_var.get()
except ValueError:
# one or both values are not integers
return
newtotal = sum(para)
total_var.set(newtotal)
I've discovered urwid recently and started to play around with it. I've seen a Menu like tutorial example (which works!) and I've tried to modify the code a bit so I can get back and forth in the menu for starters - without doing anything else.
However I got stuck - and Im at a loss on why its happening.
Running this code:
import urwid
choices = u'Tank_1 Tank_2 Tank_3 Solarkreis Exit'.split()
def menu(title, choices):
body = [urwid.Text(title), urwid.Divider()]
for c in choices:
button = urwid.Button(c)
if c == "Exit":
urwid.connect_signal(button, 'click', exit_program)
else:
urwid.connect_signal(button, 'click', item_chosen, c)
body.append(urwid.AttrMap(button, None, focus_map='reversed'))
return urwid.ListBox(urwid.SimpleFocusListWalker(body))
def item_chosen(button, choice):
response = urwid.Text([u'Uebersicht ', choice, u'\n'])
done = urwid.Button(u'Ok')
urwid.connect_signal(done, 'click', menu(u'Menu', choices))
main.original_widget = urwid.Filler(urwid.Pile([response,
urwid.AttrMap(done, None, focus_map='reversed')]))
def exit_program(button):
raise urwid.ExitMainLoop()
main = urwid.Padding(menu(u'Menu', choices), left=2, right=2)
top = urwid.Overlay(main, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9)
urwid.MainLoop(top, palette=[('reversed', 'standout', '')]).run()
Running it I get
TypeError: 'ListBox' object is not callable
And I done quite understand how and why.. Help is much appreciated!
Edit: Forgot to add, the error pops up when I try to go back from the sub - menu to the original menu.
line 22, the third parameter is a ListBox object not a callable function.
urwid.connect_signal(done, 'click', menu(u'Menu', choices))