Как использовать QSignalMapper для сопоставления целых чисел с цифрами?

У меня проблемы с простым приложением в Qt. Приложение выглядит как простой калькулятор с кнопками (цифры от 0 до 9).

После нажатия кнопки приложение должно отобразить на выходе приложения соответствующее число в виде цифры и в виде цифры (слова).

Мне нужно использовать QSignalMapper. Как я могу это решить?

Мой код до сих пор:

QLayout* Widget::createButtons()
{
    QGridLayout     *lt = new QGridLayout(this);
    QSignalMapper   *signalMapper = new QSignalMapper(this);

    connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(keyPressed(int)));

    QString txtButtons[10] = {"zero", "one", "two", 
                              "three", "four", "five",
                              "six", "seven", "eight", 
                              "nine"};

    for(int i=0; i<10; i++) {

        buttons[i] = new QPushButton(txtButtons[i], this);
        signalMapper->setMapping(buttons[i], i);
        connect(buttons[i], SIGNAL(clicked()), signalMapper, SLOT(map()));
        lt->addWidget(buttons[i], i/3, i%3);
    }

    return lt;
}

void Widget::keyPressed(int buttonID)
{
    qDebug() << QString::number(buttonID) + " was clicked";
}

person pank_94    schedule 27.05.2016    source источник
comment
Вы читали документацию?   -  person rbaleksandar    schedule 28.05.2016
comment
Да, я написал эту строку кода, например: button9 = new QPushButton(tr("9"), this); connect(button9, SIGNAL(clicked(bool)), m, SLOT(map())); m->setMapping(button0, 9);   -  person pank_94    schedule 28.05.2016
comment
Пожалуйста, указывайте свой код в сообщении, а не в разделе комментариев. Чем больше полезной информации вы предоставите (особенно фрагментов кода), тем лучше и быстрее придет ответ.   -  person rbaleksandar    schedule 28.05.2016
comment
Это классное задание? В Qt 5 вам больше не нужно использовать преобразователь сигналов :) Даже в Qt 4 вам не нужно, вы можете назначить каждой кнопке динамическое свойство, указывающее число/слово.   -  person Kuba hasn't forgotten Monica    schedule 28.05.2016
comment
хорошо, мой код немного изменился   -  person pank_94    schedule 28.05.2016
comment
Ваш код работает нормально, каков ваш вопрос?   -  person m. c.    schedule 28.05.2016
comment
После нажатия кнопки приложение должно отображать на выходе приложения соответствующее число в виде цифры и в виде слова. Например: 0, ноль Мой код отображает только: 0   -  person pank_94    schedule 28.05.2016
comment
Я вижу, в qt не существует способа перевести число в слово, в ответе ниже есть одно из возможных решений. Ваш код SignalMapper работает.   -  person m. c.    schedule 28.05.2016
comment
@Kuba: Пожалуйста, уточните: каким образом Qt5 делает QSignalMapper устаревшим? Как добавить динамическое свойство в Qt4?   -  person Silicomancer    schedule 28.05.2016
comment
@Silicomancer Смотрите дубликат.   -  person Kuba hasn't forgotten Monica    schedule 31.05.2016


Ответы (2)


См. этот вопрос для трех способов сопоставления одного из множества объектов со значением. Использование QSignalMapper не обязательно в Qt 5 и необязательно в Qt 4.

Ниже приведен пример использования QSignalMapper в Qt4/5. При использовании QSignalMapper следует помнить о трех моментах:

  1. Используйте метод setMapping, чтобы добавить сопоставление между экземпляром отправителя QObject и значением (целым числом, строкой и т. д.).

  2. Подключите сигнал отправителя к слоту map в картографе.

  3. Подключите сигнал mapped(ValueType) преобразователя к потребителю отображения. ValueType — это тип, на который вы сопоставляете — здесь это будет QString.

скриншот примера

// https://github.com/KubaO/stackoverflown/tree/master/questions/button-grid-37492290
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
const QString numerals[] = {"zero", "one", "two", "three", "four", "five", "six", "seven",
                            "eight", "nine", "ten"};

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   QWidget w;
   QGridLayout layout{&w};
   QLabel label;
   QSignalMapper mapper;
   QPushButton buttons[10];
   for (int i = 0; i < 10; ++i) {
      auto n = qMax(7-(3*(i/3))+i%3, 0); // numpad layout
      auto & button = buttons[i];
      button.setText(QString::number(n));
      mapper.setMapping(&button, QString("%1 - %2").arg(n).arg(numerals[n]));
      mapper.connect(&button, SIGNAL(clicked(bool)), SLOT(map()));
      layout.addWidget(&button, 1+i/3, i%3, 1, n > 0 ? 1 : 3);
   }
   layout.addWidget(&label, 0, 0, 1, 3);
   label.connect(&mapper, SIGNAL(mapped(QString)), SLOT(setText(QString)));
   w.show();
   return app.exec();
}
person Kuba hasn't forgotten Monica    schedule 31.05.2016

QString::number(buttonID) отображает только текст в виде числа, но не печатает это число в слове. Для печати одним словом вы можете переработать свой QString txtButtons[]:

QString txtButtons[10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

(Это должно быть txtButtons[9], 0 тоже считается! Но вы могли бы использовать QStringList лучше http://doc.qt.io/qt-4.8/qstringlist.html)

Возьмите эти слова для отображения после номера:

void Widget::keyPressed(int buttonID)
{
    qDebug() << QString::number(buttonID) + ", " + **txtButtons[buttonID]** + " was clicked";
}
person DYangu    schedule 27.05.2016
comment
Итак, я должен объявить QString txtButtons[] членом класса. - person pank_94; 28.05.2016
comment
Я не могу инициализировать массив QString :( - person pank_94; 28.05.2016
comment
Вам лучше использовать QStringList: - person DYangu; 28.05.2016
comment
Да, объявите этот QStringList в вашем файле .h (но только объявите, не инициализируйте) и инициализируйте его следующим образом (замените массив QString этим): QStringList txtButtons ‹‹ ноль ‹‹ один ‹‹ два ‹‹ три ‹‹ четыре ‹‹ пять ‹‹ шесть ‹‹ семь ‹‹ восемь ‹‹ девять; - person DYangu; 28.05.2016
comment
Хорошо спасибо. Это работает. Я взял слова для отображения следующим образом: void Widget::keyPressed(int buttonID) { qDebug() << "Button clicked: " << buttons[buttonID]->text().trimmed() << " with ID " << buttonID; } Как я могу объявить этот QStringList как указатель, например: QStringList *txtButtons; - person pank_94; 28.05.2016
comment
Этот раздел может помочь вам в использовании QStringList в качестве указателя: stackoverflow.com/questions/19178815/ - person DYangu; 28.05.2016