Qt 5 назначить слот с параметрами QPushButton

у меня есть приложение Qt на C++, и я хочу назначить слот QPushButton. Но я хочу передать некоторые аргументы, потому что у меня есть несколько QPushButton, которые делают то же самое, поэтому я хочу одну функцию, но с параметром в ней, но Qt продолжает говорить мне, что нет такого слота. Может кто-нибудь сказать мне, почему и как я должен делать это?

спасибо заранее

в рамках .H-файл у меня есть: (это было в начале, но я изменил его в поиске проблема)

public slots:
    void handleButton(int row, int col);

затем в .cpp:

void fieldWindow::handleButton(int row, int col){
    cout << row << " " << col << endl;
}

и снова в том же самом .cpp:

connect(this->buttonsField[i][j], SIGNAL(released()), this, SLOT(handleButton(i,j)));

это делается в два вложенных цикла, так i и j четко определены.

и моя ошибка:

QObject::connect: No such slot fieldWindow::handleButton(i,j) in ..Proj1fieldwindow.cpp:41
QObject::connect:  (receiver name: 'fieldWindow')

Я что-то читал в интернете, что я должен сказать handleButton(int, int); но тогда как я должен передать аргументы ?

1 ответов


к сожалению, соединение Qt signal-slot не принимает никаких аргументов для передачи в слот при вызове сигнала. Это работает только в том случае, если сам сигнал предоставляет эти аргументы, но вы не можете добавить их в connect заявление.

но вы не единственный, кто хочет это сделать, поэтому в Qt есть класс, который делает почти что требуется: QSignalMapper. Экземпляр этого класса можно использовать в качестве "прокси" для соединения сигнал-слот: вы подключите (несколько) кнопок к слоту этого класса и подключите сигнал этого класса к целевому слоту. Затем для каждого экземпляра "отправителя" (в вашем случае кнопки) вы можете указать класс, какое значение добавить в вызываемый слот. Пример:

QPushButton * button1 = ...;
QPushButton * button2 = ...;

QSignalMapper mapper;

connect(button1, SIGNAL(released()), &mapper, SLOT(map()));
mapper.setMapping(button1, 42); // Number to be passed in the slot

connect(button2, SIGNAL(released()), &mapper, SLOT(map()));
mapper.setMapping(button2, 1337); // Number to be passed in the slot

connect(&mapper, SIGNAL(mapped(int)), this, SLOT(handleButton(int)));

к сожалению, как вы можете видеть, этот класс может обрабатывать только один параметр. Для вашего случая вы должны выбрать другой метод (я объяснил выше, если вы снова столкнетесь с подобной проблемой, но с одним int параметр.)

альтернатива, которая соответствует вашей проблеме полагаться на sender() в слот. Помните свое отображение в структуре данных, например

QMap<QObject*,int> rows;
QMap<QObject*,int> cols;

и открыть в слот, который занимает аргумент:

void fieldWindow::handleButton(){
    int row = rows[sender()];
    int col = cols[sender()];
    cout << row << " " << col << endl;
}

конечно, при инициализации пользовательского интерфейса, вы должны поместить соответствующие значения в эти карты. Или вы можете найти свою кнопку в существующем массиве buttonsField.

другой метод существует с Qt5 и C++11: вместо слота вы можете обрабатывать сигналы в лямбда-функции. Это будет выглядеть так (сигнал называется с использованием нового синтаксиса):

connect(this->buttonsField[i][j], &QPushButton::released, [=]{
    handleButton(i, j);
});

Если вам не нравится синтаксис лямбда, также можно использовать некоторые помощники из стандартной библиотеки для создания функтора вместо лямбды, или вы можете написать свой собственный класс функтора, но лично я нахожу лямбду очень читаемой.