Подтвердить что ты не робот

Насколько полезен Qt без шага предварительной обработки?

Я считаю, что для библиотеки нецелесообразно требовать предварительной обработки моего исходного кода с помощью специального инструмента. Тем не менее, несколько человек рекомендовали мне библиотеку Qt для разработки графического интерфейса кросс-платформы.

Насколько полезен Qt без этапа предварительной обработки?

EDIT: Хорошо, я не имею в виду этот вопрос, как рип на Qt - слишком много поклонников Qt рассматривают его так, как будто это так. Я не хочу обсуждать достоинства того факта, что Qt придумал этот инструмент предварительной обработки. Я понимаю, почему инструмент существует, и я понимаю, почему существуют большие части дизайна Qt, которые основаны на идее предварительной обработки.

Я никогда не использовал Qt, ergo. Я не вправе рипать на нем. Но я бы скорее заплатил в письменной форме небольшое количество шаблонов и не зависеть от разрыва моего всего процесса сборки. Я не буду использовать Flex и Bison в моем текущем проекте по той же причине; если я не буду использовать эти инструменты, я определенно не буду использовать другой вид предварительной обработки.

Итак, пожалуйста, не принимайте меня, как разрывать Qt. Я не могу прокомментировать, насколько он хорош или не хорош; Я не использовал его. Я просто хочу знать, можно ли использовать его без moc.

4b9b3361

Ответ 1

Qt не требует использования moc только для его использования, это требует использования, если вы создаете подкласс QObject и объявляете сигналы и слоты в своих пользовательских классах.

Это не необоснованно, moc предоставляет функции, которые С++ не имеет, сигналы/слоты, интроспекция и т.д.

Итак, чтобы сделать что-то минимально продвинутое, вам нужно использовать препроцессор moc. Вы либо любите его, либо ненавидите.

Ответ 2

Я не считаю необоснованным, что Qt требует специального инструмента предварительной обработки, учитывая, насколько велика и обширна библиотека.

Другие подобные библиотеки, такие как Boost и GLib, не требуют специальных средств предварительной обработки, но широко используют стандартный препроцессор C. Qt может быть реализован с использованием только препроцессора C, но, используя собственный специальный инструмент предварительной обработки, он может обеспечить более чистый синтаксис и избежать многих ошибок, связанных с макросами препроцессора C.

Как уже было сказано, вы можете использовать Qt без moc, просто ничего, что требует сигналов и слотов. Да, это включает все компоненты GUI, но Qt никоим образом не является только графической библиотекой.

Ответ 3

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

Без moc ты не сможешь

  • Используйте сигналы и слоты (которые все, но необходимы для пользовательского интерфейса)
  • Используйте динамическую систему свойств (помимо прочего, для написания плагинов).
  • Используйте функции интернационализации
  • Ожидайте, чтобы получить помощь от кого-либо, когда ничего не работает

Если вы хотите использовать Qt, используйте moc. На самом деле, даже не беспокойтесь о moc - просто используйте QMake. Вы можете написать файл .pro QMake, который выглядит следующим образом:

TARGET = myApp

FORMS += MainWindow.ui

HEADERS += MainWindow.h

SOURCES += MainWindow.cpp
SOURCES += main.cpp

Все будет позаботиться автоматически. Или вы можете потратить все свое время, пытаясь понять, как избежать moc.

См. Https://doc.qt.io/archives/qt-4.7/metaobjects.html и https://doc.qt.io/archives/qt-4.7/moc.html#moc.

Ответ 4

Теперь он вполне можно использовать. Составитель moc сделал альтернативу с немного более подробным синтаксисом, чем обычный Qt, но он использует стандартный С++ 14, поэтому нет лишнего шага.

Он называется Verdigris

(как в стороне, moc на самом деле не является шагом предварительной обработки, а также генератором кода. Код, который вы пишете, является допустимым С++, а moc не изменяет его. Он просто генерирует для вас дополнительный код С++. )

Ответ 5

Я действительно не могу придумать ничего такого уникального и полезного с Qt без использования QObjects. Хотелось бы, чтобы они работали на этом этапе предварительной компиляции.

Ответ 6

