Jython Swing: Passing more than self and event on

2019-08-06 11:56发布

问题:

I'm creating a couple of swing JButtons buttons in a loop in Jython. On press, each button should call the same function, but with one different parameter. I'm having trouble passing any parameters outside of self, and event.

This works:

for x in range(0,3):
    name = JButton(str(x))
    name.actionPerformed = self.foo

def foo(self, event):
    print "I work."

Somehow event magically is passed to the method.

This doesn't:

for x in range(0,3):
    name = JButton(str(x))
    name.actionPerformed = self.foo(x)

def foo(self, event, number):
    print "I don't work."
    print str(number)

The issue as I see it, it that I'm not when I add any argument, I no longer pass an event and I end up with an error telling me "foo() takes exactly 3 arguments (2 given)". I get that, but how can I extract the event from the button?

回答1:

A callback only takes what the code calling it (the GUI toolkit) passes in. If you want to pass in more and you can't convince said caller to pass on something extra, you're out of luck.

But luckily, there's a loophole: You can pass arbitrary callables, and you can construct partial functions, which are functions wrapping another function, remembering additional arguments to pass along whenever they are called.

import functools

def callback(x, y):
    return x + y

g = functools.partial(callback, y=3)
g(2) #=> 5

There are a few issues with strange argument orders (e.g. you can't easily call partial with positional arguments if the first argument was supplied via keyword argument), but your use case (add arguments to the end of the argument list) should work just fine. You just need to use keyword arguments.



回答2:

I'm going with delnan's answer, but I did find another more problem specific solution that I'm going to use in this case and thought it would be worth passing along.

Instead of adding additional information to the function call, it's rather easy to use the event passed to get information on the caller.

I.E.

for x in range(0,3):
    name = JButton(str(x))
    name.actionPerformed = self.foo

def foo(self, event):
   sender = event.getSource()
   print sender.getText()