Синтаксис Qt "connect" очень длинный. Есть ли уловки, чтобы сделать его короче? - PullRequest
1 голос
/ 26 декабря 2009

В C # для подключения сигнала к слоту (делегат методу) все, что я делаю, это:

first.signal += second.slot

Но в Qt это:

connect( & first, SIGNAL( signal( int, int, QString ) ), & second, SLOT( slot( int, int, QSTring ) ) );

А этот считается коротким, обычно он порождает 2-3 строки. Конечно, я полностью понял, что Qt подделывает только файлы .h и для .cpp они связаны со стандартным синтаксисом, но есть ли какие-нибудь хитрости / способы сделать подключения сигнальных слотов немного короче? Я знаю об автоматическом подключении сигналов к слотам, присваивая им специальные имена, но это работает только для сигналов в файле .ui. Есть намеки?

Ответы [ 7 ]

6 голосов
/ 27 декабря 2009

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

Этот подход можно использовать вне файлов .ui, вы можете вызывать QMetaObject :: connectSlotsByName где угодно.

3 голосов
/ 26 декабря 2009

Если вы выполняете соединения от сигнала в другом объекте к слоту в this объекте, вы можете сделать ярлык и использовать это:

connect( & first, SIGNAL( signal( int, int, QString ) ), SLOT( slot( int, int, QSTring ) ) );

вместо этого:

connect( & first, SIGNAL( signal( int, int, QString ) ), & second, SLOT( slot( int, int, QSTring ) ) );

, который удаляет немного связи. Я считаю, что есть и другие доступные ярлыки. Тем не менее, ваша общая точка зрения верна и, в основном, является побочным эффектом того, как Qt использует свой механизм сигнал / слот. Если вы действительно хотите более краткий синтаксис в C ++, вы можете взглянуть на библиотеки Boost :: Signals или SigC ++, которые также предоставляют механизм сигнал / слот. Однако следует помнить о конфликтах синтаксиса.

3 голосов
/ 26 декабря 2009

Если вы находите это длинным и повторяющимся, вы можете использовать макросы для облегчения синтаксиса. Например:

#define S_i_i(x) x(int, int, QString)
#define CONNECT(sx,x,tx,sy,y,ty) connect(&x, SIGNAL(tx(sx)), &y, SLOT(ty(sy)))

CONNECT(signal, first, S_i_i, slot, second, S_i_i)

Недостатком является то, что ваш код потеряет читабельность для других, если вы тщательно не выберете свои макросы.

1 голос
/ 27 декабря 2009

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

Кажущееся несвязанным отражение в том, что Qt стремится иметь довольно многословный API, так как его легче читать (и запоминать при написании). Таким образом, они избегают сокращений и пишут, что они означают: QAbstractItemModel, setWindowTitle и т. Д. Не QAbstItModel, setWinTit и т. Д. Больше типизации, меньше недопонимания и ошибок компоновщика (пропущенные символы)

1 голос
/ 26 декабря 2009

Лично я не думаю, что это так плохо. Вы должны записать его только один раз для каждого сигнала / слота, и большую часть времени вам не нужно прикасаться к нему позже.

Ближайшая вещь, которая мне в чем-то помогает, это использование boost :: bind / function с механизмом сигналов / слотов. Он не дает прямого ответа на ваш вопрос, но он связан, и вы можете использовать его. Вы можете прочитать об этом здесь .

0 голосов
/ 28 апреля 2013

Другое решение для компиляторов с поддержкой Qt5 и C ++ 11:

#define Q_CONNECT(sender, signal, receiver, slot) \
    QWidget::connect( \
        sender, &boost::remove_reference<boost::mpl::identity<decltype(*sender)>::type>::type::signal, \
        receiver, &boost::remove_reference<boost::mpl::identity<decltype(*receiver)>::type>::type::slot);

#define Q_CONNECT_LAMBDA(sender, signal, receiver) \
    QWidget::connect( \
    sender, &boost::remove_reference<boost::mpl::identity<decltype(*sender)>::type>::type::signal, \
    receiver);

Обратите внимание, что boost :: mpl :: identity требуется только для компиляторов, которые еще не обрабатывают следующее (например, VS2010):

decltype(expr)::member

Пример использования:

Q_CONNECT(
    this, mySignalMethodName,
    &someHandler, handlerMethodName);

Q_CONNECT_LAMBDA(
    this, mySignalMethodName,
    [=]() { handlerCode(); });

Плюсы:

  • нет необходимости вводить списки аргументов;
  • нет необходимости явно дублировать информацию о типе;
  • нет необходимости использовать какие-либо макросы SIGNAL, SLOT, Q_SIGNAL, Q_SLOT;
  • все проверки совместимости выполняются во время компиляции.

Минусы:

  • не будет работать с перегруженными методами.
0 голосов
/ 24 июня 2011

Через несколько лет я нашел решение, которое может сделать соединения короче. Решение основано на ответе @WildSeal и использует этот простой макрос:

#define QCON( a, b, c, d ) VERIFY( QObject::connect( a, SIGNAL(b), c, SLOT(d) ) )

Итак, длинный рассматриваемый код:

VERIFY( QObject::connect( first, SIGNAL(signal(int,int,QString)), second, SLOT(slot(int,int,QSTring)) ) );

Будет значительно короче:

QCON( first, signal(int,int,QString), second, slot(int,int,QString) );

Любые комментарии и предложения приветствуются :). Единственные недостатки, которые я обнаружил на данный момент, это то, что мне нужен отдельный макрос для подключения SIGNAL к SIGNAL. Но так как такая операция довольно редкая, я просто ввел QCONS(), и она делает свое дело.

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