Как создать обработчик в Qt?

Я работаю над приложением, использующим Qt версии 4.8 в C ++.

Мне нужно использовать функцию C, которая требует указатель на свободную функцию:

void handler(int dummy)

Мне нужно изменить отображаемые значения в моем графическом интерфейсе в зависимости от того, что происходит внутри функции.

Итак, я читал о том, как преобразовать функцию-член в свободную функцию. Я обнаружил, что я могу сделать это, только если моя функция-член является статической.

Но я не могу сделать это статичным — я не смогу изменить какие-либо виджеты, если я сделаю это статичным.

Итак, как я могу справиться с проблемой? Как я могу передать нестатическую функцию-член в качестве указателя на свободную функцию. Если это невозможно, как обойти это?

Буду благодарен за любые предложения, отличающиеся тем, что использовать другую библиотеку.

3

Решение

Поскольку функция C принимает аргумент, вы можете использовать аргумент в качестве индекса в массиве функторов:

class MyWidget : public QWidget {
using vector_t = QVector<std::function<void()>>;
static vector_t m_functions;
public:
using function_type = void(*)(int);
using size_type = vector_t::size_type;

static function_type getHandler() {
return +[](int index){ MyWidget::m_functions[index]; };
}
template <typename F> static size_type getIndexFor(F && fun) {
m_functions.append(std::forward<F>(fun));
return m_functions.size() - 1;
}
//...
size_type getIndexForSetTitle();
};

getHandler возвращает адрес функции-обработчика.
getIndexFor возвращает аргумент, который будет передан обработчику для запуска заданного функтора. Функтор может инкапсулировать вызовы методов виджета. Здесь мы позвоним setWindowTitle на виджете:

MyWidget::size_type MyWidget::getIndexForSetTitle() {
static size_type index = getIndexFor([this]{ setWindowTitle("Foo"); });
return index;
}
2

Другие решения

Да, C ++ не позволяет передавать функции-члены в виде указателя на библиотеку C.

В этом случае общий подход использует вспомогательную функцию, которая действует как мост между библиотекой C и нашим экземпляром класса. Эта вспомогательная функция является свободной функцией, которая получает указатель на текущий экземпляр класса и в своем теле вызывает соответствующий метод-член экземпляра класса.

void handler_helper(int data){
MyClass *obj = (MyClass *) data;
obj->handler(); // This is the corresponding member method
}

И где вы вызываете функцию из этой библиотеки C, вы должны передать handler_helper в качестве указателя на функцию и (int) this в качестве аргумента.

1

По вопросам рекламы [email protected]