I'm beginning in C++ and Qt. I have a matrix of QPushButtons and I want to handle the click event for them. Problem is I'm not being able to tell the slot the coordinates os the button in the array so that I can play with them. I've succeed in passing a integer to my slot, but not both coordinates. I'm not sure if I'm making myself clear enough... That's my problematic code:
for (int i = 0; i < mapSize_x; i++) {
for (int j = 0; j < mapSize_y; j++) {
buttonsArray[i][j] = new QPushButton();
ui->mainLayout->addWidget(buttonsArray[i][j], i, j);
connect(buttonsArray[i][j], SIGNAL(clicked()),
signalMapper, SLOT(map()));
signalMapper->setMapping(buttonsArray[i][j], i, j); // here
}
}
connect(signalMapper, SIGNAL(mapped(int, int)),
this, SLOT(buttonClick(int, int)));
setMapping only accepts two parameters, and I want to pass three. Is there a workaround? I've googled a lot and still can't find an answer. I've also tried to pass the QPushButton object instead of the coordinates, but unsuccessfully as well. Thanks in advance.
Consider using a QHash
to store your pushbuttons, keyed by the buttons themselves and pointing to a pair containing their row and column. You should then be able to set your mapping based on the widget pointer and then look up the associated row and column when the signal mapper emits its signal. For example, declare a class data member as follows:
QHash<QPushButton*, QPair<int, int> > buttonHash;
Then your code above could become
for (int i = 0; i < mapSize_x; i++) {
for (int j = 0; j < mapSize_y; j++) {
QPair<int, int> gridPair(i, j);
QPushButton* button = new QPushButton();
buttonHash.insert(button, gridPair);
ui->mainLayout->addWidget(button, i, j);
connect(button, SIGNAL(clicked()),
signalMapper, SLOT(map()));
signalMapper->setMapping(button, qobject_cast<QWidget*>(button));
}
}
connect(signalMapper, SIGNAL(mapped(QWidget*)),
this, SLOT(buttonClick(QWidget*)));
Finally, your buttonClick
slot would become the following:
void SomeClass::buttonClick(QWidget* widget) {
QPair<int, int> pair = buttonHash.value(qobject_cast<QPushButton*>(widget));
int myRow = pair.first;
int myColumn = pair.second;
...
}
There are also at least 2 other ways of tackling this problem:
QSignalMapper::setMapping(QObject*, const QString&)
. This would then require some logic to pull the row and column out of the string in the buttonClick
slot.QSignalMapper::setMapping(QObject*, int)
. This would require some logic to pull the row and column out of the integer in the buttonClick
slot.I won't go into detail about these other solutions because they're somewhat ugly. The solution I provided above remains the most intuitive.