2017-12-25 2 views
3

편집 # 2 : 필요한 람다 호출 구문을 파악했습니다!C++ Qt, 콜백 전달

[=](int value) { (this->*callback_function)(i, value); } 

이 작업을 더 잘 조정하는 방법에 대한 제안을 찾고 있습니다.이 방법이 너무 복잡합니다.


편집 : 코드가 업데이트되었지만 거의 계속 충돌합니다.

template <typename F> 
void Dialog::create_spinbox_column(const int &NUM_ROWS, QFrame *&frame, 
            QLabel *label_arr[], 
            QSpinBox *spinbox_arr[], 
            F callback_function) { 
    frame = new QFrame(); 
    QGridLayout *layout = new QGridLayout; 
    for(int i = 0; i < NUM_ROWS; i++) { 
     int row = i+1; 
     QString label_text = QObject::tr("Line %1:").arg(row); 
     label_arr[i] = new QLabel(label_text); 
     spinbox_arr[i] = new QSpinBox; 
     layout->addWidget(label_arr[i], row, 1); 
     layout->addWidget(spinbox_arr[i], row, 2); 
     QObject::connect(spinbox_arr[i], qOverload<int>(&QSpinBox::valueChanged), this, 
         [=](int value) { callback_function(i, value); }); 
    } 
    frame->setLayout(layout); 
} 

은 내가 this->callback_function(i, value) 같은 몇 가지를 시도했습니다 오류

error: must use '.*' or '->*' to call pointer-to-member function in 'callback_function (...)', e.g. '(... ->* callback_function) (...)' 
         [=](int value) { callback_function(i, value); }); 
                ^

받고 있어요,하지만 난 아직 시도했습니다 아무 일 없다. 확실히 콜백이 정적 인 것은 원하지 않습니다. 그 의미는 없습니다. create_spinbox_column 함수를 호출하는 현재 Dialog 클래스의 컨텍스트 내에서 호출되어야합니다. 다음은


원래 게시물입니다 : 내가 최근에 GUI 입력에 텍스트 기반의 입력에서 내 프로그램 중 하나를 변환하는 Qt를 사용하기 시작


,하지만 몇 가지 그루터기를 치는거야 . Qt에서 "제대로"수행하는 방법에 대한 높은 수준의 설계 피드백과 현재의 문제점을 디버그하는 방법에 대한 구체적인 피드백을 모두 사용할 수 있습니다.

먼저 내 현재 작업에 대한 간단한 설명 (마음에 들지 않으면 아래 코드를 건너 뜁니다.) : 나는 깔끔하게 정리되고 콜백 함수에 연결되는 많은 수의 스핀 상자를 갖습니다 void callback_with_id(int id, int value) 형태로, 여기서 id은 어떤 스핀 박스 값이 변경되었는지를 식별하는 고유 번호이고, value은 물론 스핀 박스의 새로운 값이됩니다.

내가 좋아하는 시각적 레이아웃을 만들었지 만, 스핀 상자를 콜백 함수에 연결하면 문제가 발생합니다. 여기에 내 코드가 있는데, 지금은 컴파일되지 않습니다. 지금은 ACCOUNT_DATA_COLS = 1을 가장하는 것이 좋습니다.

void Dialog::create_spinbox_column(const int &NUM_ROWS, QFrame *&frame, 
            QLabel **label_arr, 
            QSpinBox **spinbox_arr, 
            void (*callback_function)(int, int)) { 
    frame = new QFrame(); 
    QGridLayout *layout = new QGridLayout; 
    for(int i = 0; i < NUM_ROWS; i++) { 
     int row = i+1; 
     QString label_text = QObject::tr("Line %1:").arg(row); 
     label_arr[i] = new QLabel(label_text); 
     spinbox_arr[i] = new QSpinBox; 
     layout->addWidget(label_arr[i], row, 1); 
     layout->addWidget(spinbox_arr[i], row, 2); 
     //QObject::connect(spinbox_arr[i], SIGNAL(valueChanged(int)), this, 
     //    [=](int value) { callback_function(i, value); }; 
    } 
    frame->setLayout(layout); 
} 

(나는 컴파일러 오류가 발생했기 때문에 나는 연결 라인에서 댓글을 달았습니다.)

void Dialog::create_account_data_grid() { 
    account_data_box = new QGroupBox(tr("Account Data")); 
    QHBoxLayout *layout = new QHBoxLayout; 
    for (int i = 0; i < ACCOUNT_DATA_COLS; i++) { 
     QFrame *frame; 
     QLabel *label_arr[ACCOUNT_DATA_ROWS]; 
     QLabel *spinbox_arr[ACCOUNT_DATA_ROWS]; 
     create_spinbox_column(ACCOUNT_DATA_ROWS, frame, label_arr, spinbox_arr, 
           callback_with_id); 
     // int col = i + 1; 
     layout->addWidget(frame); 
    } 
    account_data_box->setLayout(layout); 
} 

내 콜백 함수 :

void Dialog::callback_with_id(int id, int value) { 
    std::cout << "callback_with_id(" << value << ", " << id << ")" << std::endl; 
} 

나는 오류

받고 있어요
error: no matching function for call to 'Dialog::create_spinbox_column(const int&, QFrame*&, QLabel* [8], QLabel* [8], <unresolved overloaded function type>)' 
           callback_with_id); 
              ^

나는 여기에서 한 가지 이상을 잘못하면 모든 의견에 감사하게 될 것입니다.

+0

당신이하고있는 방법은 Qt에서보기 드문 것 같습니다. – drescherjm

+0

당신의 함수'void Dialog :: callback_with_id'는'static' 클래스 여야 만합니다. 그렇지 않으면 [멤버 함수에 대한 포인터]를 전달해야합니다 (https://stackoverflow.com/questions/2402579/function-pointer- 회원 기능으로). –

답변

3

"런타임"(SIGNALSLOT 매크로 사용)과 "컴파일 타임"(호출 가능 코드를 직접 전달할 수있는)의 두 가지 연결 스타일을 혼합하는 경우 주석 처리 된 줄의 문제는 " .

보통 후자의 구문은

QObject::connect(spinbox_arr[i], &QSpinBox::someSignal, this, 
       [=](int value) { callback_function(i, value); }; 

하지만 당신은 두 개의 오버로드를 가지고로 따라서 당신이 qOverload를 사용하는, 그래서 그 결과 코드는 다음과 같을 것이다, 직접 valueChanged 신호에 대해이 작업을 수행 할 수 없습니다 :

QObject::connect(spinbox_arr[i], qOverload<int>(&QSpinBox::valueChanged), this, 
       [=](int value) { callback_function(i, value); }; 

일부 C++ 14 지원이 필요합니다. 사용할 수 없으면 대신 QOverload<int>::of(&QSpinBox::valueChanged)을 사용해야합니다. ,

  1. callback_with_id 정적 기능이
  2. 또는 펑터 유형에 템플릿 create_spinbox_column을,
  3. 을하거나 마지막 변경 : 코멘트에 지적

    또한, 하나 확인을 매개 변수는 create_spinbox_column에서 std::function<void(int, int)>이고 호출 사이트에서 람다 캡처 this을 전달합니다.

이 점에 대해 자세히 설명해 주시겠습니까?

+0

니스, 도움이 될 것 같습니다, 나는 일하게 될 것이고 그것이 어떻게 진행되는지 알려줄 것입니다! – Apollys

+0

콜백에 대한 한 가지 더 많은 문제가 제 코드를 업데이트 할 것이라고 거의 생각합니다. – Apollys