2015-10-16 3 views
0

В течение двух дней я пытаюсь понять, почему разные слоты вызываются одной и той же кнопкой в ​​моем приложении. Я гугле много о предмете, но в основном то, что I found был относительно уникального SLOT называют несколько раз по той же кнопке, которая решается при добавлении пятого параметра Qt::UniqueConnection на подключения вызова т.е.Как разные слоты вызываются одной и той же кнопкой?

подключения (объект, СИГНАЛ (сигнал()), obj2, SLOT (слот()), Qt :: UniqueConnection);

Продолжая, моя проблема в том, что одна и та же кнопка вызывает разные слоты, если это не так. Я создал общий код для установки все мои кнопки:

void KHUB::btSetupInt(QPushButton **button, const QString name, int posX, int posY, int width, int height, void (KHUB::*fptr)(int parameter), int value, int handler) { 
    *button = new QPushButton(name, this); 
    (*button)->setGeometry(QRect(QPoint(posX, posY), QSize(width, height))); 

    signalMapper->setMapping(*button, value); 
    connect(*button, SIGNAL(clicked()), signalMapper, SLOT(map())); 
    //qDebug() << "My value: " + QString::number(value); 

    switch (handler) { 
    case (int) ButtonHandler::hl_Register: 
     connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleRegister(int)), Qt::UniqueConnection); 
     break; 
    case (int)ButtonHandler::hl_UpVote: 
     connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleUpVote(int)), Qt::UniqueConnection); 
     break; 
    case (int) ButtonHandler::hl_OpenUrl: 
     //connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleUrl(int)), Qt::UniqueConnection); 
     break; 
    case (int)ButtonHandler::hl_DownVote: 
     connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleDownVote(int)), Qt::UniqueConnection); 
     break; 
    case (int) ButtonHandler::hl_DisposeBrowser: 
     connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleDispose(int)), Qt::UniqueConnection); 
     break; 
    } 
} 

В этом у меня есть мой signalMapper который объявлен в моем файле заголовка. Эта настройка кнопки вызывается по:

void KHUB::handleSearch() { 
    //DO THE MATH 
    for (int pos = 0; pos < localUrl.size(); pos++){ 
    QLabel *link = new QLabel(); 
    link->setText("<a href=\"" + localUrl.at(pos) + "\">" + localUrl.at(pos) + "</a>"); 
    link->setTextFormat(Qt::RichText); 
    link->setTextInteractionFlags(Qt::TextBrowserInteraction); 
    link->setOpenExternalLinks(true); 

    QPushButton *upArrow = new QPushButton(); 
    btSetupInt(&upArrow, "Up Vote", 225, 300, 100, 25, &KHUB::handleUpVote, pos*147, (int)ButtonHandler::hl_UpVote); 

    QPushButton *open = new QPushButton("Open"); 
    //btSetupInt(&open, "Open", 225, 300, 100, 25, &KHUB::handleUrl, pos, (int) ButtonHandler::hl_OpenUrl); 

    QPushButton *downArrow = new QPushButton(); 
    btSetupInt(&downArrow, "Down Vote", 225, 300, 100, 25, &KHUB::handleDownVote, pos*163, (int)ButtonHandler::hl_DownVote); 

    QLabel *separator = new QLabel(); 
    QLabel *guider = new QLabel("<----------------------------------------------------------------------------------------------------------------------------------------------------->"); 

    gridLayout->addWidget(link, componentsPos, 0, 1, -1); 
    gridLayout->addWidget(guider, componentsPos, 1, 1, -1); 
    gridLayout->addWidget(upArrow, componentsPos - 1, 2, 1, 1, Qt::AlignBottom); 
    gridLayout->addWidget(open, componentsPos, 2, 1, 1); 
    gridLayout->addWidget(downArrow, componentsPos + 1, 2, 1, 1, Qt::AlignTop); 
    gridLayout->addWidget(separator, componentsPos + 2, 1, 1, 1); 

    componentsPos = componentsPos + 5; 
    } 
    //KEEP DOING THE MATH 
} 

