Heres a simple bank account i coded in Python using Tkinter, the issue im having is with the conditional statements in the withdraw and deposit functions, the code always goes with the else statement although in the standard and interest function it should change the value for the TypeOfAccount. Give your insight.
import tkinter
from tkinter import *
from random import randint
class BankAccount(object):
def __init__(self, initial_balance=0):
self.balance = initial_balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def get_balance(self, initial_balance, rate):
return self.get_balance() * self._rate
class BankAccountWithInterest(BankAccount):
def __init__(self, initial_balance=0, rate=0.1):
BankAccount.__init__(self, initial_balance)
self._rate = rate
def interest(self):
return self.balance * self._rate
balance = (randint(100, 500))
my_account = BankAccount(balance)
my_interest = BankAccountWithInterest(balance)
interest = my_interest.balance + my_interest.interest()
print(interest)
class GUI:
def __init__(self, master):
frame = Frame(master)
frame.pack()
#Toolbar#
toolbar = Frame(root)
toolbar.pack(side=TOP, fill=X)
#Button#
button1 = Button(toolbar, text="Deposit", width = 13, command=self.depositBalance)
button2 = Button(toolbar, text="Withdraw",width = 13, command=self.depositWithdraw)
button1.pack(side=LEFT)
button2.pack(side=RIGHT)
#Menu#
subMenu = Menu(menu)
menu.add_cascade(label="Type of Account", menu=subMenu)
subMenu.add_command(label="Standard", command= self.standard)
subMenu.add_command(label="Interest", command= self.interest)
#Textbox#
self.text = Entry(root)
self.text.pack()
def standard(self):
typeOfAcc = "standard"
w1.config(text=my_account.balance)
w1.pack()
def interest(self):
typeOfAccount = "interest"
w1.config(text=interest)
w1.pack()
def depositBalance(self):
if typeOfAccount == "interest":
a = int(self.text.get())
interest = interest + a
w1.config(text=interest)
elif typeOfAccount == "standard":
a = int(self.text.get())
my_account.balance = my_account.balance + a
print(my_account.balance)
w1.config(text=my_account.balance)
else:
w1.config(text="Error: Select account type")
def depositWithdraw(self):
if typeOfAccount == 1:
a = int(self.text.get())
interest = interest - a
w1.config(text=interest)
elif typeOfAccount == 0:
a = int(self.text.get())
my_account.balance = my_account.balance - a
print(my_account.balance)
w1.config(text=my_account.balance)
else:
w1.config(text="Error: Select account type")
typeOfAccount = 0
root = Tk()
menu = Menu(root)
root.config(menu=menu)
root.title("Bank Account")
root.minsize(width=250, height=100)
root.maxsize(width=300, height=150)
#Labels#
w = Label(root, text="Current Balance:")
w.pack()
w1 = Label(root, text="0")
w1.pack()
GUI(root)
root.mainloop()
Part of the problem is that in your deposit function, you are checking if typeOfAccount is 'standard' or 'interest', while in your withdraw function, you are checking if typeOfAccount is 1 or 0. This inconsistency will cause errors and unexpected behavior.
I also strongly suggest you put these 2 blocks of code:
balance = (randint(100, 500))
my_account = BankAccount(balance)
my_interest = BankAccountWithInterest(balance)
interest = my_interest.balance + my_interest.interest()
print(interest)
typeOfAccount = 0
root = Tk()
menu = Menu(root)
root.config(menu=menu)
root.title("Bank Account")
root.minsize(width=250, height=100)
root.maxsize(width=300, height=150)
#Labels#
w = Label(root, text="Current Balance:")
w.pack()
w1 = Label(root, text="0")
w1.pack()
in your main GUI class.
class Account:
def __init__(self, init_balance=0):
self.balance = init_balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def get_balance(self, init_balance, rate):
return self.get_balance() * self._rate
class InterestAccount(Account):
def __init__(self, init_balance=0, rate=0.1):
super().__init__(init_balance)
self._rate = rate
def interest(self):
return self.balance * self._rate
class GUI(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Bank Account')
#Menu#
menu = Menu(self)
acct_type_menu = Menu(menu)
menu.add_cascade(label='Account Type', menu=acct_type_menu)
acct_type_menu.add_command(label='Standard', command=self.set_type_standard)
acct_type_menu.add_command(label='Interest', command=self.set_type_interest)
self.config(menu=menu)
#Account#
start_balance = randint(100, 500)
self.acct = Account(start_balance)
self.my_interest = InterestAccount(start_balance)
self.interest = self.my_interest.balance + self.my_interest.interest()
#Labels#
Label(self, text='Current Balance:').pack()
self.balance_label = Label(self, text='Error: Select account type')
self.balance_label.pack()
#Button#
btns_frame = Frame(self)
btns_frame.pack(side=TOP, fill=X)
Button(btns_frame, text='Deposit', width=13, command=self.deposit).pack(side=LEFT)
Button(btns_frame, text='Withdraw', width=13, command=self.withdraw).pack(side=RIGHT)
#Textbox#
self.text = Entry(self)
self.text.pack()
def set_type_standard(self):
self.acct_type = 'standard'
self.balance_label.config(text=self.acct.balance)
def set_type_interest(self):
self.acct_type = 'interest'
self.balance_label.config(text=self.interest)
def clear_entry(self):
self.text.delete(0, END)
def deposit(self):
if self.acct_type == 'interest':
a = int(self.text.get())
interest = interest + a
self.balance_label.config(text=self.interest)
elif self.acct_type == 'standard':
a = int(self.text.get())
self.acct.balance += a
self.balance_label.config(text=self.acct.balance)
else:
self.balance_label.config(text='Error: Select account type')
self.clear_entry()
def withdraw(self):
if self.acct_type == 'interest':
a = int(self.text.get())
self.interest -= a
self.balance_label.config(text=self.interest)
elif self.acct_type == 'standard':
a = int(self.text.get())
self.acct.balance -= a
self.balance_label.config(text=self.acct.balance)
else:
self.balance_label.config(text='Error: Select account type')
self.clear_entry()
if __name__ == '__main__':
GUI().mainloop()
Major Changes:
made GUI inherit from Tk
moved more code into GUI class
altered main deposit and withdraw methods to use deposit and withdraw from the Account class
set the initial balance to be Error: Select account type
Minor Changes:
removed code that did nothing
clear entry when Deposit or Withdraw button is clicked
shortened the 2 account class names
made method and variable names more appropriate
EDIT: Because the Entry widget you are using is for deposit and withdrawal amounts, you may want to restrict input of the Entry to be numbers and period only:
class GUI:
def __init__(self):
...
vcmd = (self.register(self.onValidate), '%S')
self.text = Entry(self, validate='key', vcmd=vcmd)
self.text.pack()
...
def onValidate(self, S):
if S in '0123456789.':
return True
return False
...
Related
Ive been coding a maths game but stumbled across a problem where I cant clear a text widget. SO after the users get shown a list of incorrect questions and to play the game again, but after playing the game a second time the list doesn't reset. I've added a comment above the text widget I want to clear if that helps.
from tkinter import *
import random
from tkinter import messagebox
class Timestable:
def __init__(self, parent):
Timestable.f1 = Frame(parent,bg='#66bcb9')
Timestable.f1.grid()
Timestable.f2 = Frame(parent,bg='#66bcb9')
Timestable.f2.grid()
Timestable.f2.grid_forget()
Timestable.f3 = Frame(parent,bg='#66bcb9')
Timestable.f3.grid()
Timestable.f3.grid_forget()
Timestable.f4 = Frame(parent,bg='#66bcb9')
Timestable.f4.grid()
Timestable.f4.grid_forget()
#frame 1 ========================================================
Label(self.f1,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
Label(self.f1,text="Name:",bg='#508484',fg='white').grid(row=1,column=0)
Timestable.name = Entry (self.f1)
Timestable.name.grid(row=1,column=1)
Label(self.f1,text="Age",bg='#508484',fg='white').grid(row=2,column=0)
Timestable.age = Entry (self.f1)
Timestable.age.grid(row=2,column=1)
Timestable.incorrect=[]
Timestable.user = []
Timestable.checked = []
Label(self.f1,text="Select Timestable",bg='#508484',fg='white').grid(columnspan=2,row=3,column=0)
frame = Frame(self.f1)
frame.grid(row=5,column=0, columnspan=2)
for i in range(12):
Timestable.checked.append(IntVar()) # store the tkinter variable for the checkbox
Checkbutton(frame, text=i+1, variable=self.checked[-1], onvalue=i+1, offvalue=0, anchor='w',bg='#66bcb9').grid(row=i//3, column=i%3, sticky='ew')
Label(self.f1,text="Total Questions",bg='#508484',fg='white').grid(row=4,column=0)
Timestable.w = Spinbox(self.f1, from_=1, to=5)
Timestable.w.grid(row=4,column=1)
Button(self.f1,text="Start", command=lambda: data.start(self),bg='#88c43c').grid(columnspan=2, column=0,row=6)
#frame 2 ========================================================
Label(self.f2,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
self.x=0
self.correct=0
Timestable.questions=Label(Timestable.f2,text="")
Timestable.questions.grid(row=1,column=0)
Timestable.entryWidget = Entry (self.f2)
Timestable.entryWidget.grid(row=1,column=1)
Button(self.f2,text="submit", command=lambda: data.Submit(self),bg='#88c43c').grid(columnspan=2,column=0,row=3)
#frame 3 ========================================================
Label(self.f3,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
Timestable.congrats=Label(Timestable.f3,text="")
Timestable.congrats.grid(columnspan=2,column=0,row=1)
#this is the widget I want to clear
Timestable.incdisplay = Text(Timestable.f3, width=15,height=10,bg='#d0e4f4')
Timestable.incdisplay.grid(columnspan=2,column=0,row=2)
Button(self.f3,text="next", command=lambda:data.next(self),bg='#88c43c').grid(columnspan=2,column=0,row=3)
#fram 4 ========================================================
Label(self.f4,text="Multiplication Practice",bg='#508484',fg='white').grid(columnspan=2,column=0,row=0)
Label(self.f4,text="Results",bg='#508484',fg='white').grid(columnspan=2,column=0,row=1)
Timestable.my_text=Text(self.f4,width=20,height=10,bg='#d0e4f4')
Timestable.my_text.grid(columnspan=2,column=1,row=2)
Button(self.f4,text="again", command=lambda:data.again(self),bg='#88c43c').grid(columnspan=2,column=0,row=3)
class data:
def saveleader(self):
file=open('Leaderboard.txt',"a")
file.write(Timestable.name.get()+","+Timestable.age.get()+","+str(data.percent)+"%""\n")
file.close
file=open("Leaderboard.txt","r").read()
headers = " ".join(["Name", "Age", "Score"])
output = [i.split(",") for i in file.split("\n") if i]
out_sort = sorted(output, key=lambda x: int(x[2][:-1]), reverse=True)
final = "\n".join([headers, "-"*len(headers),*(" ".join(i) for i in out_sort)])
Timestable.my_text.insert(END, final)
def clear_text(self):
Timestable.entryWidget.delete(0, 'end')
def Questions(self):
number1 = random.choice(Timestable.user)
number2 = random.randrange(1,12)
self.answer = number1 * number2
self.prompt = (str(number1) + " X " + str(number2))
Timestable.questions.configure(text=self.prompt, width=len(self.prompt),bg='#66bcb9')
return self.answer
def start(self):
Timestable.user = [v.get() for v in Timestable.checked if v.get()]
if Timestable.user:
Timestable.f1.grid_forget()
Timestable.f2.grid()
data.Questions(self)
def results(self):
Timestable.f2.grid_forget()
Timestable.f3.grid()
def next(self):
Timestable.f3.grid_forget()
Timestable.f4.grid()
data.saveleader(self)
self.correct=0
data.deletold(self)
def again(self):
Timestable.f4.grid_forget()
Timestable.f1.grid()
def deletold(self):
Timestable.incdisplay.configure(state=NORMAL)
Timestable.incdisplay.delete("1.0",END)
Timestable.incdisplay.configure(state=DISABLED)
def Submit(self):
if Timestable.entryWidget.get() == "":
messagebox.showerror("Error", "Please enter a number.")
else:
if self.answer != int(Timestable.entryWidget.get().strip()):
messagebox.showinfo("Answer", "INCORRECT! Answer: " + str(self.answer))
Timestable.incorrect.append(self.prompt+"\n")
else:
messagebox.showinfo("Answer", "CORRECT!")
self.correct = self.correct +1
self.x=self.x+1
if self.x < int(Timestable.w.get()):
data.Questions(self)
data.clear_text(self)
else:
data.clear_text(self)
data.results(self)
data.percent = round(self.correct/self.x*100)
Timestable.congrats.configure(text="Congrats, you got "+ str(data.percent) +"% of the questions correct",bg='#66bcb9')
self.x=0
for i in Timestable.incorrect:
Timestable.incdisplay.configure(state=NORMAL)
Timestable.incdisplay.insert(END,i)
Timestable.incdisplay.configure(state=DISABLED)
root = Tk()
root.geometry("300x300")
root.configure(bg='#66bcb9')
Timestable(root)
root.mainloop()
I can't seem to update my money counter(var money) when its labeled, I have a button that's supposed to add 0.1 to moneyNum but the money counter doesn't change. I'm new to stack overflow and would appreciate any help.(btw sry if its REALLY messy)
from tkinter import *
import random
from time import sleep
root = Tk()
root.geometry('320x320')
#spacing
spacingTitle = Label(root, text=" \n\n\n\n\n\n\n\n\n")
#title
title = Label(root, text=" \bGamblers Dream\b", font="Helvetica", fg="red")
titleWelcom = Label(root, text=" Welcom to...")
titleWelcom.grid()
title.grid()
#money counter
moneyNum = float(10.0)
money = Label(root, text="money:" + str(moneyNum), font="Helvetica")
money.grid(row=3, column=0)
#moneyClicker
def moneyButtonAdder():
global moneyNum
moneyNum = moneyNum + 0.1
moneyClicker = Button(root, text="click", fg="green", command=moneyButtonAdder)
moneyClicker.grid(row=14)
root.mainloop()
The problem is that once you create a label, you pass the string to it. Label displays the string, and:
changing a string object does not change the label text
changing the integer does not change the string - it lost the whole connection when the new string object was created
So everything is not as procedural as you would have hoped it is.
The solution - use StringVar objects and detect value changes - see this.
So, the solution is:
from tkinter import *
class Observed(object):
"""adapted copy from https://stackoverflow.com/a/6192298/10713244"""
def __init__(self):
self._observed = 10.0
self._observers = []
#property
def observed(self):
return self._observed
#observed.setter
def observed(self, value):
self._observed = value
for callback in self._observers:
print('announcing change')
callback(self._observed)
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
class Observer(object):
def __init__(self, data):
self.text = ''
self.data = data
self.data.bind_to(self.update)
self.tkinter_init()
def update(self, observed):
self.text = 'float: '+str(data._observed)
self.tkinter_update()
def tkinter_init(self):
self.tk = Tk()
self.tvar = StringVar()
self.label = Label(textvariable=self.tvar)
self.label.pack()
def tkinter_update(self):
self.tvar.set(self.text)
if __name__ == '__main__':
data = Observed()
label = Observer(data)
print(label.text)
data.observed = 10.0
print(label.text)
def dec(): data.observed -= 0.1
Button(label.tk, text='decrease', command=dec).pack()
label.tk.mainloop()
Hope that's helpful!
I am creating a simple bank account GUI , when i click the menu " interest" the variable changed from 1 to 2 , which should change the value of the current balance by 10 percent, however the value stays the same, give your insight.
from tkinter import *
from random import randint
class BankAccount(object):
def __init__(self, initial_balance=0):
self.balance = initial_balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def get_balance(self, initial_balance, rate):
return self.get_balance() * self._rate
class BankAccountWithInterest(BankAccount):
def __init__(self, initial_balance=0, rate=0.1):
BankAccount.__init__(self, initial_balance)
self._rate = rate
def interest(self):
return self.balance * self._rate
balance = (randint(100, 500))
my_account = BankAccount(balance)
my_interest = BankAccountWithInterest(balance)
interest = my_interest.balance + my_interest.interest()
typeOfAccount = "1"
class GUI:
def __init__(self, master):
frame = Frame(master)
frame.pack()
#Toolbar#
toolbar = Frame(root)
toolbar.pack(side=TOP, fill=X)
#Button#
button1 = Button(toolbar, text="Deposit", width = 13, command=self.depositBalance)
button2 = Button(toolbar, text="Withdraw",width = 13, command=self.depositWithdraw)
button1.pack(side=LEFT)
button2.pack(side=RIGHT)
#Menu#
subMenu = Menu(menu)
menu.add_cascade(label="Type of Account", menu=subMenu)
subMenu.add_command(label="Standard", command= self.standard)
subMenu.add_command(label="Interest", command= self.interest)
#Textbox#
self.text = Entry(root)
self.text.pack()
#Labels#
w = Label(root, text="Current Balance:")
w.pack()
w1 = tkinter.StringVar()
if typeOfAccount == "1":
w1 = Label(root, text=my_account.balance)
w1.pack()
elif typeOfAccount == "2":
w1.set(text=interest)
w1.pack()
def depositBalance(self):
a = int(self.text.get())
my_account.balance = a + my_account.balance
print(my_account.balance)
def depositWithdraw(self):
a = int(self.text.get())
my_account.balance = my_account.balance - a
print(my_account.balance)
def standard(self):
typeOfAccount = "1"
def interest(self):
typeOfAccount = "2"
root = Tk()
menu = Menu(root)
root.config(menu=menu)
root.title("Bank Account")
root.minsize(width=250, height=100)
root.maxsize(width=300, height=150)
GUI(root)
root.mainloop()
There are several problems with your code. The multiple class files do not appear to work as you think they should and some things are just wrong. I have reworked your program into what I think it is you are trying to do and I have moved everything into 1 big class as it made more sense in this situation. You were making things more complicated than it needed to be by creating variables outside of the classes and by making several classes. There is nothing really wrong with using several classes but the way you were going about it was making things way more difficult than it needed to be.
First thing I did was to create all the class variables/attributes that we are going to use.
To make things easier on us going forward I made every widget and variable a class attribute by placing self. as a prefix to all the variable/widget names. This will allow us to interact with and change each attribute in any of the class methods without an issue and if you add more options down the road the attributes will already be defined and ready to change.
Next I moved all your separate class methods into the main class to make things easier to work with.
I replaced your if/else statement on the account types into a methods. This will allow us to update label to show the balance or the interest any time the account type changes or an amount is added or removed from the balance.
I modified the depositBalance and depositWithdraw methodsto have a little error handling because your entry field is not restricted to only numbers and can cause errors if the user puts anything else in or leaves it blank.
I change the standard and interest methods to update the typeOfAccount attribute and to update the label by calling on the type_account method.
Last but not least some general clean up so the code did not have pointless spacing and to make sure we follow a DRY (don't repeat yourself) standard.
Below is the reworked code with all the changes I mentioned above. Let me know if this helps and if you are confused on anything.
from tkinter import *
from random import randint
class GUI:
def __init__(self, master):
self.master = master
self.typeOfAccount = "1"
self.balance = (randint(100, 500))
self.rate = 0.1
self.frame = Frame(master)
self.frame.pack()
self.toolbar = Frame(root)
self.toolbar.pack(side=TOP, fill=X)
self.button1 = Button(self.toolbar, text="Deposit", width = 13, command=self.depositBalance)
self.button2 = Button(self.toolbar, text="Withdraw",width = 13, command=self.depositWithdraw)
self.button1.pack(side=LEFT)
self.button2.pack(side=RIGHT)
self.menu = Menu(self.master)
self.master.config(menu = self.menu)
self.subMenu = Menu(self.menu)
self.menu.add_cascade(label="Type of Account", menu=self.subMenu)
self.subMenu.add_command(label="Standard", command=self.standard)
self.subMenu.add_command(label="Interest", command=self.interest)
self.text = Entry(self.master)
self.text.pack()
self.w = Label(root, text="Current Balance: {}".format(self.balance))
self.w.pack()
#removed "tkinter." not needed because of the type of import you used
self.w1 = StringVar()
def type_account(self):
if self.typeOfAccount == "1":
self.w.config(text="Current Balance: {}".format(self.balance))
elif self.typeOfAccount == "2":
interest = self.balance * self.rate
self.w.config(text="Current Balance: {}".format(interest))
def depositBalance(self):
try:
if int(self.text.get()) > 0:
a = int(self.text.get())
self.balance = a + self.balance
self.type_account()
except:
print("Blank or non numbers in entry field")
def depositWithdraw(self):
try:
if int(self.text.get()) > 0:
a = int(self.text.get())
self.balance = self.balance - a
self.type_account()
except:
print("Blank or non numbers in entry field")
def standard(self):
self.typeOfAccount = "1"
self.type_account()
def interest(self):
self.typeOfAccount = "2"
self.type_account()
if __name__ == "__main__":
root = Tk()
root.title("Bank Account")
root.minsize(width=250, height=100)
root.maxsize(width=300, height=150)
app = GUI(root)
root.mainloop()
You should set self.w1, (rather than just w1) for example, then you can update the text from any instance method in that class.
I need help with a program which uses tkinter. So I try to use a button to cycle trough some pictures, but there are two cycles and when i press one button either disappears or goes back to the first one (it's kinda hard to explain). I was asking myself if I could use some threading here and I need help since I've never used it before.
This is the part of the code:
square1 = Image.open("Square1.jpg")
square1r = ImageTk.PhotoImage(square1)
self.square1img = Label(self.windowSq, image=square1r)
self.square1img.image = square1r
self.square1img.place(x=30, y=100)
square1 = Image.open("Square1a.jpg")
square1r = ImageTk.PhotoImage(square1)
self.square1img = Label(self.windowSq, image=square1r)
self.square1img.image = square1r
self.square1img.place(x=435, y=100)
next = Button(self.windowSq, text="Next", font=self.customFont, relief=GROOVE, command=self.next, cursor='hand2')
next.place(x=185, y=380)
self.num = 0
next1 = Button(self.windowSq, text="Next", font=self.customFont, relief=GROOVE, command=self.next1, cursor='hand2')
next1.place(x=600, y=380)
self.num1 = 0
def next(self):
self.num = self.num + 1
if self.num == 1:
self.square1img.destroy()
square2 = Image.open("Square2.jpg")
square2r = ImageTk.PhotoImage(square2)
self.square2img = Label(self.windowSq, image=square2r)
self.square2img.image = square2r
self.square2img.place(x=30, y=100)
elif self.num == 2:
self.square2img.destroy()
square3 = Image.open("Square3.jpg")
square3r = ImageTk.PhotoImage(square3)
self.square3img = Label(self.windowSq, image=square3r)
self.square3img.image = square3r
self.square3img.place(x=30, y=100)
elif self.num == 3:
self.square3img.destroy()
square4 = Image.open("Square4.jpg")
square4r = ImageTk.PhotoImage(square4)
self.square4img = Label(self.windowSq, image=square4r)
self.square4img.image = square4r
self.square4img.place(x=30, y=100)
elif self.num == 4:
self.square4img.destroy()
square5 = Image.open("Square5.jpg")
square5r = ImageTk.PhotoImage(square5)
self.square5img = Label(self.windowSq, image=square5r)
self.square5img.image = square5r
self.square5img.place(x=30, y=100)
elif self.num == 5:
self.square5img.destroy()
square1 = Image.open("Square1.jpg")
square1r = ImageTk.PhotoImage(square1)
self.square1img = Label(self.windowSq, image=square1r)
self.square1img.image = square1r
self.square1img.place(x=30, y=100)
self.num = 0
self.windowSq.after(50000, self.next)
def next1(self):
self.num1 = self.num1 + 1
if self.num1 == 1:
self.square1img.destroy()
square2 = Image.open("Square2a.jpg")
square2r = ImageTk.PhotoImage(square2)
self.square2img = Label(self.windowSq, image=square2r)
self.square2img.image = square2r
self.square2img.place(x=435, y=100)
elif self.num1 == 2:
self.square2img.destroy()
square3 = Image.open("Square3a.jpg")
square3r = ImageTk.PhotoImage(square3)
self.square3img = Label(self.windowSq, image=square3r)
self.square3img.image = square3r
self.square3img.place(x=435, y=100)
elif self.num1 == 3:
self.square3img.destroy()
square4 = Image.open("Square4a.jpg")
square4r = ImageTk.PhotoImage(square4)
self.square4img = Label(self.windowSq, image=square4r)
self.square4img.image = square4r
self.square4img.place(x=435, y=100)
elif self.num1 == 4:
self.square4img.destroy()
square5 = Image.open("Square5a.jpg")
square5r = ImageTk.PhotoImage(square5)
self.square5img = Label(self.windowSq, image=square5r)
self.square5img.image = square5r
self.square5img.place(x=435, y=100)
elif self.num1 == 5:
self.square5img.destroy()
square1 = Image.open("Square1a.jpg")
square1r = ImageTk.PhotoImage(square1)
self.square1img = Label(self.windowSq, image=square1r)
self.square1img.image = square1r
self.square1img.place(x=435, y=100)
self.num1 = 0
self.windowSq.after(50000, self.next1)
The whole program is in a class (if you are wondering...)
class Window(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.master.resizable(0, 0)
master.title("Arcade Games")
master.geometry("800x600+560+240")
You have a lot of redundant code above. The idea is to first store the images in a list and then cycle through the list. You can have 2 buttons that call 2 different functions (one for each list), 2 lists of images, and 2 counters to keep your place in each list, and then change the image on a Label from whichever list you want (I use a button as below, and note that only one button is created-never destroyed, and just the image is changed each time). Or you can use one class, and 2 instances of the class, passing a different list of images to be loaded to each instance. This is just a simple proof of concept program. Click on the button/image to change it.
import sys
if sys.version_info[0] < 3:
import Tkinter as tk ## Python 2.x
else:
import tkinter as tk ## Python 3.x
class ChangeImage():
def __init__(self, root):
self.photos=[]
self.load_images()
self.image_num=0
self.btn = tk.Button(root, image=self.photos[self.image_num], command=self.next_image)
self.btn.grid(row=0)
tk.Button(root, text="Exit", bg="orange", command=root.quit).grid(row=1)
def next_image(self):
self.image_num += 1
if self.image_num >= len(self.photos):
self.image_num=0
## pipe the next image to be displayed to the button
self.btn["image"]=self.photos[self.image_num]
def load_images(self):
""" copy data images to a list that is an instance variable
"""
ladybug_gif_b64='''\
R0lGODlhIAAgALMAAP///wAAADAwMP99Hf8AAP+lAP//AMopUwAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACH5BAAAAAAALAAAAAAgACAAAwTHEMhJq714hp3lDh0GiqH2UWOVAt96pUIsBLKglWg87Dwv
4xMBj0Asxgg+XKxwLBJrxUGsI5TKnARoVHoLDp5XbNP5cwmNAqwa/aOc13ByrfKOw2UGw1SSxrb+
AWIxeXsAaX92UDQ1Nh6BdneMhQIHkHGSjYaVlmt4epmacp19YAKEoJRspKWrjBapWWGqcm1uB5tj
ok4HZa+3m5wEt5kuhpTAcb+FVL/NzspAfDHPysslMJjEIS0oLygnOMVd0SwcHeDk6errEQA7
'''
grape_gif='''\
R0lGODlhIAAgALMAAAAAAAAAgHCAkC6LV76+vvXeswD/ANzc3DLNMubm+v/6zS9PT6Ai8P8A////
/////yH5BAEAAAkALAAAAAAgACAAAAS00MlJq7046803AF3ofAYYfh8GIEvpoUZcmtOKAO5rLMva
0rYVKqX5IEq3XDAZo1GGiOhw5rtJc09cVGo7orYwYtYo3d4+DBxJWuSCAQ30+vNTGcxnOIARj3eT
YhJDQ3woDGl7foNiKBV7aYeEkHEignKFkk4ciYaImJqbkZ+PjZUjaJOElKanqJyRrJyZgSKkokOs
NYa2q7mcirC5I5FofsK6hcHHgsSgx4a9yzXK0rrV19gRADs=
'''
house='''R0lGODdhFQAVAPMAAAQ2PESapISCBASCBMTCxPxmNCQiJJya/ISChGRmzPz+/PxmzDQyZDQyZDQy
ZDQyZCwAAAAAFQAVAAAElJDISau9Vh2WMD0gqHHelJwnsXVloqDd2hrMm8pYYiSHYfMMRm53ULlQ
HGFFx1MZCciUiVOsPmEkKNVp3UBhJ4Ohy1UxerSgJGZMMBbcBACQlVhRiHvaUsXHgywTdycLdxyB
gm1vcTyIZW4MeU6NgQEBXEGRcQcIlwQIAwEHoioCAgWmCZ0Iq5+hA6wIpqislgGhthEAOw==
'''
## could also be a list of files passed to the class
for photo in (ladybug_gif_b64, grape_gif, house):
self.photos.append(tk.PhotoImage(data=photo))
root=tk.Tk()
CI=ChangeImage(root)
root.mainloop()
I want to separate the GUI and the game logic using object oriented but when Im trying to display the "self.result" using tkinter.Label its show "PY VAR1".
Can anyone please help how to update the self.result?
rockpaperscissor.py
import random
class RockPaperScissor:
def __init__(self):
self.rock = 'rock'
self.paper = 'paper'
self.scissor = 'scissor'
self.playerA_win = 'player A win'
self.playerB_win = 'player B win'
self.draw = 'Its draw'
self.playerA_score = 0
self.playerB_score = 0
self.choices = {'rock': self.rock,
'paper': self.paper,
'scissor': self.scissor}
self.transition = {
(self.rock, self.rock): self.draw,
(self.rock, self.paper): self.playerB_win,
(self.rock, self.scissor): self.playerA_win,
(self.paper, self.rock): self.playerA_win,
(self.paper, self.paper): self.draw,
(self.paper, self.scissor): self.playerB_win,
(self.scissor, self.rock): self.playerB_win,
(self.scissor, self.paper): self.playerA_win,
(self.scissor, self.scissor): self.draw}
def play(self, playerA, playerB):
self.playerA_answer = self.choices[playerA]
self.playerB_answer = self.choices[playerB]
self.result = self.transition[self.playerA_answer,
self.playerB_answer]
def get_result(self):
return self.result
def computer():
choices = ('rock', 'paper', 'scissor')
playerB = random.choice(choices)
return playerB
if __name__ == "__main__":
rps = RockPaperScissor()
while True:
playerA = input('What is your guess? ')
playerB = computer()
rps.play(playerA,playerB)
print(rps.get_result())
and
rockpaperscissor_gui.py
import tkinter as tk
import rockpaperscissor as rps
class MyFrame(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.pack()
self.value = tk.StringVar()
self.result = tk.StringVar()
self.choice = ('rock', 'paper', 'scissor')
self.rps = rps.RockPaperScissor()
for i in self.choice:
self.radio = tk.Radiobutton(self,
text=i,
variable=self.value,
value=i).pack()
self.button = tk.Button(self,
text='play',
command=self.play).pack()
self.label = tk.Label(self,
text=self.result).pack()
def play(self):
playerA = self.value.get()
playerB = rps.computer()
self.rps.play(playerA, playerB)
self.result.set('result: {0}'.format(self.result))
if __name__ == '__main__':
MyFrame().mainloop()
this is the screenshot image
thanks for answer now its working!
this is the new code
#rockpaperscissor_gui.py
import tkinter as tk
import random as rn
import rockpaperscissor as rps
class RockPaperScissor:
def __init__(self):
self.rps = rps.RockPaperScissor()
self.root = tk.Tk()
self.playerA = tk.StringVar()
self.playerA.set('Pick your answer')
self.playerB = tk.StringVar()
self.playerB.set('Pick your answer')
self.result = tk.StringVar()
self.rps.playerA_score = tk.StringVar()
self.rps.playerB_score = tk.StringVar()
self.choices = ('rock', 'paper', 'scissor')
self.label_choices = (self.playerA, self.playerB, self.result)
for item in self.label_choices:
self.label = tk.Label(self.root, textvariable=item)
self.label.pack()
for item in self.choices:
self.radiobutton = tk.Radiobutton(self.root, text=item,
variable=self.playerA,
value=item)
self.radiobutton.pack()
self.button = tk.Button(self.root,
text='update',
command=self.update).pack()
self.root.mainloop()
def update(self):
self.playerB_answer = rn.choice(self.choices)
self.playerB.set(self.playerB_answer)
player = self.playerA.get()
computer = self.playerB.get()
self.rps.play(player, computer)
answer = self.rps.get_result()
self.result.set(answer)
if __name__ == '__main__':
RockPaperScissor()
You have to use textvariable in Label and display self.rps.get_result()
btw: you don't have to assign widget to variable if you don't use this variable.
Code could be like this
import tkinter as tk
import rockpaperscissor as rps
class MyFrame(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.pack()
self.value = tk.StringVar()
self.result = tk.StringVar()
self.choice = ('rock', 'paper', 'scissor')
self.rps = rps.RockPaperScissor()
for i in self.choice:
tk.Radiobutton(self,
text=i,
variable=self.value,
value=i).pack()
tk.Button(self, text='play', command=self.play).pack()
tk.Label(self, textvariable=self.result).pack() # textvariable
def play(self):
playerA = self.value.get()
playerB = rps.computer()
self.rps.play(playerA, playerB)
self.result.set('result: {0}'.format(self.rps.get_result())) # get_result()
if __name__ == '__main__':
MyFrame().mainloop()