I'm currently implementing a game GUI, where there are three
components to the screen: A battle, a command button area and a city
view area. Each of these are rectangular, and handle interactions in
different ways.
For example, on the battle "frame" you can select units, right-click
to deliver context-sensitive commands, etc. On the command frame, you
select buttons to deliver commands, change the state of the battle
frame (i.e., a move command sets the battle frame to accept a move-to
location). This sort of thing.
So I'm implementing the frame code right now. Each Frame object has a
StateMachine object. Which mean that in the __init__ code of a child
of Frame, you add rules to the StateMachine object:
###
class ButtonFrame(Fra me):
def __init__(self, owner, pos, size=None):
Frame.__init__( self, owner, pos, size)
ism = self.input_stat e_machine
ism.add_rule("N one", "LWait", (MOUSEBUTTONDOW N, 1))
##
ism.add_rule("L Wait", "None", (MOUSEBUTTONDOW N, 2))
ism.add_rule("L Wait", "None", (MOUSEBUTTONUP, 1))
###
This is all fine and good. Now, when creating a Frame child class, you
make an implicit agreement that you'll create methods for each state,
such as ButtonFrame.ent er_state_LWait( ) or
ButtonFrame.lea ve_state_None() .
My current approach is that in the Frame class, I have a method to
call _after_ initialization that creates a bunch of dummy methods so
the user doesn't have to implement EVERY state change method in a
Frame child:
###
## @classmethod -- Python 2.4
def _empty_state_me thod(self):
pass
_empty_state_me thod = classmethod(_em pty_state_metho d)
def create_empty_st ate_methods(sel f):
ism = self.input_stat e_machine
for timing in ('enter','durin g','leave'):
for state in ism.states:
method = '%s_state_%s' % (timing, state)
if not hasattr(self.__ class__, method):
setattr(self.__ class__, method, Frame._empty_st ate_method)
###
This means that if the user hasn't implemented
ButtonFrame.dur ing_state_LWait (), for example, an empty function will
be provided (pointing to _empty_state_me thod().
(Aside: I'm considering putting all these state methods in a
dictionary of dictionaries so you can do a quick
myButtonFrame.s tate_dict['during']['LWait'] to access the proper
method)
What this now means is that when implementing a child, I am not only
forcing a call to Frame.__init__( ), but also
Frame.create_em pty_state_metho ds(). So my ButtonFrame class looks
like:
###
class ButtonFrame(Fra me):
def __init__(self, owner, pos, size=None):
Frame.__init__( self, owner, pos, size)
ism = self.input_stat e_machine
ism.add_rule("N one", "LWait", (MOUSEBUTTONDOW N, 1))
##
ism.add_rule("L Wait", "None", (MOUSEBUTTONDOW N, 2))
ism.add_rule("L Wait", "None", (MOUSEBUTTONUP, 1))
self.create_emp ty_state_method s()
###
Note the last line. When programming EVERY child I have to remember to
add this self.create_emp ty_state_method s() line.
My question: What are Pythonic alternatives to this sort of thing?
I can think of a few solutions, but none of them seem to be obviously
advantageous:
1. All children don't call __init__, but have an _init() method that
is called by Frame.__init__( ). That way ButtonFrame has an _init()
method rather than an __init__() method. This may be my best option.
###
class Frame:
def __init__(self, owner, pos, size=None):
self.owner = owner
self.children = []
# more setup code here.
self._init()
self.create_emp ty_state_method s()
###
2. Frame has an init() function that needs to be called following the
instantiation of a Frame (or Frame child object). I'm not too keen on
this, because it requires creating the Frame object and _then_ running
an init() method. I try to keep that sort of thing to a minimum
because it makes quick object creation a little funky. (init() has to
return self so you can do a myList.append(B uttonFrame().in it()))
###
class Frame:
def __init__(self, owner, pos, size=None):
self.owner = owner
self.children = []
# more setup code here.
def init(self):
self.create_emp ty_state_method s()
return self
b = Frame()
b.init()
myList.append(b )
###
Phew! Hope that's not overly long! Now I can't be the first person to
want a pre- and post- child init code! I'm worried that I'm
overlooking something or there's an even more Pythonic way to do
things than above.
--
Zak Arntson
http://www.harlekin-maus.com - Games - Lots of 'em
components to the screen: A battle, a command button area and a city
view area. Each of these are rectangular, and handle interactions in
different ways.
For example, on the battle "frame" you can select units, right-click
to deliver context-sensitive commands, etc. On the command frame, you
select buttons to deliver commands, change the state of the battle
frame (i.e., a move command sets the battle frame to accept a move-to
location). This sort of thing.
So I'm implementing the frame code right now. Each Frame object has a
StateMachine object. Which mean that in the __init__ code of a child
of Frame, you add rules to the StateMachine object:
###
class ButtonFrame(Fra me):
def __init__(self, owner, pos, size=None):
Frame.__init__( self, owner, pos, size)
ism = self.input_stat e_machine
ism.add_rule("N one", "LWait", (MOUSEBUTTONDOW N, 1))
##
ism.add_rule("L Wait", "None", (MOUSEBUTTONDOW N, 2))
ism.add_rule("L Wait", "None", (MOUSEBUTTONUP, 1))
###
This is all fine and good. Now, when creating a Frame child class, you
make an implicit agreement that you'll create methods for each state,
such as ButtonFrame.ent er_state_LWait( ) or
ButtonFrame.lea ve_state_None() .
My current approach is that in the Frame class, I have a method to
call _after_ initialization that creates a bunch of dummy methods so
the user doesn't have to implement EVERY state change method in a
Frame child:
###
## @classmethod -- Python 2.4
def _empty_state_me thod(self):
pass
_empty_state_me thod = classmethod(_em pty_state_metho d)
def create_empty_st ate_methods(sel f):
ism = self.input_stat e_machine
for timing in ('enter','durin g','leave'):
for state in ism.states:
method = '%s_state_%s' % (timing, state)
if not hasattr(self.__ class__, method):
setattr(self.__ class__, method, Frame._empty_st ate_method)
###
This means that if the user hasn't implemented
ButtonFrame.dur ing_state_LWait (), for example, an empty function will
be provided (pointing to _empty_state_me thod().
(Aside: I'm considering putting all these state methods in a
dictionary of dictionaries so you can do a quick
myButtonFrame.s tate_dict['during']['LWait'] to access the proper
method)
What this now means is that when implementing a child, I am not only
forcing a call to Frame.__init__( ), but also
Frame.create_em pty_state_metho ds(). So my ButtonFrame class looks
like:
###
class ButtonFrame(Fra me):
def __init__(self, owner, pos, size=None):
Frame.__init__( self, owner, pos, size)
ism = self.input_stat e_machine
ism.add_rule("N one", "LWait", (MOUSEBUTTONDOW N, 1))
##
ism.add_rule("L Wait", "None", (MOUSEBUTTONDOW N, 2))
ism.add_rule("L Wait", "None", (MOUSEBUTTONUP, 1))
self.create_emp ty_state_method s()
###
Note the last line. When programming EVERY child I have to remember to
add this self.create_emp ty_state_method s() line.
My question: What are Pythonic alternatives to this sort of thing?
I can think of a few solutions, but none of them seem to be obviously
advantageous:
1. All children don't call __init__, but have an _init() method that
is called by Frame.__init__( ). That way ButtonFrame has an _init()
method rather than an __init__() method. This may be my best option.
###
class Frame:
def __init__(self, owner, pos, size=None):
self.owner = owner
self.children = []
# more setup code here.
self._init()
self.create_emp ty_state_method s()
###
2. Frame has an init() function that needs to be called following the
instantiation of a Frame (or Frame child object). I'm not too keen on
this, because it requires creating the Frame object and _then_ running
an init() method. I try to keep that sort of thing to a minimum
because it makes quick object creation a little funky. (init() has to
return self so you can do a myList.append(B uttonFrame().in it()))
###
class Frame:
def __init__(self, owner, pos, size=None):
self.owner = owner
self.children = []
# more setup code here.
def init(self):
self.create_emp ty_state_method s()
return self
b = Frame()
b.init()
myList.append(b )
###
Phew! Hope that's not overly long! Now I can't be the first person to
want a pre- and post- child init code! I'm worried that I'm
overlooking something or there's an even more Pythonic way to do
things than above.
--
Zak Arntson
http://www.harlekin-maus.com - Games - Lots of 'em
Comment