Qt почти такие же записи в главном меню

Я использую библиотеку C++ Qt, и я хочу сделать что-то, что будет делать:

connect(actionB11, SIGNAL(triggered()), this, SLOT(SetSomething(1, 1)));
connect(actionB12, SIGNAL(triggered()), this, SLOT(SetSomething(1, 2)));
connect(actionB21, SIGNAL(triggered()), this, SLOT(SetSomething(2, 1)));
connect(actionB22, SIGNAL(triggered()), this, SLOT(SetSomething(2, 2)));

Приведенный выше код не работает, потому что функция SIGNAL должна иметь те же числа и типы аргументов, что и функция SLOT.

Существует ли способ, как это сделать? Я не хочу иметь около 20 функций, таких как SetSomething11, SetSomething12, вызывающих SetSomething (1, 1) и т. Д.

3 ответа

Решение

В таких ситуациях у вас есть три простых варианта:

  1. подключите каждый QAction к своему собственному слоту (не хорошо)
  2. использовать QSignalMapper
  3. добавьте каждую QAction в QActionGroup и используйте QActionGroup::triggered(QAction*) сигнал, в сочетании с настройкой данных каждого QAction (см. QAction::setData() а также QAction::data())

Когда вы устанавливаете данные для QAction, вы можете хранить только один QVariant (то есть одно значение). Поэтому, если вам нужны два значения, я бы порекомендовал просто создать простое отображение, например так:

void Window::onActionGroupTriggered(QAction *action);
{
    int i = action->data().toInt();
    int a, b;
    a = i / 10;
    b = i - 10;
    setSomething(a, b); // for example if i = 15, then a = 1 and b = 5
}

Вы не можете использовать константу в подписи SLOT, вы должны использовать типы там. При подключении сигнала к слоту у слота должно быть то же подмножество параметров, что и у сигнала, иначе они не могут быть подключены, и QObject::connect() вернет false.

connect(actionB11, SIGNAL(triggered()),
        this, SLOT(SetSomething()));

Этот слот не принимает параметров, но вы можете использовать QObject::sender(), чтобы получить указатель на объект, который испустил сигнал. Затем этот указатель можно использовать для различения источника сигнала:

void SetSomething() {
    switch(sender()) {
    case actionB11;
        // do something
        break;
    case actionB12;
        // do something
        break;
    case actionB21;
        // do something
        break;
    case actionB22;
        // do something
        break;
    default:
        // Exceptional situation
    }
}

В качестве альтернативы вы можете использовать QSignalMapper для добавления дополнительных различающих параметров в слоты.

Вы можете изменить класс QAction.

class QMyAction : public QAction
{
    Q_OBJECT
    QMyAction ( QObject * parent ) : 
    QAction(parent), _x(0), _y(0)
    {
         connect(this, SIGNAL(triggered(bool)), this, SLOT(re_trigger(bool)));
    } 
    QMyAction ( const QString & text, QObject * parent ) : 
    QAction (text, parent), _x(0), _y(0)
    {
         connect(this, SIGNAL(triggered(bool)), this, SLOT(re_trigger(bool)));
    }
    QMyAction ( const QIcon & icon, const QString & text, QObject * parent ) : 
    QAction(icon, text, parent), _x(0), _y(0)
    {
         connect(this, SIGNAL(triggered(bool)), this, SLOT(re_trigger(bool)));
    }
    void setX(int x)
    {
        _x = x;
    }
    int getX()
    {
        return _x;
    }
    void setY(int y)
    {
        _y = y;
    }
    int getY()
    {
        return _y;
    }

public slots:
    void re_trigger(bool)
    {
        emit triggered(_x, _y);
    }

signals:
    void triggered(int,int);

private:
    int _x;
    int _y;
};

Теперь вы можете подключить триггер (int,int) к SetSomething(int,int). Но вы должны установить х и у. Если только они не будут 0.

Другие вопросы по тегам