Как передать переменные методам слотов в QT?
Я создаю небольшую программу для обмена чатами, для которой нужен список каналов чата, к которым присоединился пользователь. Чтобы представить этот список графически, я составил список QPushButtons
, которые все представляют собой другой канал. Эти кнопки сделаны со следующим методом, и где моя проблема срабатывает:
void Messenger::addToActivePanels(std::string& channel)
{
activePanelsContents = this->findChild<QWidget *>(QString("activePanelsContents"));
pushButton = new QPushButton(activePanelsContents);
pushButton->setObjectName("pushButton");
pushButton->setGeometry(QRect(0, 0, 60, 60));
pushButton->setText("");
pushButton->setToolTip(QString(channel.c_str()));
pushButton->setCheckable(true);
pushButton->setChecked(false);
connect(pushButton, SIGNAL(clicked()), this, SLOT(switchTab(channel)));
}
(activePanelContents - это QWidget, который содержит список.)
Дело в том, что каждая кнопка должна вызывать метод switchTab(string& tabname)
при нажатии, включая конкретное имя канала как переменной. Однако эта реализация не работает, и я не смог выяснить, как правильно это сделать.
Ответы
Ответ 1
Для строк и целых чисел вы можете использовать QSignalMapper. В вашем классе Messenger
вы добавите объект QSignalMapper mapper
, и ваша функция будет выглядеть так:
void Messenger::addToActivePanels(std::string& channel)
{
activePanelsContents = this->findChild<QWidget *>(QString("activePanelsContents"));
pushButton = new QPushButton(activePanelsContents);
// ...
connect(pushButton, SIGNAL(clicked()), &mapper, SLOT(map()));
mapper.setMapping(pushButton, QString(channel.c_str()));
}
и после того, как вы добавили все каналы в активные панели, вы вызываете
connect(&mapper, SIGNAL(mapped(const QString &)), this, SLOT(switchTab(const QString &)));
Ответ 2
Используйте QSignalMapper
для передачи переменных;
QSignalMapper* signalMapper = new QSignalMapper (this) ;
QPushButton *button = new QPushButton();
signalMapper -> setMapping (button, <data>) ;
connect (signalMapper, SIGNAL(mapped(QString)), this,
SLOT(buttonClicked(QString))) ;
в слоте i.e
void class::buttonClicked(QString data){
//use data
// to get sender
QSignalMapper *temp = (QSignalMapper *)this->sender();
QPushButton *btn = (QPushButton *)temp->mapping(data);
// use btn
}
Надеюсь, что мои анны помогут вам
Ответ 3
Не используйте метод отправителя, если вам абсолютно не нужно. Он напрямую связывает функцию, которая используется только как слот (не может быть вызвана напрямую). Сохраните поведение функции, принимающей строку, и просто создайте механизм, с помощью которого вы можете его назвать.
Одним из способов, среди прочего, может оказаться использование QSignalMapper. Он будет отображать объекты в значения и регенерировать сигналы соответствующей сигнатуры.
Ответ 4
Я бы сделал это с объектами "relay":
Создайте TabSwitchRelay
, который является подклассом QObject
с этим конструктором:
TabSwitchRelay::TabSwitchRelay(QObject *parent, Messanger * m, const QString & c)
: QObject(parent), m_messanger(m), m_channel(c)
{
}
Он также имеет слот clicked()
:
void TabSwitchRelay::clicked()
{
m_messager->switchTab(m_channel);
}
Теперь замените строку в коде, который соединяется с этим:
TabSwitchRelay * tabRelay = new TabSwitchRelay(pushButton, this, channel);
connect(pushButton, SIGNAL(clicked()), tabRelay, SLOT(clicked()));
Он не тестировался, но вы получили основную идею.
Ответ 5
Вы можете попробовать, чтобы ваш слот switchTab
не принимал аргументов и использовал QObject::sender
, чтобы получить объект, который отправил сигнал.
Messenger::switchTab()
{
QObject* sender = this->sender();
QPushButton* button = qobject_cast<QPushButton*>(sender);
if(button)
{
// Do stuff...
}
}
Ответ 6
если вы используете Qt5, вы можете сделать это через лямбда:
connect( sender, &Sender::valueChanged, [=](){ myMethod(5); } );
void myMethod(int value)
{
// do stuff
}