Получить индекс QPushButton для двумерного массива QPushButton
У меня есть 2D массив QPushButton
Как я могу получить индекс кнопки, когда пользователь нажимает на нее? например, когда пользователь нажимает на кнопку a[2][3]
это покажет (2,3)
?
2 ответа
Пример выглядит так:
Qt 4/5 Использование имен объектов
Вы можете дать своим кнопкам уникальные имена объектов. В идеале имена должны быть действительными идентификаторами C++.
// https://github.com/KubaO/stackrun/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 - Использование Lambdas
В Qt 5 и C++11 вы должны использовать функторы для генерации пользовательского слота для каждой кнопки на лету. Например:
// https://github.com/KubaO/stackrun/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 - Использование QSignalMapper
QSignalMapper
в значительной степени предназначен для того, что вы хотите. Это позволяет вам отобразить QObject*
"что-то еще", как строка. Например:
#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 - Использование системы свойств
Вы можете использовать тот факт, что QWidget
это QObject
, У объектов QObject есть система свойств, поэтому вы можете установить индекс каждой кнопки как свойство, а затем извлечь его в слоте, подключенном к clicked()
сигнал. Например:
#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"
В общем, вам придется циклически проходить по массиву и проверять цель события на равенство с каждым элементом, пока вы не достигнете правильного индекса