У меня нет полного ответа, но, как я понимаю, moc в основном (или, возможно, только) генерирует дополнительный код на С++. Так что потенциально нет ничего такого, что вы не могли бы сделать самостоятельно. Тем не менее, я не знаю, насколько утомительно это могло быть и сколько исследований он мог бы принять, чтобы понять все необходимые понятия и детали, которые входят в этот код.


Кроме того, как я отмечаю: на мой взгляд, причина, по которой вы получаете такую ​​же защиту Qt и moc, - это то, что вы начали свой вопрос с сильно сформулированного слова "Я думаю, что это необоснованно", что легко интерпретировать как означающее, что вы не думаете, что moc должен был существовать. Это отвлекает вас от вашего фактического вопроса. Я думаю, было бы лучше сказать "мок не вписывается в мою систему сборки" или просто "у меня есть свои причины, чтобы не хотеть его использовать".

Ответ 7

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

Почему вам все равно: Учитывая природу "прекомпиляции", если вы используете cmake или qmake, это не очень важно в плане неудобств. Если вы делаете что-либо с графическим интерфейсом в наши дни, вы должны использовать графический конструктор для большей части работы, так что вы уже добавляете некоторые шаги "предварительной компиляции".

Относительно того, почему они это сделали: Вам может быть интересно прочитать объяснение Qt: http://doc.qt.io/qt-4.8/templates.html

Это сводится к:

  • В решении шаблона отсутствуют свойства и перегрузка
  • Решение moc предотвращает нарушение бинарной совместимости сигналов
  • Анализ и изменение времени выполнения возможны при использовании механизма шаблонов без шаблонов.

С другой стороны, многопотоковые сигналы/слоты также являются преимуществом их системы.

Ответ 8

Вы можете использовать Qt без moc, но затем вы теряете определенные функции, особенно те, которые делают Qt интересным в первую очередь (например, большинство элементов GUI, сигналов и слотов, а также перевод строк). Но это все еще хорошая библиотека общего назначения, даже без moc.

Ответ 9

В настоящее время я хочу найти альтернативы MOC. Пока я использую GLib для перевода текста, и я в середине реинжиниринга библиотеки сигналов/слотов, которые я нашел в Интернете (sigslot), используя шаблоны С++ и комбинированные макросы C. Скучная и изнуряющая часть обновляет графический интерфейс для моего приложения и заменяет обычные виджеты Qt моими собственными виджетами (то есть QPushButton → MyPushButton) через продвижение виджета (особенность Qt Designer). Таким образом, я могу заставить мои виджеты испускать шаблонные сигналы вместо Qt. Там поймать, tho. Мои "модифицированные" классы виджетов ДОЛЖНЫ запускаться через препроцессор, но это шаг один раз в жизни. После этого я могу двигаться дальше.

Я могу позволить себе все это сделать только потому, что уже написал библиотеку приложений с собственным циклом событий (ну, это оболочка, которая контактирует с кодом цикла событий Qt), многопоточность и классы строк и т.д. Мой проект вам понадобится только Qt, чтобы отобразить красивые и элегантные виджеты.

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

Здесь мое сообщение: если вы можете использовать QMake или moc, просто используйте их.

Ответ 10

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

class SignalProxy : public QWidget
{
public:
  SignalProxy() {}

  void setVisible( bool isVisible )
  {
     // Do whatever you want to do when the signal is emitted.
  }
};


// code to connect the signal, e.g., to a QWebView object
SignalProxy proxy;
QWebView webview;
QObject::connect( &webview, SIGNAL(loadFinished(bool)),
        &proxy, SLOT(setVisible(bool)) );

Это не очень, но он выполняет свою работу. Если бы вы действительно намеревались делать без MOC, вы могли бы найти существующие объекты Qt для использования в качестве прокси-серверов для любой необходимой сигнальной сигнатуры, например, в классах QAbstract... есть много виртуальных слотов, и вы можете скрыть все это nastiness в библиотеке, которая обеспечивает сигналы повышения или tr1:: function < > style API для подключения к сигналам QT.

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

Ответ 11

(извините за возрождение такого старого сообщения)

Мне потребовалось выполнить назначение C/W для моего модуля MSc в 3D Software Development.

