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

Какие функции или понятия раздражают вас в Qt?

Qt - это хорошая структура и отличный инструментарий для пользовательского интерфейса и много полезных функций и концепций. Большинство из нас, вероятно, согласны с тем, что Trolltech, в последнее время Nokia, неплохо справились с этим. Одним из последних достижений в Qt является QML, который я нахожу увлекательным.

Однако я нахожу некоторые из концепций, плохо спроектированных или плохо реализованных, таких как Model/View (концепция прекрасна, но реализация это не так), то же самое относится к Phonon media framework. Некоторые люди говорят о своей концепции метаобъекта, которая сводит их с ума.

Все это, очевидно, более или менее субъективно, но какие функции или концепции вы находите раздражающими или обременительными для использования в Qt и как вы обходите их вокруг?

4b9b3361

Ответ 1

Большинство моих попыток с Qt исходят из того факта, что API не полностью использует динамизм, предоставляемый QObject. Если вы посмели создать метаобъектный компилятор, чтобы добавить динамическое поведение на С++, почему бы не стесняться в этом?

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

Нет распределенного QObject

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

Нет API для хранения данных

И, конечно же, каждый пишет свою собственную неполную библиотеку QObject-to-SQLite. Однако QDataStream - это очень хорошее начало.

Нет привязки данных

Ну, Qt Quick имеет привязку данных, но привязка данных должна жить в QtCore. При приличном привязке данных писать QAbstractItemModels, представляющие коллекции QObjects, должно быть ушли в прошлое: QObjectListModel должен быть всем, что вам нужно.

(Да, QDataWidgetMapper - шутка.)

Нет автоматического управления отмена для QObjects

Наши классы моделей обычно QObjects, а Q_PROPERTY имеет дополнительный сигнал NOTIFY, который является именно тем, что необходимо для автоматического отключения. Это так легко сделать, это уже должно быть частью Qt. (Тем не менее, для этого требуется несколько kludges.)

Свойства коллекции

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

Полуобработанный API QMetaStuff

И я ненавижу этот API только потому, что мне это нравится. Например, нельзя:

  • динамически создавать QMetaObjects и заменять их;
  • вызов мета-метода с использованием QVariants в качестве аргументов;
  • методы запроса типа возвращаемого типа, имени или аргументов;
  • подключить сигналы и слоты, используя соответствующие методы QMetaMethods (по крайней мере, до 4,8);
  • перехватить свойство set/get так же, как вы можете перехватить события, например.

Почти все из них могут легко работать. Решение для # 2:

QVariant call(QObject* object, QMetaMethod metaMethod, QVariantList args)
{
    QList<QGenericArgument> arguments;

    for (int i = 0; i < args.size(); i++) {

        // Notice that we have to take a reference to the argument. A 
        // const_cast is needed because calling data() would detach 
        // the QVariant.

        QVariant& argument = args[i];

        QGenericArgument genericArgument(
            QMetaType::typeName(argument.userType()),
            const_cast<void*>(argument.constData())
        );

        arguments << genericArgument;
    }

    QVariant returnValue(QMetaType::type(metaMethod.typeName()), 
        static_cast<void*>(NULL));

    QGenericReturnArgument returnArgument(
        metaMethod.typeName(),
        const_cast<void*>(returnValue.constData())
    );

    // Perform the call

    bool ok = metaMethod.invoke(
        object,
        Qt::AutoConnection, // In case the object is in another thread.
        returnArgument,
        arguments.value(0),
        arguments.value(1),
        arguments.value(2),
        arguments.value(3),
        arguments.value(4),
        arguments.value(5),
        arguments.value(6),
        arguments.value(7),
        arguments.value(8),
        arguments.value(9)
    );

    if (!ok) {
        // Handle the error...
    } else {
        return returnValue;
    }
}

Полезные функции, вероятно, будут удалены

В qt-интересе говорят, что DOM, таблицы стилей и пользовательские файловые движки будут удалены в будущей версии Qt.

У Phonon нет межплатформенного back-end

Помимо того, что Phonon не работает постоянно, Phonon не имеет стабильного back-end, который работает на трех наиболее распространенных платформах: Windows, Linux и Mac OS X. Существует VLC-сервер, но он определенно не стабилен, его лицензирование неясно и, кроме того, поддержка VLC для Mac "покоится на шаткой почве ". Конечно, виноват полностью на Linux. Поддержка мультимедиа никогда не была одной из ее сильных сторон. В нем нет чего-то вроде Quicktime или DirectStuff.

Нет классов криптографии

Есть QCryptographicHash и QSSLSocket (и его смешные режимы ошибок) и что это. К счастью, для заполнения этого пробела есть две хорошие библиотеки: Botan и QCA. QCA основан на Qt, но копирует его API из классов криптова Java, поэтому он не очень хорош. У Botan есть отличный интерфейс и (но?) Является "чистым" С++. Криптографическая библиотека в стиле Qt все еще отсутствует.

