我找到了解決這個問題的方法。我不確定是否有更優雅的解決方案,但基本上問題歸結爲必須將回調函數公開到global()
範圍,然後使用f()(g)
語法對API修飾器進行修飾。因此,我寫了一個基類(CallbackRegisterer
),它爲任何派生類提供了bindHandler()
方法 - 此方法包裝一個函數,併爲其提供一個唯一的ID,每個實例爲CallbackRegisterer
(我正在打開一些UI面板同一時間):
class CallbackRegisterer(object):
__count = 0
@classmethod
def _instanceCounter(cls):
CallbackRegisterer.__count += 1
return CallbackRegisterer.__count
def __init__(self):
"""
Constructor
@param eq_instance 0=playback 1=record 2=sidetone.
"""
self._id = self._instanceCounter()
print "instantiating #%d instance of %s" % (self._id, self._getClassName())
def bindHandler(self, ui_element, callback, callback_args = [], handler_type = None,
initialize = False, forward_event_args = False, handler_id = None):
proxy = lambda *args: self._handlerProxy(callback, args, callback_args, forward_event_args)
handler_name = callback.__name__ + "_" + str(self._id)
if handler_id is not None:
handler_name += "_" + str(handler_id)
globals()[handler_name] = proxy
# print "handler_name: %s" % handler_name
handler_type(ui_element)(proxy)
if initialize:
proxy()
def _handlerProxy(self, callback, event_args, callback_args, forward_event_args):
try:
if forward_event_args:
new_args = [x for x in event_args]
new_args.extend(callback_args)
callback(*new_args)
else:
callback(*callback_args)
except:
print "exception in callback???"
self.log.exception('In event callback')
raise
def _getClassName(self):
return self.__class__.__name__
然後我就可以從這個派生類,並傳入我的回調,這將使用API裝飾正確裝飾:
class Panel(CallbackRegisterer):
def __init__(self):
super(Panel, self).__init__()
# can bind from sub classes of Panel as well - different class name in handle_name
self.bindHandler(self.controls.test_button, self._testButtonCB, handler_type = valueChangeHandler)
# can bind multiple versions of same function for repeated ui elements, etc.
for idx in range(0, 10):
self.bindHandler(self.controls["check_box_"+str(idx)], self._testCheckBoxCB,
callback_args = [idx], handler_type = valueChangeHandler, handler_id = idx)
def _testCheckBoxCB(self, *args):
check_box_id = args[0]
print "in _testCheckBoxCB #%d" % check_box_id
def _testButtonCB(self):
"""
Handler for test button
"""
print "in _testButtonCB"
panel = Panel()
注意,那我也可以推導出更多的子類從Panel
開始,任何綁定的回調將根據類名稱字符串獲得自己的唯一handler_name
。
謝謝,有道理;但現在這給了我以下錯誤; 'AttributeError:'instancemethod'對象沒有屬性'panelOpenHandler'' – Aidenhjj
我不認爲你正確地複製了代碼(它應該是一個獨立的語句) - 沒有什麼東西應該把'panelOpenHandler'作爲一個屬性來查找。 – jasonharper
我想這是一個在'panelOpenHandler'裝飾器中執行的操作。我正確地複製了你的代碼。 – Aidenhjj