Прокомментированные строки как для целей отладки. Во всяком случае, этот код полностью работал, когда у меня был только open QPushButton. Когда добавлено upVote и downVote Я ожидал, что программа реплицирует свой логический успех, вместо этого, теперь, когда я нажимаю кнопку «Вверх», вы пропустите голосование. Программа запускает оба слота для обработки Up и Down votin, а также «Open», если не прокомментировать. Код для обработки вверх и вниз Голосов:

void KHUB::handleUpVote(int reference) { 
    qDebug() << "This is my reference for upvoting: " + QString::number(reference/147); 
} 

void KHUB::handleDownVote(int reference) { 
    qDebug() << "This is my reference for DOWNVOTING: " + QString::number(reference/163); 
} 

Согласно Qt QSignalMapper documentation (Тема «Дополнительные сигналы и слоты Использование» на стр который заканчивается) я делаю все, как и ожидалось. Вы также должны были заметить, что я умножил pos на btSetupInt называть 147 и 163 (для создания «случайного» номера) с every button must have its only integer ID [см. SetMapping для целых чисел void QSignalMapper::setMapping(QObject * sender, int id)].

Дней тому назад я использовал ту же позицию (pos) для трех из них (кнопок), и умножилось или нет произведенный результат. Это приводит меня к моему первому вопросу:Этот идентификатор является уникальным идентификатором для каждой кнопки или уникальным параметром, который может быть передан кнопкой? Я все еще не получил это, учитывая контекст, который я дал выше

Это мой UI:

Application UI

Это мой выходной щелчок (случайная ссылка Выбирается) Up голосов на us.battle.net/wow/en/blog/19913791/patch-623-preview-10-14-2015:

"This is my reference for upvoting: 3" 
"This is my reference for DOWNVOTING: 3" 

Это мой выходной щелчок (случайная ссылка Выбирается) Вниз голосование на http://www.swtor.com/holonet/companions/blizz:

"This is my reference for upvoting: 6" 
"This is my reference for DOWNVOTING: 6" 

Я использовал точки останова, чтобы проверить, правильно ли вызывается переключатель handler на btSetupInt. Даже не используя мою функцию-член btSetupInt для вызова соединений, я все равно получаю одинаковые неверные результаты. Чтобы закончить, мой второй и главный вопрос: Как возможно, в данном контексте, что одна и та же кнопка вызывает разные слоты? Что мне здесь не хватает?

+0

перед подключением к новому разъему необходимо отсоединить его от предыдущего. Тогда все будет хорошо работать. – johngull

+0

Просветите меня, пожалуйста, я получил ваши слова, но не знаю вообще. Как я должен это делать? Быстрое исследование google было бы чем-то вроде 'button-> disconnect (SIGNAL (signal))' в конце моего переключателя? –

ответ

1

Поскольку вы подключаете блок отображения сигналов несколько раз, то есть для каждого экземпляра кнопки. Вы создаете кнопку, а затем в зависимости от handler вы подключаетесь к другому слоту. Сигнал mapped(int) сигнала картографа подключен к нескольким слотам. Надеюсь, у тебя есть то, что я говорю здесь.

Другие проблемы с кодом - утечка памяти.

QPushButton *upArrow = new QPushButton(); 
btSetupInt(&upArrow, "Up Vote", 225, 300, 100, 25, &KHUB::handleUpVote, pos*147, (int)ButtonHandler::hl_UpVote); 

btSetupInt() создает новую кнопку. Еще раз.

*button = new QPushButton(name, this); 

Это непроверенный код. проверьте, работает ли он.

// custom button claas 
class VotingButton : public QPushButton 
{ 
    Q_OBJECT 

public: 
    VotingButton(const QString& url, int voteType, QObject* prnt=0) 
     : QPushButton(prnt) 
      m_url(url), 
      m_voteType(voteType) 
    {} 