Ответ 2

Это нечетный вопрос для разрешения SO, но здесь говорится:

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

Шаг сборки предварительной обработки метаобъекта для сигналов/слотов/и т.д. это огромный бай-ин. И многие, кто хотел бы принять добавленный уровень абстракции, - это те люди, которых привлекают к другим средам (Java, С#, независимо от того, как они относятся). С другой стороны забора стоят хардкорные программисты на C++, которые скорее предпочитают работать с std::thread вместо QThread.

(Если программа на С++ более ориентирована на сервер и не имеет графического интерфейса, люди, похоже, избегают Qt, и я вижу их точку.)

Модель/представление не существует ни здесь, ни там, но это немного тривиально. Я критиковал проблемы сродства потоков:

http://blog.hostilefork.com/qt-model-view-different-threads/

Кроме того, у меня есть кросс-скомпилированные приложения для Mac и Windows и Linux, и я обнаружил, что Qt не защищает меня от проблем с платформой, насколько я мог бы пожелать. Если вы посмотрите на внутренности и как перетаскивание осуществляется с помощью чрезвычайно разнообразного кода (например, qnd_x11.cpp, qdnd_win.cpp и qdnd_mac.mm), вы увидите, что "Leaky Abstraction" вступает в игру. Qt не накладывает сильных формализмов; вы получаете сообщения, которые вы получаете в различном порядке, или дублируетесь - или совсем не на некоторых платформах.

Но все критические замечания в стороне, мне нравятся дизайн Qt, документация, поддержка сообщества и общая эстетика. Вы могли бы сделать намного хуже! (Я смотрю на вас, wxWidgets и GTK.)

Ответ 3

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

void MainDialog::OnCppException()
{
    throw std::runtime_error("test unhandled exception");
}

Такое необработанное исключение С++ улавливается картой Qt, что предотвращает немедленную отладку исключений или генерирует информационный аварийный свал. В том месте, где Qt позволяет обрабатывать эту ситуацию, исходная информация об исключении и трассировка стека теряются. Я пытался бороться с этой проблемой в обеих структурах и не нашел приемлемого решения. Совет профессионалов Qt "Просто не делай этого" - это все, что у меня есть, это на самом деле означает: не делайте ошибок, и все будет в порядке. Это было мое самое большое разочарование от Qt и wxWidjets.

Ответ 4

Я работаю в основном на Qt для среды S60, поэтому некоторые из них относятся к этой платформе.

Система плагинов + QObjects

Вы не можете объявлять интерфейс плагина с помощью сигналов, поскольку предполагается, что реализации плагина должны быть получены из QObject и нескольких интерфейсов, поэтому интерфейс не должен быть QObject сам (требуется, если вам нужны некоторые сигналы в вашем интерфейсе). Обходной путь, который я нашел в списке рассылки Qt-interest, заключается в добавлении myQObject * getter к вашему интерфейсу плагина и добавлении всех сигналов в конкретный класс MyQObject. Он работает, но он нелогичный и уродливый.

QSet и другие Qt-контейнеры менее универсальны, чем контейнеры stl или boost

Например, вы не можете определить меньшую функцию, которая должна использоваться при вставке элементов в QSet. Другие вещи, которые я пропускаю, - remove_if и find_if.

QServiceFramework в пакете QtMobility

Смешная библиотека, которую я недавно заставил использовать. Чтобы использовать "сервис", установленный в QServiceFramework, вам нужно либо связать с dll, который содержит эту службу (что совершенно бессмысленно, учитывая, что одна из целей QSf - скрывать зависимости), либо используйте QMetaObject:: invokeMethod, который не предоставляет компиляцию - проверка временем методов, типов аргументов и т.д. и уменьшает читаемость кода:

// using QMetaObject::invokeMethod
QVariantHash data;
bool ok = QMetaObject::invokeMethod(myObject, "getStuff", 
    Q_RETURN_ARG(QVariantHash, data)
    Q_ARG(QString, QString("blah")));
Q_ASSERT(ok);

// using normal syntax
QVariantHash data(myObject->getStuff("blah"));

Чтобы ухудшить ситуацию, он довольно часто использует файловую систему (итерация dirs ищет плагины, связь с базой данных SQLite), что является медленной операцией на S60.

QPixmap требует QApplication...

... и только QPixmap имеют методы для преобразования между собственными изображениями S60 (класс CFbsBitmap) и данными Qt. Таким образом, вы должны либо сделать свое приложение QApplication (что увеличивает время запуска и потребление памяти), либо вам нужно хранить данные в собственных S60-структурах (что делает весь код специфичным для Symbian)

Ответ 5

У меня была та же самая проблема, пытаясь вызвать метод с вариантными аргументами. Я сообщил об этом здесь: https://bugreports.qt-project.org/browse/QTBUG-28833

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

Вопрос был окончательно принят (приоритет низкий и только для Qt5).