2010-09-08 6 views
16

Qt es un buen marco y gran kit de herramientas de interfaz de usuario y tiene many useful features and concepts. La mayoría de nosotros probablemente estemos de acuerdo en que Trolltech, últimamente Nokia, han hecho un buen trabajo al desarrollarlo. Uno de los últimos avances en Qt es QML, que encuentro un avance fascinante.¿Qué características o conceptos te molestan en Qt?

Sin embargo, encuentro que algunos de los conceptos están mal diseñados o mal implementados, como Model/View (el concepto está bien, pero la implementación no) y lo mismo ocurre con Phonon media framework. Algunas personas dicen que es el concepto meta-object que los vuelve locos.

Todo esto es, obviamente, más o menos subjetivo, pero ¿qué características o conceptos le resultan molestos o molestos de usar en Qt y cómo se burla de ellos?

+5

Parece que a las personas les gusta demasiado Qt como para criticarlo :-) – Tuminoid

+0

¡Pondré otra recompensa de +50 para obtener mejores respuestas! Haz que vengan. – Tuminoid

+0

quedan 2 días en la segunda recompensa, traiga sus problemas con Qt y cómo los elude, o cómo le gustaría que fueran reparados. – Tuminoid

Respuesta

27

La mayoría de mis quejas con Qt vienen del hecho de que la API no abarca por completo el dinamismo proporcionado por QObject. Si se atrevió a crear un compilador de metaobjetos para agregar un comportamiento dinámico a C++, ¿por qué ser tímido al respecto?

Todo lo que menciono a continuación son cosas que mi equipo necesitaba en algún momento y tuvimos que codificarlo nosotros mismos. Fue muy divertido y aprendimos mucho sobre las partes internas de Qt, pero no me importaría si ya estaba hecho y listo para usar.

No Distribuidos QObject

Ya sabes, como en el cacao. Llegaron a mitad de camino con QtDBus: lo único que queda por hacer es la red. Tuvimos que implementar nuestra propia solución para esto, y dado que vivimos fuera del código Qt, no podemos cambiar las partes internas para implementar todas las características agradables.

No API para almacenamiento de datos

Y, por supuesto, cada uno escribe su propia biblioteca incompleta QObject-a-SQLite. QDataStream es un muy buen comienzo, sin embargo.

Sin enlace de datos de

Bueno, Qt Quick tiene vinculante, pero el enlace de datos, que vivan en QtCore datos. Con un enlace de datos decente, escribir QAbstractItemModels que represente colecciones de QObjects debería ser cosa del pasado: QObjectListModel debería ser todo lo que necesita.

(Sí, QDataWidgetMapper es una broma.)

Sin Gestión Automática de Deshacer para QObjects

Nuestras clases del modelo son por lo general QObjects y Q_PROPERTY tiene una señal NOTIFICAR opcional que es exactamente lo que se necesita para poner en práctica Deshacer automático Es tan fácil de hacer que ya debería ser parte de Qt. (Se requiere un par de kludges, sin embargo.)

Propiedades Ninguna colección

No todas las propiedades nacen iguales. Algunos de ellos son colecciones. Ser capaz de tratar con esos de una manera abstracta sería definitivamente algo bueno.

de media al horno QMetaStuff API

Y sólo odian esta API porque lo amo. Por ejemplo, uno no puede:

  1. compilar QMetaObjects dinámicamente y reemplazarlos;
  2. llaman a un meta-método utilizando un QVariants como argumentos;
  3. métodos de consulta por tipo de declaración, nombre o tipo de argumento;
  4. conectan señales y ranuras usando los respectivos QMetaMethods (at least not until 4.8);
  5. interceptar conjunto de propiedades/obtener de la misma manera que puede interceptar eventos, por ejemplo.

Casi todos estos se pueden manipular fácilmente. Una solución para # 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; 
    } 
} 

características útiles, probablemente se retira

Se habla en qt-interés que el DOM, style sheets y custom file engines se eliminará en una versión futura de Qt.

Phonon no tiene multi-plataforma de servicios de fondo

Además de no realmente trabajando todo el tiempo, phonon ninguna de fondo estable que trabaja en las tres plataformas más comunes: Windows, Linux y Mac OS X Hay un back-end de VLC, pero definitivamente no es estable, su licencia no está clara y, además, el soporte de VLC para Mac es "resting on shaky ground". La culpa es enteramente de Linux, por supuesto. El soporte multimedia tiene never beenone of its strengths. Le falta algo como Quicktime o DirectStuff.

Clases No Crypto

Hay QCryptographicHash y QSSLSocket (y su funny error modes), y eso es todo. Afortunadamente, hay dos buenas bibliotecas para llenar este vacío: Botan y QCA. QCA se basa en Qt, pero copia su API de las clases de cifrado de Java, por lo que no es muy bueno. Botan tiene una interfaz ingeniosa y (¿pero?) Es C++ "puro". Aún falta una biblioteca de cifrado de estilo Qt.

+1

+1: esto es exactamente lo que estoy buscando, excelente respuesta. – Tuminoid

+1

+1: respuesta completa que revela su profundo conocimiento de Qt. – WolfgangA

+0

+1 para invocar QMetaMethod utilizando QVariants. ¿Es posible proporcionar parámetros erróneamente tipeados que se pueden convertir implícitamente al tipo correcto? Digamos que quiero llamar a 'foo (long)', ¿es posible llamar a su solución con un 'QVariant :: Int'? Necesito esto en mi aplicación y actualmente estoy usando una solución alternativa hackeada realmente sucia de la que quiero deshacerme. – leemes