К сожалению, требовалось использовать Qt для обеспечения контекста OpenGL, а не для использования Glut, native X11, Gtk и т.д.

Я не хотел использовать MOC и с большим количеством ворчаний, я смог получить достаточно обратных вызовов (таких как клавиатура, мышь, краска, таймер и т.д.), чтобы сделать полезную подачу. Таким образом, для использования Qt с основной причиной для программного обеспечения OpenGL он действительно отлично работает без MOC.

Однако я не вижу, как можно было бы разработать полное приложение без использования MOC. Какой позор.

Эта вещь Qt MOC - это боль. Я не понимаю, почему так много разработчиков на C++, похоже, считают это приемлемым откровенно. Это невероятно неуправляемо и быстро пробивается! (Просто попробуйте компилировать код Borland Kylix С++. Скоро вы поймете, какая это плохая идея).

Если бы я хотел использовать нестандартный С++, я бы просто использовал Microsoft С++/CLI.

Ответ 12

У меня есть решение, которое не является супер-чистым и не на 100% удовлетворительным, но это позволяет подключать сигналы Qt к вашему собственному коду без использования компилятора MOC (у меня было точно такое же ограничение, как и в вопросе, т.е. не удается запустить компилятор MOC в процессе построения моего приложения).

Чтобы иметь возможность фиксировать сигналы Qt без использования MOC, я использую следующие трюки:

(1) получить определение QMetaCallEvent (скопировать его): В Qt 5.x у вас будет что-то вроде:

class QMetaCallEvent : public QEvent {
public:
    inline int id() const {
        return method_offset_ + method_relative_;
    }

    virtual void placeMetaCall(QObject *object);

private:
    QMetaCallEvent();
    void* slotObj_;
    const QObject *sender_;
    int signalId_;
    int nargs_;
    int *types_;
    void **args_;
    void *semaphore_;
    void *callFunction_;
    ushort method_offset_;
    ushort method_relative_;
};

(2) В вашем классе виджетов, который должен захватывать сигналы Qt, вы наследуете от виджета Qt (скажем QButton) и определяете следующую функцию:

// Inspired by QObject::connect() in src/corelib/kernel/qobject.cpp
bool connect_sender(
    const QObject* sender, const char* signal, int method_index
) {

        // We need to generate MetaCall events (since QObject::event()
        //   is the only virtual function we can overload)
        // (note that the other connection types do not generate events).
        Qt::ConnectionType type = Qt::QueuedConnection ;

        if(sender == 0 || signal == 0) {
            std::cerr << "null sender or signal" << std::endl ;
            return false ;
        }

        QByteArray tmp_signal_name;
        const QMetaObject *smeta = sender->metaObject();
        ++signal; //skip code
        int signal_index = smeta->indexOfSignal(signal);
        if (signal_index < 0) {
            // check for normalized signatures
            tmp_signal_name = 
                QMetaObject::normalizedSignature(signal).prepend(*(signal - 1));
            signal = tmp_signal_name.constData() + 1;
            signal_index = smeta->indexOfSignal(signal);
            if (signal_index < 0) {
                std::cerr << "Signal \'" << signal << "\' not found" 
                          << std::endl ;
                return false;
            }
        }

        int *types = 0;

        QMetaObject::connect(
            sender, signal_index, this, method_index, type, types
        ) ;

        return true ;
    }

(3) перегрузить функцию event():

bool event(QEvent* e) {
    if(e->type() == QEvent::MetaCall) {
        QMetaCallEvent* ev = static_cast<QMetaCallEvent*>(e);
        switch(ev->id()) {
            // insert your handling code here
        }  
        return true;
    }
    return QObject::event(e) ;
}

Теперь, если вы вызываете connect_sender (qobject, signal_name, method_index), это будет вызывать событие() каждый раз при запуске сигнала с указанным методом method_index, полученным в ev- > id().

Важное примечание: Я использую этот трюк в своем приложении уже несколько лет, он работает очень хорошо, но он не очень чист. Одним из следствий является то, что всякий раз, когда изменяется определение QMetaCallEvent, вам необходимо соответствующим образом отредактировать свою декларацию (к сожалению, она не отображается в файлах заголовков Qt).