Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: xintrea от Август 24, 2008, 22:25



Название: QAction и вызов слота с параметром. Как сделать?
Отправлено: xintrea от Август 24, 2008, 22:25
Здравствуйте!


Мне нужно сделать таку вещь - создать контекстное меню (на виджете QListView) и вызывать один и тот же слот с разными параметрами. Ну то есть хотелось бы вместо создания отдельного слота на каждый пункт меню, иметь "общие" слоты, которые вызываются с параметром.

Ниже дан код (нерабочий), и хотелось бы понять, как сделать его рабочим.

Код:
  // Обычное добавление записи в конец списка
  a = new QAction(tr("Add new"), this);
  connect(a, SIGNAL(triggered()),
            this,SLOT(recordview_add_new_context(ADD_NEW_RECORD_TO_END)));
  menu.addAction(a);

  // Добавление записи до
  a = new QAction(tr("Add new before"), this);
  if((!recordview->selectionModel()->hasSelection()) ||
     (recordview->selectionModel()->selectedRows()).size()!=1 )
   a->setEnabled(false); // Пункт активен только если выбрана одна строка списка
  connect(a, SIGNAL(triggered()),
            this,SLOT(recordview_add_new_context(ADD_NEW_RECORD_BEFORE)));
  menu.addAction(a);


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: ритт от Август 25, 2008, 00:17
читай документацию по QAction и QMenu


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: lit-uriy от Август 25, 2008, 05:26
типы параметров у слота и сигнала должны совпадать


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: xintrea от Август 25, 2008, 15:43
читай документацию по QAction и QMenu

Спасибо за ответ! Он мне очень помог, теперь я точнее знаю, какие вещи в QT выше моего понимания!

Сделал по-простому, "один пункт меню"->"один слот".


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: EhTemka от Август 25, 2008, 17:28
Если будеш пользоваться QMenu или QActionGroup у них есть сигнал  void triggered ( QAction * action ), который соединяешь с одним слотом. А уже в слоте проверяешь, что за экшн передался такой  ;)

код примерно так будет выглядеть

Код:
QMenu *menu = new QMenu(this);
QAction *add = menu->addAction(tr("Add new"));
QAction *addBefor = menu->addAction(tr("Add new before"));

connect(menu , SIGNAL(triggered(QAction *)),
            this,SLOT(callAction(QAction *)));

Если пользуешся енамами можно добавить : add->setData(ADD_NEW_RECORD_TO_END) и т.д.
а уже в слоте проверять : if (action.data().toInt() == ADD_NEW_RECORD_TO_END) {...} и т.д.



Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: mks56 от Сентябрь 02, 2008, 09:38
to xintrea

А по-моему, самое простое - создать единый слот БЕЗ ПАРАМЕТРА для всех нужных пунктов меню, присоединить к нему нужные АКЦИИ, а внутри слота проверять sender() на предмет совпадения с нужной АКЦИЕЙ.


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: ритт от Сентябрь 02, 2008, 10:25
to mks56

тогда нужно хранить указатели на все акшены - чтобы было с чем сравнивать сендер()

представляю это самое простое - в декларировании класса прописывать сотню переменных :)


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: zavulon от Сентябрь 23, 2008, 18:56
Это классическая проблема. Есть два пути решения:

1. Уже предлагавшийся с проверкой объекта-отправителя: QObject::sender():
     http://doc.trolltech.com/4.4/qobject.html#sender
Совет: у отправителя можно проверять его имя или другие свойства, например QObject::objectName().

2. Более универсальный способ: использование посредника QSignalMapper:
     http://doc.trolltech.com/4.4/qsignalmapper.html
В документации есть хороший пример. Вот здесь действительно можно добавить к сигналу свой собственный параметр, причем совершенно любого типа. У каждого вызывающего объекта значение этого параметра будет своим.


Название: Re: QAction и вызов слота с параметром. Как сделать?
Отправлено: ритт от Сентябрь 23, 2008, 19:48
фактически сигналмаппер - это карта [сендер=>дата]. в зависимости от сендера будет испускаться сигнал с опр. дата. параметр не любого типа.

а вот у QAction есть сеттер/геттер data, который можно было бы получать из сендера!
Код:
QAction* action = qobject_cast<QAction*>(sender());
if(action)
    (void)action->data();