2011-01-09 3 views
3

libglade를 GtkBuilder로 사용하는 것으로 일부 코드를 업데이트하고 있습니다.이 코드는 미래의 방법이라고 생각합니다.pygtk gtk.Builder.connect_signals 여러 객체에?

gtk.glade를 사용하면 프로그램의 다른 창에 해당하는 서로 다른 클래스의 객체에 신호를 연결하기 위해 glade_xml.signal_autoconnect(...)을 반복적으로 호출 할 수 있습니다. 그러나 Builder.connect_signals은 전달 된 첫 번째 클래스에서 정의되지 않은 핸들러에 대해 경고를주기 위해 한 번만 작동하고 (따라서) 나타납니다.

수동으로 연결할 수 있지만 실제로는 약간 힘듭니다. (또는 그 문제에 관해서는 getattr hackery를 사용하여 프록시를 통해 모든 객체에 연결할 수 있습니다 ...)

여러 오브젝트에 핸들러를 연결하는 기능은 없습니까? 또는 나는 무엇인가 놓치고 있냐?

다른 사람이 비슷한 문제가 있다고 생각합니다. http://www.gtkforums.com/about1514.html 이것은 수행 할 수 없다는 것을 의미합니다.

답변

4

여기에 내가 현재 가지고있는입니다. 나는 약간의 시간이에 대한 해결책을 찾고있다

class HandlerFinder(object): 
    """Searches for handler implementations across multiple objects. 
    """ 
    # See <http://stackoverflow.com/questions/4637792> for why this is 
    # necessary. 

    def __init__(self, backing_objects): 
     self.backing_objects = backing_objects 

    def __getattr__(self, name): 
     for o in self.backing_objects: 
      if hasattr(o, name): 
       return getattr(o, name) 
     else: 
      raise AttributeError("%r not found on any of %r" 
       % (name, self.backing_objects)) 
+0

고마워, 간단하고 효과적! :) – mac

2

나는 단지 초보자 해요 그러나 이것은 내가, 어쩌면 ;-)

가 나는 '제어'에서 주요 구성 요소를 인스턴스화 영감을 인스턴스화 된 개체를 만들 수 있도록 빌더 개체를 전달할 수 않는 것입니다 빌더 객체 (예 : mainwindow)를 사용하거나 빌더 (aboutDialog 예)에 추가하십시오. 또한 각 구성 요소에 "신호"를 추가하는 사전 (dic)을 전달합니다.
그러면 'connect_signals (dic)'이 실행됩니다.
물론 callback 메서드에 사용자 인수를 전달해야 할 때 몇 가지 수동 신호 연결이 필요하지만 그 수가 적습니다.

#modules.control.py 
class Control: 

    def __init__(self): 

     # Load the builder obj 
     guibuilder = gtk.Builder() 
     guibuilder.add_from_file("gui/mainwindow.ui") 
     # Create a dictionnary to store signal from loaded components 
     dic = {} 

     # Instanciate the components... 
     aboutdialog = modules.aboutdialog.AboutDialog(guibuilder, dic)   
     mainwin = modules.mainwindow.MainWindow(guibuilder, dic, self) 
     ... 

     guibuilder.connect_signals(dic) 
     del dic 


#modules/aboutdialog.py 
class AboutDialog: 

    def __init__(self, builder, dic): 
     dic["on_OpenAboutWindow_activate"] = self.on_OpenAboutWindow_activate 
     self.builder = builder 

    def on_OpenAboutWindow_activate(self, menu_item): 
     self.builder.add_from_file("gui/aboutdialog.ui") 
     self.aboutdialog = self.builder.get_object("aboutdialog") 
     self.aboutdialog.run() 

     self.aboutdialog.destroy() 

#modules/mainwindow.py 
class MainWindow: 

    def __init__(self, builder, dic, controller): 

     self.control = controller 

     # get gui xml and/or signals 
     dic["on_file_new_activate"] = self.control.newFile 
     dic["on_file_open_activate"] = self.control.openFile 
     dic["on_file_save_activate"] = self.control.saveFile 
     dic["on_file_close_activate"] = self.control.closeFile 
     ... 

     # get needed gui objects 
     self.mainWindow = builder.get_object("mainWindow") 
     ... 

편집 : 자동차에 대한 대안은 콜백에 신호를 첨부 :
테스트되지 않은 코드

def start_element(name, attrs): 
    if name == "signal": 
     if attrs["handler"]: 
      handler = attrs["handler"] 
      #Insert code to verify if handler is part of the collection 
      #we want. 
      self.handlerList.append(handler) 

def extractSignals(uiFile) 
    import xml.parsers.expat 
    p = xml.parsers.expat.ParserCreate() 
    p.StartElementHandler = self.start_element 
    p.ParseFile(uiFile) 

self.handlerList = [] 
extractSignals(uiFile) 

for handler in handlerList: 
    dic[handler] = eval(''. join(["self.", handler, "_cb"])) 
+1

답변 해 주셔서 감사합니다. 나는 그것이 효과가 있다는 것을 알 수있다. 그러나 그것은 내가 피하고 싶었던 핸들러 이름을 반복하고있다 : – poolie

+1

나는 대답하려고 노력함으로써 배우고있다. 내가 시도 할 것인가 ... 내 핸드러의 이름을 어느 클래스에서 필요로 하는지를 규명하는 컨벤션으로 지명하십시오. 그런 다음 ui 파일을 구문 분석하여 원하는 처리기를 찾거나 ui 파일이 클래스에 특정한 경우 모든 핸들러가 될 수 있습니다. 코드가 내 대답에 추가되었습니다. 이것이 당신을 돕는 지 확실하지 않더라도, 나는 그것을 배울 것이 틀림 없습니다.:-) – Dave

3

과는 connect_signals 모든 핸들러의 DICT을 통과하여 수행 할 수 있다는 것을 발견 : 그것을 사용, 또는 더 나은 뭔가를 제안하시기 바랍니다.

해당 모듈 다음은 그러한 on_delete 같은 중복 기능 알아 보는 d.update(d3)을 사용하여 사전에 연결될 수 inspect.getmembers(instance, predicate=inspect.ismethod 사용 방법을 추출 할 수있는 검사.

예제 코드 :

import inspect 
...  
handlers = {} 
for c in [win2, win3, win4, self]: # self is the main window 
    methods = inspect.getmembers(c, predicate=inspect.ismethod) 
    handlers.update(methods) 
builder.connect_signals(handlers) 

이 별명 메소드 이름을 선택하지 않습니다는 @alias를 사용하여 선언했다. 이를 수행하는 방법에 대한 예제는 Builder.py의 코드 (def dict_from_callback_obj)를 참조하십시오.

-1
builder.connect_signals 
({ 
    "on_window_destroy" : gtk.main_quit, 
    "on_buttonQuit_clicked" : gtk.main_quit 
})