Get index of QPushButton on 2D array QPushButton

前端 未结 2 791
忘了有多久
忘了有多久 2020-11-29 12:28

I have an 2D array QPushButton, how can I get index of the button when user clicks on its? such as When user clicks on the button a[2][3] it will s

相关标签:
2条回答
  • 2020-11-29 13:12

    The example looks like this:

    screenshot

    Qt 4/5 Using Object Names

    You can give your buttons unique object names. The names should ideally be valid C++ identifiers.

    // https://github.com/KubaO/stackoverflown/tree/master/questions/button-grid-22641306
    #include <QtGui>
    #if QT_VERSION_MAJOR >= 5
    #include <QtWidgets>
    #endif
    
    struct Display : QLabel {
       Q_SLOT void onClicked() {
          auto const elements = sender()->objectName().split('_');
          auto const i = elements.at(1).toInt();
          auto const j = elements.at(2).toInt();
          setText(QString{"(%1,%2)"}.arg(i).arg(j));
       }
       Q_OBJECT
    };
    
    int main(int argc, char *argv[])
    {
       QApplication a{argc, argv};
       QWidget window;
       QGridLayout layout{&window};
       QVarLengthArray<QPushButton, 12> buttons(12);
       Display display;
    
       const int rows = 4, columns = 3;
       for (int i = 0; i < rows; ++ i)
          for (int j = 0; j < columns; ++j) {
             auto & button = buttons[i*columns+j];
             button.setText(QString{"(%1,%2)"}.arg(i).arg(j));
             button.setObjectName(QString{"buton_%1_%2"}.arg(i).arg(j));
             layout.addWidget(&button, i, j);
             display.connect(&button, SIGNAL(clicked()), SLOT(onClicked()));
          }
       layout.addWidget(&display, rows, 0, 1, columns);
    
       window.show();
       return a.exec();
    }
    #include "main.moc"
    

    Qt 5 - Using Lambdas

    In Qt 5 and C++11, you should use functors to generate custom slot for each button, on the fly. For example:

    // https://github.com/KubaO/stackoverflown/tree/master/questions/button-grid-22641306
    #include <QtWidgets>
    
    int main(int argc, char *argv[])
    {
       QApplication a{argc, argv};
       QWidget window;
       QGridLayout layout{&window};
       QVarLengthArray<QPushButton, 12> buttons(12);
       QLabel display;
    
       const int rows = 4, columns = 3;
       for (int i = 0; i < rows; ++ i)
          for (int j = 0; j < columns; ++j) {
             auto text = QStringLiteral("(%1,%2)").arg(i).arg(j);
             auto & button = buttons[i*columns+j];
             button.setText(text);
             layout.addWidget(&button, i, j);
             QObject::connect(&button, &QPushButton::clicked, [&display, text] {
                display.setText(text);
             });
          }
       layout.addWidget(&display, rows, 0, 1, columns);
    
       window.show();
       return a.exec();
    }
    

    Qt 4/5 - Using QSignalMapper

    QSignalMapper is pretty much designed for what you want. It lets you map a QObject* to "something else", like a string. For example:

    #include <QtGui>
    #if QT_VERSION_MAJOR >= 5
    #include <QtWidgets>
    #endif
    
    int main(int argc, char *argv[])
    {
       QApplication a{argc, argv};
       QSignalMapper mapper;
       QWidget window;
       QGridLayout layout{&window};
       QVarLengthArray<QPushButton, 12> buttons(12);
       QLabel display;
    
       const int rows = 4, columns = 3;
       for (int i = 0; i < rows; ++ i)
          for (int j = 0; j < columns; ++j) {
             auto text = QString{"(%1,%2)"}.arg(i).arg(j);
             auto & button = buttons[i*columns+j];
             button.setText(text);
             layout.addWidget(&button, i, j);
             mapper.connect(&button, SIGNAL(clicked()), SLOT(map()));
             mapper.setMapping(&button, text);
          }
       display.connect(&mapper, SIGNAL(mapped(QString)), SLOT(setText(QString)));
       layout.addWidget(&display, rows, 0, 1, columns);
    
       window.show();
       return a.exec();
    }
    

    Qt 4/5 - Using the Property System

    You can leverage the fact that a QWidget is a QObject. QObjects have a property system, so you can set each button's index as a property, and then retrieve it in the slot connected to the clicked() signal. For example:

    #include <QtGui>
    #if QT_VERSION_MAJOR >= 5
    #include <QtWidgets>
    #endif
    
    const char kIndex[] = "index";
    struct Display : QLabel {
       Q_SLOT void onClicked() {
          setText(sender()->property(kIndex).toString());
       }
       Q_OBJECT
    };
    
    int main(int argc, char *argv[])
    {
       QApplication a{argc, argv};
       QWidget window;
       QGridLayout layout{&window};
       QVarLengthArray<QPushButton, 12> buttons(12);
       Display display;
    
       const int rows = 4, columns = 3;
       for (int i = 0; i < rows; ++ i)
          for (int j = 0; j < columns; ++j) {
             auto index = QString{"(%1,%2)"}.arg(i).arg(j);
             auto & button = buttons[i*columns+j];
             button.setText(index);
             button.setProperty(kIndex, index);
             layout.addWidget(&button, i, j);
             display.connect(&button, SIGNAL(clicked()), SLOT(onClicked()));
          }
       layout.addWidget(&display, rows, 0, 1, columns);
    
       window.show();
       return a.exec();
    }
    #include "main.moc"
    
    0 讨论(0)
  • 2020-11-29 13:23

    in general, you would have to loop over the array and test the event target for equality with each element until you reach the correct index

    0 讨论(0)
提交回复
热议问题