2011-04-19 4 views
7

슬롯을 동적으로 생성하고 연결하려고합니다. pushButton을 동적으로 생성하고 기존 슬롯과 연결할 수 있습니다. 하지만 일부 멤버 함수가있는 클래스가 있고 이러한 함수를 슬롯으로 사용하려면 어떻게해야합니까?Qt에서 동적 슬롯 만들기

일반적인 관점에서 볼 때 함수 포인터가있는 슬롯을 생성하기위한 템플릿을 만들고 싶습니다. 이렇게하면 기존 코드를 변경하지 않고 슬롯을 만들 수 있으며 MOC를 사용하여 다시 컴파일 할 필요가 없습니다. 이것이 의미가 없다면 알려주세요. 고맙습니다.

-CV

답변

9

많은 의미가 있습니다. 나는 QSignalMapper을 원하는 것으로 생각하지 않습니다. 당신의 함수는 인수가없는 경우,이 같은 아마 뭔가 충분하다 :

class SlotForwarder : public QObject 
{ 
    Q_OBJECT 

public: 

    typedef void (*Function)(); // or whatever. I never get this syntax right... 

    SlotForwarder(Function function, QObject* parent = 0) 
     : QObject(parent) 
     , m_fptr(function) 
    {} 

public slots: 

    void forward() 
    { 
     m_fptr(); 
    } 

private: 

    Function m_fptr; 
}; 

당신이 캡슐화 평소대로 forward에 연결하려는 각 기능에 대한 하나 만듭니다. 그들은이 인수를 할 경우


지금, 어쩌면이 Qt는 분기 별 기사는 도움이 될 수 있습니다.

Dynamic Signals and Slots by Eskil A. Blomfeldt

기술은 qt_metacall 방법 자신을 재 구현이 포함됩니다.

int QObject::qt_metacall(QMetaObject::Call call, int id, void **arguments) 

통화 metacall의 종류 : 슬롯, 신호, 읽기 또는 쓰기 재산권 등 모든 슬롯은 ID를 가지고있어서,이 서명을 가진다. 매개 변수는 배열의 배열 안에 (값 또는 포인터로) 묶입니다. moc이 생성하는 코드를 읽는 것은 그것이 어떻게 작동하는지 이해하는 좋은 방법입니다.

원시 함수 시그니처에 대한 데이터는 컴파일 타임에만 사용할 수 있지만 런타임에는 슬롯을 확인합니다. 이러한 불일치로 인해 qt_metacall 구현에 대한 지속적인 인터페이스를 제공하고 arguments 배열을 함수가 이해할 수있는 것으로 변환하는 템플릿 어댑터 유형으로 함수를 래핑해야합니다 (Python unpack 연산자 참조). Boost.Signals은 이런 종류의 template hackery입니다.

+0

확실히 어떠한 멤버 함수를 사용하도록. 이것은 정상적인 기능에는 작동하지만 멤버 기능에는 작동하지 않아야합니다. 클래스 멤버 함수에 대해이 작업을 수행하는 방법을 알고 있습니까? 감사합니다 andref. – blueskin

+0

. tr1 :: bind를 사용하여 멤버 함수 부분을 알아 냈습니다. 아래 코드를 게시했습니다. 동적 UI 생성 (동적 신호/슬롯 연결 포함)을위한 작은 앱이 있으면 링크를 게시합니다. – blueskin

2

andref의 코드의 연속 코드하는 슬롯으로서

class SlotForwarder : public QObject 
    { 
     Q_OBJECT 

    public: 

     typedef void (*Function)(); 

     SlotForwarder(Function function, QObject* parent = 0) 
      : QObject(parent) 
      , m_fptr(function) 
     {} 

    public slots: 

     void forward() 
     { 
      m_fptr(); 
     } 

    private: 

     Function m_fptr; 
    }; 

    int main(){ 
     QApplication a(argc, argv); 
     MyClass myClassObject; //contains a function called MemberFunc 
     //create a slotforwarder object so 
     SlotForwarder *memberFuncSlot = new SlotForwarder (std::tr1::bind(&MyClass::MemberFunc, &myClassObject)); 
     QObject::connect(ui.button,SIGNAL(clicked()),memberFuncSlot,SLOT(forward()); 
    } 
+0

와우! 'tr1 :: bind'는 훌륭합니다. 그리고 나는 그것에 대해 완전히 잊어 버렸습니다. – andref

+0

예, 잊어 버렸습니다 – blueskin

+0

흥미로운 접근 방법이지만 일반적인 프로그램에서 전달자를 언제 삭제합니까? 스마트 포인터가 더 합리적인 것 같아요. – Martin