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 ответа
В таких ситуациях у вас есть три простых варианта:
- подключите каждый QAction к своему собственному слоту (не хорошо)
- использовать QSignalMapper
- добавьте каждую 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.