I am currently a student obtaining a Bachelor's in Computer Science, and I am writing a python program in the little spare time that I have to help me learn Spanish. It's definitely not an extravagant program that I'm going to publish or anything, just for me to have fun and mess around with. I just learned the basic GUI structure of python programming with Tkinter, and I am just trying to be pointed in the right direction to optimize my code to make it smaller and not look so basic. I have 3500 lines of code so far, so I won't upload the whole code, but here is the structure of pretty much my entire program
def _months( self ):
#Framework for the Month Window
Frame.__init__( self )
self.master.title( "Months" )
self.grid()
labelfont = ( "times", 18, "bold" )
homefont = ( "times", 10, "bold" )
self._monthMenuImage = PhotoImage( file = 'mexicoWater.gif' )
self._monthBackgroundLabel = Label( self, image = self._monthMenuImage )
self._monthBackgroundLabel.place( x = 0, y = 0 )
self.grid_propagate(0)
self["height"] = 600
self["width"] = 800
#January button
self._januaryButton = Button( self, text = "January",
command = self._switchJanuary )
self._januaryButton.config( font = labelfont, bg = self.water2 )
self._januaryButton.config( height = 0, width = 10 )
self._januaryButton.place( x = 65, y = 325 )
#February button
self._februaryButton = Button( self, text = "February",
command = self._switchFebruary )
self._februaryButton.config( font = labelfont, bg = self.water2 )
self._februaryButton.config( height = 0, width = 10 )
self._februaryButton.place( x = 315, y = 325 )
#March button
self._marchButton = Button( self, text = "March",
command = self._switchMarch )
self._marchButton.config( font = labelfont, bg = self.water2 )
self._marchButton.config( height = 0, width = 10 )
self._marchButton.place( x = 565, y = 325 )
The "command = self._switch...."
leads to different methods such as
def _switchJanuary( self ):
if self._januaryButton["text"] == "January":
self._januaryButton.config( bg = self.water1 )
self._januaryButton["text"] = "Enero"
else:
self._januaryButton["text"] = "January"
self._januaryButton.config( bg = self.water2 )
def _switchFebruary( self ):
if self._februaryButton["text"] == "February":
self._februaryButton.config( bg = self.water1 )
self._februaryButton["text"] = "Febrero"
else:
self._februaryButton["text"] = "February"
self._februaryButton.config( bg = self.water2 )
def _switchMarch( self ):
if self._marchButton["text"] == "March":
self._marchButton.config( bg = self.water1 )
self._marchButton["text"] = "Marzo"
else:
self._marchButton["text"] = "March"
self._marchButton.config( bg = self.water2 )
"self.water1" and "self.water2" are just cool blue colors that I declared as class variables earlier on.
This is the basic structure of my entire code, with months, days, numbers and such. I'm just trying to find a way to make the code smaller, because I want to add a lot of different features to the program without it being a million lines. I've been told to use a dictionary, in which I could access the key values to translate the words instead of having to have each Button lead to a different method, but I am lost. Any help would be greatly appreciated. Thank you for your time!
The best way to archive a smarter (generic) code is the right level of abstraction. If you look closely you will see a pattern in every of those methods. In every method you have two different strings. Like you have already mentioned it is perfect for a dictionary, where the english word remark the key and the spanish word is the value. You have to define a dictionary with all needed word. Than you can create your Buttons, with reference to your generic method. This generic method has a the Button as a paramter. Now you check if the button-text matches the keys, if not check if the button-text matches those values. I hope you get the idea now. Here is a small working example:
from Tkinter import Tk, Frame, Button
def translate(button):
if button["text"] in monthdict.keys():
button.config(bg="Red", text=monthdict[button["text"]])
else:
for key, val in monthdict.iteritems():
if val in button["text"]:
button.config(bg="Blue", text=key)
root = Tk()
mainframe = Frame(root)
mainframe.pack()
monthdict = {"January": "Enero", "February": "Febrero", "March": "Marzo"}
janbutton = Button(mainframe, text="January", bg="Blue", command= lambda: translate(janbutton))
janbutton.pack()
febbutton = Button(mainframe, text="February", bg="Blue", command= lambda: translate(febbutton))
febbutton.pack()
marchbutton = Button(mainframe, text="March", bg="Blue", command= lambda: translate(marchbutton))
marchbutton.pack()
root.mainloop()
Even here you can optimize. Maybe a smarter way to get the key from a given value in the translate
method. Or a smarter way to add the buttons. For example you can use a foreach to create the button. They only problem is that you have to find a way to pass the button as a value to the function.
EDIT:
It kinda bugged me that the foreach didn't worked for creating the buttons right. So the solution is to use binding for each button, with the event
parameter you get access to your Button
again:
from Tkinter import Tk, Frame, Button
def translate(event):
if event.widget["text"] in monthdict.keys():
event.widget.config(bg="Red", text=monthdict[event.widget["text"]])
else:
for key, val in monthdict.iteritems():
if val in event.widget["text"]:
event.widget.config(bg="Blue", text=key)
root = Tk()
mainframe = Frame(root)
mainframe.pack()
monthdict = {"January": "Enero", "February": "Febrero", "March": "Marzo"}
buttondict = {}
for key in monthdict.keys():
buttondict[key] = Button(mainframe, text=key, bg="Blue")
buttondict[key].bind("<Button-1>", translate)
buttondict[key].pack()
root.mainloop()
With buttondict
you still has access to the created Buttons. If i count it right this optimzed 120 lines of code to 13 lines.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.