11

Ésta es una pregunta extraña para el SO de sanción, pero aquí va:

qmake es largo en el diente (y yo soy not the only one to say so). Yo uso cmake, a pesar de que tiene su propia incomodidad.

El paso de compilación de preprocesamiento de metaobjetos para señales/ranuras/etc. es un gran buy-in. Y muchos que estarían dispuestos a aceptar el nivel agregado de abstracción son el tipo de personas que se sentirían atraídas por otros entornos (Java, C#, lo que sea-lo-que-ey). En el otro lado de la valla están los programadores hardcore de C++ que preferirían trabajar con std::thread en lugar de QThread.

(Si un programa en C++ es más y no tiene interfaz gráfica de usuario, las personas parecen evitar Qt, y veo su punto. Orientada servidor-)

El modelo/vista es ni aquí ni allá, pero es tipo de trivial. He cuestiones de afinidad hilo criticado:

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

Además, he-cruz compilada a aplicaciones Mac y Windows y Linux, y se encontró Qt no me protege de los problemas de la plataforma tanto que podría' lo he deseado Si nos fijamos en las partes internas y cómo arrastrar y soltar se implementa mediante el código extremadamente diverso (por ejemplo, qnd_x11.cpp, qdnd_win.cpp y qdnd_mac.mm), entonces verá que el principio "Leaky Abstraction" entra en juego. Qt no impone formalismos fuertes; obtienes los mensajes que obtienes en orden variable, o por duplicado, o no en absoluto en algunas plataformas.

Pero aparte de todas las críticas, me gusta el diseño, la documentación, el apoyo de la comunidad y la estética general de Qt. ¡Podrías hacerlo mucho peor! (. Yo estoy mirando a ti, wxWidgets y GTK)

+1

A veces encuentras información valiosa de esta manera: las personas odian/molestan a algo y lo eluden haciendo lo mismo de otra manera, posiblemente mejor, peor. También me gusta Qt, así que esta no es una pregunta básica :) – Tuminoid

5

El problema que trató de resolver es general para Qt, wxWidgets y posiblemente otros marcos de interfaz de usuario:

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

Tal controlada C excepción ++ se captura por Qt framework, evitando la depuración de excepciones inmediatas o generando volcado de datos informativos. En el lugar donde Qt permite manejar esta situación, la información de excepción original y el seguimiento de la pila se pierden. Traté de luchar con este problema en ambos marcos, y no encontré una solución aceptable. El consejo de los profesionales de Qt "Simplemente no hagas esto" es todo lo que tengo, esto en realidad significa: no hagas errores, y todo estará bien. Esta fue mi gran decepción de Qt y wxWidjets.

1

Estoy trabajando principalmente en Qt para el entorno S60, por lo que algunos de los problemas son específicos para esa plataforma.

sistema de plugins + QObjects

no se puede declarar interfaz de complementos con las señales, debido a que las implementaciones de plug-in se supone que deben derivarse de QObject y múltiples interfaces, por lo que la interfaz no debe ser QObject sí (obligatorio si se quiere algunas señales en tu interfaz). La solución alternativa que encontré en la lista de correo de Qt-interest es agregar un MyQObject * getter a su interfaz de complemento y agregar todas las señales a la clase concreta MyQObject. Funciona, pero es contraintuitivo y feo.

Qset y otros recipientes Qt son menos versátiles que stl o aumentar contenedores

Por ejemplo no se puede definir menos la función que debe ser utilizado cuando se inserta elementos en Qset. Otras cosas que echo de menos es remove_if y find_if.

QServiceFramework en el paquete QtMobility

biblioteca ridícula que se vio obligado recientemente a utilizar. Para usar un "servicio" instalado en QServiceFramework, debe vincularlo a dll que contiene ese servicio (lo cual es bastante inútil, teniendo en cuenta que uno de los objetivos de QSf es ocultar dependencias) o usar QMetaObject :: invokeMethod que no proporciona compilación -tiempo comprobación de métodos, tipos de argumentos, etc., y reduce la legibilidad del código:

// 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")); 

para empeorar las cosas, el sistema de archivos utiliza mucho (la iteración de directorios en busca de plugins, la comunicación con la base de datos SQLite), la cual es una operación lenta en S60.

QPixmap requiere QApplication ...

... y sólo QPixmap tener métodos para la conversión entre las imágenes nativas S60 (clase CFbsBitmap) y los datos de Qt. Entonces, o tiene que hacer de su aplicación una aplicación Q (que aumenta los tiempos de inicio y el consumo de memoria) o tiene que almacenar los datos en estructuras nativas S60 (lo que hace que todo el código sea específico de Symbian)

+7

La mayoría de los contenedores Qt son compatibles con los algoritmos STL, por lo que siempre se puede llamar a remove_if y find_if en ellos. –

+0

Interesante, no sabía de eso. ¡Gracias! – chalup

+2

Puede declarar señales virtuales puras en la interfaz del complemento. – andref

1

Tuve el mismo problema al intentar invocar un método con argumentos variantes. Informé el problema aquí: https://bugreports.qt-project.org/browse/QTBUG-28833

De hecho, me recomendaron usar detalles de implementación no documentados para solucionar el problema. Así que creo que vale la pena vincularlo aquí.

El problema finalmente se aceptó (prioridad baja y solo para Qt5).

Cuestiones relacionadas