Qt: адаптация сигналов / привязка аргументов к слотам? - PullRequest
3 голосов
/ 07 мая 2009

Есть ли способ привязать аргументы к слотам ala boost :: bind ?

Вот, к примеру, У меня есть окно с представлением дерева, и я хочу позволить пользователю скрыть столбец из контекстного меню. В итоге я делаю что-то вроде:

void MyWindow::contextMenuEvent (QContextMenuEvent* event) {
   m_column = view->columnAt (event->x());
   QMenu menu;
   menu.addAction (tr ("Hide Column"), this, SLOT (hideColumn ()));
   // .. run the menu, etc
}

Мне нужно захватить индекс столбца, по которому было активировано контекстное меню, и сохранить его в переменной-члене, которая используется в hideColumn слоте моего окна:

void MyWindow::hideColumn () {
    view->setColumnHidden (m_column, true);
}

Что мне действительно нравится, так это возможность привязывать номер столбца к моему слоту при создании меню, чтобы мне не нужна эта переменная-член. В основном эквивалент Qt:

menu.addAction (tr ("Hide Column"),
                boost::bind (&MyWindow::hideColumn, this,
                             event->columnAt (event->x()));

Или еще лучше, адаптируя сигнал QAction :: triggered и присоединяя его к слоту QTreeView :: hideColumn , который принимает индекс столбца в качестве аргумента:

menu.addAction (tr ("Hide Column"),
                boost::bind (&QTreeView::hideColumn, view,
                             event->columnAt (event->x())));

Можно ли что-нибудь из этого сделать?

Ответы [ 4 ]

6 голосов
/ 09 мая 2009

LibQxt делает это возможным через QxtBoundFunction и QxtMetaObject (первый почему-то не отображается в их документации ). Это проект с открытым исходным кодом, так что вы можете получить исходный код, если вы заинтересованы в реализации. Он использует следующий синтаксис:

connect(
    button,
    SIGNAL(clicked()),
    QxtMetaObject::bind(
        lineEdit,
        SLOT(setText(QString)),
        Q_ARG(QString, "Hello World!)
        )
    );

LibQxt имеет некоторые другие очень полезные функции, такие как возможность испускать сигналы через QIODevice , например, сетевое соединение.

6 голосов
/ 09 ноября 2012

Разве вы не можете использовать setData функцию QAction?

void MyWindow::contextMenuEvent (QContextMenuEvent* event)
{
    m_column = view->columnAt (event->x());
    QMenu menu;
    QAction * action = menu.addAction (tr ("Hide Column"), this, SLOT (hideColumn ()));
    action->setData(QVariant(hideColumn));
}

void hideColumn()
{
    const QAction * action = qobject_cast<const QAction *>(this->sender());
    assert(action);

    int hide_column = action->data().value<int>();
    this->view->setColumnHidden (m_column, true);
}
4 голосов
/ 07 мая 2009

AFAIK единственный способ - создать объект QSignalMapper для этого. Это похоже на дополнительный уровень косвенности, который можно использовать для генерации нового сигнала, обеспечивающего индекс столбца. Это немного неуклюжий IME, в конечном итоге вы можете получить множество объектов QSignalMapper, которые постоянно находятся вокруг, но, похоже, в настоящее время это лучший способ. (В идеале, IMO, вы можете просто указать любое значение, например индекс столбца, для connect (), которое будет передано в качестве аргумента в слот, но вы не можете.)

3 голосов
/ 29 января 2013

Как упомянуто в комментарии выше, это намного проще в Qt 5, так как вы можете подключить сигнал напрямую к функтору, такому как результат std :: tr1 :: bind () или boost :: bind (). Для Qt 4 существует несколько библиотек адаптеров. Калеб упомянул LibQxt. У меня есть один на https://github.com/robertknight/qt-signal-tools

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...