    QString getUrl() const { return m_url; } 
    int getVoteType() const { return m_voteType; } 

private: 
    QString  m_url; 
    int   m_voteType; 
} 

в вашем KHUB классе

connect(signalMapper, SIGNAL(mapped(QObject*)), this, SLOT(handleButtonPress(QObject*))); 

void KHUB::btSetupInt(QPushButton* button, const QString& name, int posX, int posY, int width, int height, const QString& url, int handler) { 
    button = new VotingButton(url, handler, this); 
    button->setText(name); 
    button->setGeometry(QRect(QPoint(posX, posY), QSize(width, height))); 
    signalMapper->setMapping(button, this); 
    connect(button, SIGNAL(clicked()), signalMapper, SLOT(map())); 
} 

void KHUB::handleSearch() { 
    //DO THE MATH 
    for (int pos = 0; pos < localUrl.size(); pos++){ 
    QLabel *link = new QLabel(); 
    link->setText("<a href=\"" + localUrl.at(pos) + "\">" + localUrl.at(pos) + "</a>"); 
    link->setTextFormat(Qt::RichText); 
    link->setTextInteractionFlags(Qt::TextBrowserInteraction); 
    link->setOpenExternalLinks(true); 

    QPushButton *upArrow; 
    btSetupInt(upArrow, "Up Vote", 225, 300, 100, 25, localUrl.at(i), (int)ButtonHandler::hl_UpVote); 

    QPushButton *open; 
    btSetupInt(open, "Open", 225, 300, 100, 25, localUrl.at(i), (int)ButtonHandler::hl_OpenUrl);  

    QPushButton *downArrow; 
    btSetupInt(downArrow, "Down Vote", 225, 300, 100, 25, localUrl.at(i), (int)ButtonHandler::hl_DownVote); 

    QLabel *separator = new QLabel(); 
    QLabel *guider = new QLabel("<----------------------------------------------------------------------------------------------------------------------------------------------------->"); 

    gridLayout->addWidget(link, componentsPos, 0, 1, -1); 
    gridLayout->addWidget(guider, componentsPos, 1, 1, -1); 
    gridLayout->addWidget(upArrow, componentsPos - 1, 2, 1, 1, Qt::AlignBottom); 
    gridLayout->addWidget(open, componentsPos, 2, 1, 1); 
    gridLayout->addWidget(downArrow, componentsPos + 1, 2, 1, 1, Qt::AlignTop); 
    gridLayout->addWidget(separator, componentsPos + 2, 1, 1, 1); 

    componentsPos = componentsPos + 5; 
    } 
    //KEEP DOING THE MATH 
} 

void KHUB::handleButtonPress(QObject* obj) 
{ 
    VotingButton* voteButton = static_cast<VotingButton*>(obj); 
    if (voteButton) { // now you have voteType and the url assigned to the button 
     switch (voteButton->getVoteType()) 
     { 
      case ... 
     } 
    } 
} 
+0

Я очень ценю ваш ответ, спасибо; Но мне понадобится несколько часов, пока я не смогу проверить это, у меня есть экзамен завтра, и как только я смогу, я вернусь, чтобы ответить, что произошло –

0

Насколько я понял на основе ответа ramtheconqueror, вы не можете использовать ту же карту для подключения различных слотов. В моем коде я использовал signalMapper для подключения к различным обработчикам (слотам), и, чтобы решить это, я просто добавил параметр QSignalMapper в btSetupInt. Я создал три разных карты для каждого типа кнопки, чтобы предоставить карту, на которую я хотел бы подключить слот.

Мой код будет выглядеть так:

