From: Charlie G. <cha...@gm...> - 2007-12-18 09:38:59
|
On Dec 17, 2007 8:25 PM, Eric Johnson <er...@eb...> wrote: > Is there a good Pythonic way to write the propertyChange method for a > PropertyChangeListener? > > Writing code like: > > def propertyChange(self, e): > if e.propertyName == "progress": > self.progressBar.value = e.newValue > elif e.propertyName == swing.SwingWorker.StateValue.PENDING: > ... > > seems to be a very unsatisfactory. > > In the case of ActionListeners being able to use actionPerformed is greaqt > but I don't really understand the reflection magic that Jython perfoms > behind the scenes to know if that can be applied here. As astigmatik pointed out, you can set a propertyChange function in the constructor to an object that has an addPropertyChangeListener method, but that still leaves you writing that propertyChange function which is just a bunch of if else statements. I attempted to whip up a little module that would relieve some of that tedium, but it ended up being overkill for the task at hand. I'm still sending it on in the hopes that someone can simplify it to something reasonable. from java.awt import Color from java.beans import PropertyChangeListener, PropertyChangeEvent from javax.swing import JPanel class PropertyMatcher(PropertyChangeListener): def __init__(self, action, name=None, newVal=None, oldVal=None): ''' Takes an action to execute if this matches, and optional values for each of the fields on PropertyChangeListener to check for equality. ''' self.action = action self.checkers = [ (name, PropertyChangeEvent.getPropertyName), (newVal, PropertyChangeEvent.getNewValue), (oldVal, PropertyChangeEvent.getOldValue)] def __call__(self, e): self.match(e) def match(self, e): # If e passes all the checkers, or we don't have a checker for a field, # invoke the action with e and return true. Otherwise return false. for checker, val in self.checkers: if checker and not checker == val(e): return 0 self.action(e) return 1 class MultiplePropertyMatcher(PropertyMatcher): '''Calls the first PropertyMatcher it has that matches a change''' def __init__(self, *matchers): '''Takes a list of PropertyMatchers to check in order''' self.matchers = matchers def __call__(self, e): for matcher in self.matchers: if matcher.match(e): break def printer(val): def print_func(x): print val return print_func if __name__ == '__main__': matcher = MultiplePropertyMatcher( PropertyMatcher(printer('background to black'), 'background', Color.BLACK), PropertyMatcher(printer('something is black'), newVal=Color.BLACK), PropertyMatcher(printer('background changed'), 'background'), PropertyMatcher(printer('nothing matched'))) p = JPanel(propertyChange=matcher) p.setBackground(Color.BLACK) p.setBackground(Color.RED) p.setForeground(Color.BLACK) p.setForeground(Color.RED) Running that module prints four lines: background to black background changed something is black nothing matched As I said earlier, it barely feels better to me than just writing the if elses directly, but it *almost* feels elegant. Any takers on making it suck less? Charlie |