Подтвердить что ты не робот

Как передать переменные методам слотов в 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) при нажатии, включая конкретное имя канала как переменной. Однако эта реализация не работает, и я не смог выяснить, как правильно это сделать.

4b9b3361

Ответ 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
}