void KHUB::btSetupInt(QPushButton **button, const QString name, int posX, int posY, int width, int height, void (KHUB::*fptr)(int parameter), QSignalMapper* map, int value, int handler) { 
    *button = new QPushButton(name, this); 
    (*button)->setGeometry(QRect(QPoint(posX, posY), QSize(width, height))); 

    map->setMapping(*button, value); 
    connect(*button, SIGNAL(clicked()), map, SLOT(map())); 
    //qDebug() << "My value: " + QString::number(value); 

    switch (handler) { 
    case (int) ButtonHandler::hl_Register: 
     connect(map, SIGNAL(mapped(int)), this, SLOT(handleRegister(int)), Qt::UniqueConnection); 
     break; 
    case (int)ButtonHandler::hl_UpVote: 
     connect(map, SIGNAL(mapped(int)), this, SLOT(handleUpVote(int)), Qt::UniqueConnection); 
     break; 
    case (int) ButtonHandler::hl_OpenUrl: 
     //connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(handleUrl(int)), Qt::UniqueConnection); 
     break; 
    case (int)ButtonHandler::hl_DownVote: 
     connect(map, SIGNAL(mapped(int)), this, SLOT(handleDownVote(int)), Qt::UniqueConnection); 
     break; 
    case (int) ButtonHandler::hl_DisposeBrowser: 
     connect(map, SIGNAL(mapped(int)), this, SLOT(handleDispose(int)), Qt::UniqueConnection); 
     break; 
    } 
} 

    void KHUB::handleSearch() { 
    //DO THE MATH 
    upVoteMap = new QSignalMapper(this); 
    downVoteMap = new QSignalMapper(this); 
    openMap = new QSignalMapper(this); 

    for (int pos = 0; pos < localUrl.size(); pos++){ 
    QLabel *link = new QLabel(); 
    link->setText("<a href=\"" + localUrl.at(pos) + "\">" + localUrl.at(pos) + "</a>"); 
    link->setTextFormat(Qt::RichText); 
    link->setTextInteractionFlags(Qt::TextBrowserInteraction); 
    link->setOpenExternalLinks(true); 

    QPushButton *upArrow; 
    btSetupInt(&upArrow, "Up Vote", 225, 300, 100, 25, &KHUB::handleUpVote, upVoteMap, pos, (int)ButtonHandler::hl_UpVote); 

    QPushButton *open; 
    btSetupInt(&open, "Open", 225, 300, 100, 25, &KHUB::handleUrl, openMap, pos, (int) ButtonHandler::hl_OpenUrl); 

    QPushButton *downArrow; 
    btSetupInt(&downArrow, "Down Vote", 225, 300, 100, 25, &KHUB::handleDownVote, downVoteMap, pos, (int)ButtonHandler::hl_DownVote); 

    QLabel *separator = new QLabel(); 
    QLabel *guider = new QLabel("<----------------------------------------------------------------------------------------------------------------------------------------------------->"); 

    gridLayout->addWidget(link, componentsPos, 0, 1, -1); 
    gridLayout->addWidget(guider, componentsPos, 1, 1, -1); 
    gridLayout->addWidget(upArrow, componentsPos - 1, 2, 1, 1, Qt::AlignBottom); 
    gridLayout->addWidget(open, componentsPos, 2, 1, 1); 
    gridLayout->addWidget(downArrow, componentsPos + 1, 2, 1, 1, Qt::AlignTop); 
    gridLayout->addWidget(separator, componentsPos + 2, 1, 1, 1); 

    componentsPos = componentsPos + 5; 
    } 
    //KEEP DOING THE MATH 
} 

Я считаю, что решение ramtheconqueror была бы работать, и наверняка это фантазер, чем у меня, хотя это не применимо в моем случае, так как я работаю над диссертацией и для доказательства моего POV мне нужно создать ограниченное количество классов, которые были предварительно установлены.

В любом случае, я буду считать его ответ правильным, потому что без него я не пойму свой ответ.

К сожалению, у меня до сих пор нет ответа на мой первый вопрос, но я надеюсь, что в целом это поможет кому-то в будущем.

Cheers

 Смежные вопросы

  • Нет связанных вопросов^_^