I am new to programming in python, and I want to create simple app for calculating your age based on the user input. I am using the 'datetime' module, and I found example of the program running in the terminal, but I don't know tow to link the entry box with the button using tkinter. This is the link from the code sample I am using and want to recreate it in tkinter.
import tkinter as tk
from datetime import date
def CheckAge():
global result # to return calculation
result = str(entry.get())
today = date.today()
#Convert user input into a date
dob_data = result.split("/")
dobDay = int(dob_data[0])
dobMonth = int(dob_data[1])
dobYear = int(dob_data[2])
dob = date(dobYear,dobMonth,dobDay)
#Calculate number of days lived
numberOfDays = (today - dob).days
#Convert this into whole years to display the age
age = numberOfDays // 365
label=tk.Label(root, "You are "+str(age) +" years old", command=CheckAge)
label.pack()
print("You are " + str(age) + " years old.")
result = 0
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Calculate", command=CheckAge)
button.pack()
root.mainloop()
At the end of executing this code I get this error message:
dobDay = int(dob_data[0])
ValueError: invalid literal for int() with base 10: ''
As mentioned, I am beginner and I am using multiple code samples from online forums.
first of all, label does NOT have a command. Secondly, you need to add the attribute "text" to the label. So, here is the modified version of your code:
import tkinter as tk
from datetime import date
def CheckAge():
global result # to return calculation
result = str(entry.get())
today = date.today()
#Convert user input into a date
dob_data = result.split("/")
dobDay = int(dob_data[0])
dobMonth = int(dob_data[1])
dobYear = int(dob_data[2])
dob = date(dobYear,dobMonth,dobDay)
#Calculate number of days lived
numberOfDays = (today - dob).days
#Convert this into whole years to display the age
age = numberOfDays // 365
label=tk.Label(root, text="You are "+str(age) +" years old")
label.pack()
print("You are " + str(age) + " years old.")
result = 0
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Calculate", command=CheckAge)
button.pack()
root.mainloop()
With these little modifications you should be able to get the result you wanted it.
Related
I have no idea why this is not working, I have been looking and I cant see whats wrong I have messed with it for a while all I want is for it to work.
gets input outputs numbers equal to randomly generated if full number equals the random then you win but it just crashes when I press the button
from tkinter import *
from tkinter import ttk
import random
master = Tk()
master.title('Guess The Number!')
global answer
global guess_entry
global guess_display
answer = str(random.randint(1000,9999))
guess_counter = 0
def callback():
print('Button pressed')
counter = 0
correct = []
while counter < 4:
if guess_entry.get() == answer:
correct.append('Well done, that is correct')
break
elif guess_entry.get()[counter] == answer[counter]:
correct.append(guess_entry.get[counter])
counter += 1
guess_display['text'] = ' '.join(str(correct))
def Help():
win = Toplevel()
win.title('Help')
l = Label(win, text="Guess a 4 digit number and I will tell you\n what you got right,\n keep trying until you get it in the \ncorrect order with correct numbers")
l.grid(row=0, column=0)
b = Button(win, text="Okay", command=win.destroy)
b.grid(row=1, column=0)
guess_entry = Entry(master)
guess_check = Button(master, text='Guess', command=callback)
guess_display = Label(master,text='_ _ _ _')
help_button = ttk.Button(master, text="?", command=Help,width=3)
guess_entry.grid(row=0,column=2)
guess_check.grid(row=1,column=2)
guess_display.grid(row=2,column=1)
help_button.grid(row=0,column=4)
master.mainloop()
If the numbers aren't equal the first time through the loop, they won't be equal any other time through the loop since the user won't have a chance to change their answer while the loop is running.
You can see this by adding a print statement:
while counter < 4:
print("counter:", counter, "guess:", guess_entry.get())
...
One last attempt to solve this problem. I have a Python program that queries the database using a default rundate to today - timedelta(7). I have created a datepicker to be opened using a menu button if the user want to choose their own dates to query. I am having problems figuring out the query that will integrate the dates chosen by the datepicker into the program.
The datepicker works fine as I am able to print the start and end dates that are chosen using
def submit():
start = self.result1.strftime("%m/%d/%Y")
end = self.result2.strftime("%m/%d/%Y")
print(start, end)
I assume that the "print(start, end)" will have to be changed to "return(start,end)" to incorporate it into the main query but I could be wrong.
The initial query and top part of the interface is
import pyodbc
from datetime import date, timedelta
from tkinter import *
from tkinter.ttk import *
import calendar
from decimal import *
import sqlite3
import os
import pick
db = r"M:\CWA_DB\WPTS\WPTS_Prod\WPTS_PROD_be.accdb"
conn = pyodbc.connect('Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq='+db)
cur = conn.cursor()
#Rundate, 7 days ago
rundate = date.today() - timedelta(7)
print(rundate)
#Query permits made effective since rundate
query = '''select `NPDES_ID`, `EffectiveDate`, `FacilityName`, `StateFacilityID`, `City`, `CountyName`
from Permits
where `EffectiveDate` >= ?
order by `NPDES_ID`'''
IDS=[]
FacCodes=[]
PermStrings=[]
PayStrings=[]
OwnerStrings=[]
MTB=[]
MTG=[]
MTR=[]
SWC=[]
MT0=[]
count=0
#for each row in result of query
for row in cur.execute(query, (rundate)):
try:
d= row[1].strftime('%m/%d/%Y')
except:
d=""
#create a display string with the appropriate information permit # - date - facility name - city, county
for i in range(len(row)):
if not row[i]:
row[i] = ""
permitstring=row[0]+" | "+d+"\t | "+row[2]+"\t | "+row[4]+", "+row[5]+" County"
IDS.append(row[0])
tempid=row[0]
#add the index to the appropriate permit type array, used to display seperately
if tempid[0:3]=="MTB":
MTB.append(count)
if tempid[0:3]=="MTG":
MTG.append(count)
if tempid[0:4]=="MTR0":
MTR.append(count)
if tempid[0:3]=="MT0" or tempid[0:3]=="MT4" or tempid[0:3]=="MTX":
MT0.append(count)
if tempid[0:4]=="MTR1":
SWC.append(count)
FacCodes.append(row[3])
PermStrings.append(permitstring)
count+=1
WPTSInv=[]
#get the owners for the permits
for i in range(len(IDS)):
query = '''select `Owner`
from Owners
where `StateFacilityID` = ?'''
for row in cur.execute(query, (str(FacCodes[i]))):
#create an owner name string for the facility ID
OwnerStrings.append("Owner: "+row[0])
#get payments on the permits
for i in range(len(IDS)):
paydate = date.today() - timedelta(60)
query = '''select `AmountPaid_credit`, `PayComment`, `DateReceived`, `WPTSinvoiceNo`
from Payments
where `NPDES_ID` = ? and `DateReceived` >= ?'''
PayStrings.append("\tPayment Received")
for row in cur.execute(query, (IDS[i],paydate)):
WPTSInv.append(row[3])
d= row[2].strftime('%m/%d/%Y')
#create a payment string
PayStrings[i]="\t$"+str(round(Decimal(row[0]),2))+" | "+d+" | "+row[1]
#Initiate interface
root = Tk()
master = Frame(root, name='master')
master.pack(fill=BOTH)
root.geometry("800x800+300+100")
root.title('WeeklyReport')
menu_bar = Menu(root)
def exit():
root.destroy()
def GetCalendar():
os.system("Pick.py")
root.wait_window
filemenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Exit", command=exit)
datemenu = Menu(menu_bar)
menu_bar.add_command(label='Change Date', command=GetCalendar)
root.config(menu=menu_bar)
# start the app
if __name__ == "__main__":
master.mainloop()
I have searched high and low for a solution but have not had much luck. I am sure others would be helped by an answer (even if the answer is that what I am trying to do is impossible)
I have been trying to build my skills in Python and am trying to create a risk style game.
I am not far in to it at the moment as I am trying to get to grips with classes and Tkinter.
My first trial is to create a series of buttons to take the place of the different countries. I then want these buttons to update the amount of armies on the country when they are clicked.
So far I have been able to get the map to generate from the class I have created and the buttons are clickable. When a button is clicked it updates the amount of armies but always for the last button.
How do I get it so that the button I click updates and not the last one?
Have I gone about this in entirely the wrong way?
from tkinter import *
import random
class territory:
def __init__ (self, country, player = "1", current_armies = 0, x=0, y=0):
self.country = country
self.current_armies = current_armies
self.player = player
self.y = y
self.x = x
def get_armies(self):
print(self.country + " has " + str( self.current_armies)+ " armies.")
def add_armies (self, armies):
self.current_armies += armies
def roll_dice (self, dice=1):
rolls = []
for i in range(0, dice):
rolls.append(random.randint(1,6))
rolls.sort()
rolls.reverse()
print (self.country + " has rolled " + str(rolls))
return rolls
def owner(self):
print (self.country + " is owned by " + self.player)
def get_country(self):
print(country)
def button (self):
Button(window, text = territories[0].current_armies, width = 10, command = click1(territories, 0)).grid(row=y,column=x)
window = Tk()
def create_territories():
countries = ["UK", "GER", "SPA", "RUS"]
terr_pos = [[1,0],[2,0],[1,5],[4,1]]
sta_arm = [1,1,1,1]
terr = []
player = "1"
for i in range(len(countries)):
terr.append(territory(countries[i],player, sta_arm [i] , terr_pos[i][0],terr_pos[i][1]))
if player == "1":
player = "2"
else:
player = "1"
return terr
def click1(territory, i):
territory[i].current_armies += 1
build_board(territory)
def build_board(territories):
for i in range(0,4):
Button(window, text = territories[i].country+"\n"+str(territories[i].current_armies), width = 10, command = lambda: click1(territories, i)).grid(row=territories[i].y,column=territories[i].x)
territories = create_territories()
window.title ("Domination")
create_territories()
build_board(territories)
window.mainloop()
In your def button(self):... you are always referencing territories[0]:
Button(window, text=territories[0].current_armies,... command=click1(territories, 0)...
As such, you are always using the first territory as your reference, so you ought to initialize each territory with its index in territories[] so you can pass that into your Button constructor.
On your question of "entirely the wrong way," I'd personally send that question over to CodeReview, since that's more of their domain (we fix broken code, they address smelly code), though there is significant overlap. We do prefer one question per question, however, and "is this whole thing wrong?" is a little broad for StackOverflow.
I am working on creating a gui and could use some help. There are three programs that build off of each other. MY imput will be two CSV files, Examples below:
items4.csv
12345,Italy,100
13579,China,50
ETC.
transactions4.csv
12345,15
13579,10
12345,20
13579,-10
What I want it to do is upon running the gui will open and the window will ask for the "Item ID" Upon entering an id, say 12345, it will open up a new window that displays the following: getID, getName, getAvailableStart, and getAvailableEnd, all of these definitions are were created by the travelclass program (found below) when the program travelToolbox reads the two CSV files.
Note: Both the travelClass and travelToolbox programs are working fine. IT is only travelSystem that needs changing at this point
What I've done:
At this point I have managed to get the travelSystems presents the initial GUI however it doesn't matter what I enter in the entry box because when I hit the open button the next gui opens up but it only shows the information found in the first line of items4.csv. I think my main issue is line 34 or may be line 16. Let me know if any other information is needed.
I could really appreciate some help. Thank you in advance.
travelsystem
from travelToolbox import readItems, readTransactions
from tkinter import *
from tkinter import font
import tkinter as tk
class myApp :
def __init__(self, top, itemRecords) :
self.root = top
# Create a container Frame at the bottom
self.bframe = Frame(self.root)
self.bframe.pack(side=BOTTOM) # Create Label
self.xlabel = Label(self.root, text="Item ID")
self.xlabel.pack(side=LEFT)
self.xentry = Entry(self.root, bd=5) # Create Entry box
self.xentry.pack(side=LEFT)
self.xentry.focus_set() # Set focus in Entry box
self.xopen = Button(self.root, text="Open", command=self.showStockItem) # Create open Button
self.xopen.pack(side=LEFT)
self.xquit = Button(self.bframe, text="Quit", command=self.quitit ) # Create quit Button
#self.root instead of bframe
self.xquit.pack(side=BOTTOM)
def showStockItem(self):
tbl = Toplevel() # Create Toplevel window
hdr = font.Font(underline=1, weight="bold") # Create header font
tid = Label(tbl, text="ID", font=hdr) # Create 4 column headers in grid
tid.grid(row=0, column=0)
tlast = Label(tbl, text="Name", font=hdr)
tlast.grid(row=1, column=0)
tfirst = Label(tbl, text="Start", font=hdr)
tfirst.grid(row=2, column=0)
tlabel = Label(tbl, text="End", font=hdr)
tlabel.grid(row=3, column=0)
for rec in itemRecords.values() :
tid = Label(tbl, text= rec.getID()) # Create 4 column headers in grid
tid.grid(row=0, column=1)
tlast = Label(tbl, text= rec.getName())
tlast.grid(row=1, column=1)
tfirst = Label(tbl, text= rec.getAvailableStart())
tfirst.grid(row=2, column=1)
tlabel = Label(tbl, text= rec.getAvailableEnd())
tlabel.grid(row=3, column=1)
#self.xquit.pack(side=BOTTOM) #May not need this.
return
def quitit(self):
self.root.destroy()
return
itemsFileName = "items4.csv"
transactionsFileName = "transactions4.csv"
# itemRecords is a dictionary of stockItem records indexed by item ID
itemRecords = {}
# Read the items from itemsFileName into itemRecords
readItems(itemsFileName, itemRecords)
# Read the transactions from transactionsFileName into itemRecords
readTransactions(transactionsFileName, itemRecords)
top = tk.Tk()
#top = Travel()
app = myApp(top, itemRecords)
top.mainloop()
Other files:
travelToolbox
import csv
from travelClass import travelItem
def readItems(itemsFileName, itemRecords) :
# readItems reads items from itemsFileName into the itemRecords dictionary
# Open itemsFileName and create a CSV file reader
itemsFile = open(itemsFileName, 'r')
itemsReader = csv.reader(itemsFile)
# Process each row of the items file
for row in itemsReader :
# Get the values for the record
(iid, iname, icount) = row
iid = str(iid)
iname = str(iname)
icount = int(icount)
# Check if this ID is not yet in itemRecords
if (not(iid in itemRecords)) :
# Create a travelItem object and add it to itemRecords
itemRecord = travelItem(iid, iname, icount)
itemRecords[iid] = itemRecord
def readTransactions(transactionsFileName, itemRecords) :
# readTransactions reads transactions from transactionsFileName into the itemRecords dictionary
transactionFile = open(transactionsFileName, 'r')
transactionReader = csv.reader(transactionFile)
for row in transactionReader :
# Get the values for the record
(iid, itransaction) = row
iid = str(iid)
itransaction = int(itransaction)
itemRecords[iid].appendTransaction(itransaction)
#for key, value in itemRecords.items() :
transactionFile.close()
travelClass
class travelItem :
Class travelItem :
def __init__(self, itemID, itemName, itemCount) :
# Constructor to create inventoryItem CORRECT
self.id = itemID
self.name = itemName
self.AvailableStart = itemCount
self.transactions = []
def getID(self) :
# getID returns the tour ID CORRECT
return(self.id)
def getName(self) :
# getName returns the tour name CORRECT
return (self.name)
def setName(self, newName) :
# setName sets the tour name
self.name = newName
def getAvailableStart(self) :
# returns the starting availability
return (self.AvailableStart)
def appendTransaction(self, num) :
# appendTransaction appends a transaction to the transactions list
self.transactions.append(num)
def getTransactions(self) :
# getTransactions returns the list of transactions
return (self.transactions)
def getReservations(self) :
# returns the total of reservation transactions
total = 0
for num in self.transactions :
if ((num) > 0):
total += (num)
self.Reservations = total
return(self.Reservations)
def getCancellations(self) :
# returns the total of cancellation transactions
total = 0
for num in self.transactions :
if (num <= 0):
total += (num)
return(total)
def getAvailableEnd(self) :
# returns the ending availability, which is availableStart minus transactions
self.AvailableEnd = ((self.AvailableStart) - (self.Reservations) - (self.getCancellations()))
return(self.AvailableEnd)
I am building a device that counts how many parts are made off a machine and then turns the machine off at a specific number. I am using an Arduino for all the I/O work and then importing the serial data into Python as variable partCount. I would like to create a simple GUI in tkinter to show the number of parts that have been made and the total number needed. The problem is that I keep getting an error on the label lines that include a variable instead of just a text. I've done a lot of research on it, but I just can't get it for some reason. Any advice would be appreciated.
import serial
import csv
import datetime
import tkinter
#Part Variables
partNumber = "A-33693" #Part Number
stockupTotal = 10
arduinoSerialData = serial.Serial('com3',9600) #Serial Variable
now = datetime.datetime.now()
#GUI
window = tkinter.Tk()
window.title("Troy Screw Products")
titleLabel = tkinter.Label(window, text="Davenport Machine Control")
partNumberLabel = tkinter.Label(window, text="Part #:")
stockUpTotalLabel = tkinter.Label(window, text="Stockup Total:")
partCountLabel = tkinter.Label(window, text="Current Part Count:")
partNumberInfo = tkinter.Label(window, partNumber)
stockUpTotalInfo = tkinter.Label(window, stockupTotal)
partCountInfo = tkinter.Label(window, partCount)
titleLabel.pack()
partNumberLabel.pack()
partNumberInfo.pack()
stockUpTotalLabel.pack()
stockUpTotalInfo.pack()
partCountLabel.pack()
partCountInfo.pack()
window.mainloop()
#Write to CSV File
def writeCsv():
with open("machineRunData.csv", "a") as machineData:
machineDataWriter = csv.writer(machineData)
machineDataWriter.writerow([partNumber, "Stockup Complete",now.strftime("%Y-%m-%d %H:%M")])
machineData.close()
#Serial Import
while (1==1):
if (arduinoSerialData.inWaiting()>0):
partCount = arduinoSerialData.readline()
partCount = int(partCount)
if partCount == 999999:
writeCsv()
print(partCount)
There are several options you can give to a Label widget, as you can see here. You should specify all parameters after the first by name:
partNumberInfo = tkinter.Label(window, text=PartNumber)
To use Python variables in Tkinter you need to special Tk objects, of which there are four: BooleanVar, DoubleVar, IntVar, and StringVar. See this answer for a good example.
So after a ton of research over the last week, I found a solution. The problem was that the program would run the GUI, but not run the code for the serial import until the GUI window was closed. I needed a way to get both the GUI running and updated and get the serial data importing at the same time. I resolved this by creating a thread for both operations. There's probably an easier way to do this, but this what I came up with. The code is below for anyone having a similar problem.
import serial
import time
import threading
from tkinter import *
#Part Variables
partNumber = "A-33693" #Part Number
stockupTotal = 10
partCount = 0
def countingModule():
global partCount
while (1==1):
time.sleep(2)
partCount += 1
print(partCount)
def gui():
global partCount
root = Tk()
pc = IntVar()
pc.set(partCount)
titleLabel = Label(root, text="Machine Control")
partNumberLabel = Label(root, text="Part #:")
stockUpTotalLabel = Label(root, text="Stockup Total:")
partCountLabel = Label(root, text="Current Part Count:")
partNumberInfo = Label(root, text=partNumber)
stockUpTotalInfo = Label(root, text=stockupTotal)
partCountInfo = Label(root, textvariable=pc)
titleLabel.pack()
partNumberLabel.pack()
partNumberInfo.pack()
stockUpTotalLabel.pack()
stockUpTotalInfo.pack()
partCountLabel.pack()
partCountInfo.pack()
def updateCount():
pc.set(partCount)
root.after(1, updateCount)
root.after(1, updateCount)
root.mainloop()
op1 = threading.Thread(target = countingModule)
op2 = threading.Thread(target = gui)
op1.start()
op2.start()