Mostrando entradas con la etiqueta Qt. Mostrar todas las entradas
Mostrando entradas con la etiqueta Qt. Mostrar todas las entradas

viernes, 19 de mayo de 2017

Un acercamiento a la implementación del método elementById de la clase QDomDocument de Qt

En ocasiones trabajamos con archivos xml bastante estructurados y se requiere de ciertos mecanismos para acceder de forma más eficiente a los elementos y/o nodos contenidos en estos. Un ejemplo de esto sería trabajar con HTML en el cual queremos acceder a un contenedor particular (DIV); y si hemos sido muy precavidos al momento de maquetar nuestro HTML, habremos definido ID's, si bien no para todos los DIV's (lo cual sería lo ideal, por lo de la web semántica y todo eso), por lo menos si para los DIV's más importantes y que proveen una funcionalidad muy particular.

Pues bien, si estamos trabajando con Qt e intentamos realizar una pequeña utilidad para analizar nuestro código HTML, una de las API con la que debemos trabajar sería la API xml y xmlpatterns, pero que sorpresa cuando al utilizar la clase QDomDocument, y se quiere acceder a un elemento por su ID, la documentación no muestra lo siguiente:

Returns the element whose ID is equal to elementId. If no element with the ID was found, this function returns a null element.
Since the QDomClasses do not know which attributes are element IDs, this function returns always a null element. This may change in a future version.
Devuelve el elemento cuyo ID es igual a elementId. Si no se encontró ningún elemento con el ID, esta función devuelve un elemento nulo.
Dado que las QDomClasses no saben qué atributos son identificadores de elementos, esta función devuelve siempre un elemento nulo. Esto puede cambiar en una versión futura.
http://doc.qt.io/qt-5/qdomdocument.html#elementById

Es decir, el método QDomDocument::getElementById ( const QString &elementId ), no está implementado, por esta razón, hoy traigo esta pequeña contribución que tenía mucho tiempo ya que había escrito para facilitar el acceso a elementos vía ID

QDomElement getElementById ( QString id ) {

  QDomElement elementReturned;
  QDomElement filesListNode = this->xmlDocument.firstChildElement ( "ETIQUETA_RAIZ" ).firstChild ().toElement ();
  while ( !filesListNode.isNull () ) {

    QDomNamedNodeMap attributes = filesListNode.attributes ();

    if ( attributes.namedItem ( "id" ).nodeValue () == id ) {

      elementReturned = filesListNode;
      break;
    }
    filesListNode = filesListNode.nextSibling ().toElement ();
  }
  return elementReturned;
}
Por otro lado mientras escribía esta entrada, me di cuenta que se puede hacer mucho más genérica y no tener que modificar nada, y esto sería cambiando la línea:

QDomElement filesListNode = this->xmlDocument.firstChildElement ( "ETIQUETA_RAIZ" ).firstChild ().toElement ();
por

QDomElement filesListNode = this->xmlDocument.documentElement ();
Hay que tomar en cuenta, que este método debe ser incluido en una clase que encapsule la utilización de la clase QDomDocument, donde habrá un atributo xmlDocument de tipo QDomDocument, es decir:

private:
  QDomDocument xmlDocument;
Por otro lado se pueden hacer variaciones, para hacerlo más genérico aun, como pasarle por parámetros, todos los datos requeridos para efectuar la implementación, un ejemplo sería:

QDomElement getElementById ( QDomDocument xmlDocument, QString id )
Pues bueno, la implementación les queda de tarea para la casa ;).

Hasta una nueva entrada.

sábado, 3 de enero de 2009

Personalizar tus ventanas en Qt::Ventanas sin marcos (con formas personalizadas)

Ya vistos los ejemplos anteriores, ahora se tiene que la forma de la aplicación no es la deseada. Como en el ejemplo Personalizar tus ventanas en Qt::Ventanas sin marcos (con movilidad en el escritorio) solo que se tiene que añadir estas lineas de código.

Eso se puede resolver de la siguiente manera.

Si bien se puede modificar el método

QSize sizeHint() const;//DEFINE EL TAMAÑO INICIAL DE LA VENTANA

del primer ejemplo, eso no nos permitira darle la forma real que queremos.

En cambio lo haremos con un nuevo metodo que vamos a reescribir.

Archivo cabecera

void resizeEvent(QResizeEvent *event);// DEFINE EL ESPACIO VISIBLE DE LA APLICACION, EN ESTE CASO LA ELIPSE

Archivo CPP

void SinMarco::resizeEvent(QResizeEvent * /* event */) {// DEFINE EL ESPACIO VISIBLE DE LA APLICACION, EN ESTE CASO UNA ELIPSE
  // USAR SOLO UNO DE LAS DOS FORMAS
  //QRegion maskedRegion(10, 10, 1000, 130, QRegion::Rectangle);
  QRegion maskedRegion(10, 10, 1000, 130, QRegion::Elipse); // EL CENTRO DE ESTA ELIPSE ES (10+1000)/2 Y (10+130)/2
  setMask(maskedRegion);
}


Tambien para este ejemplo se puede usar poligonos.

Y así ya tenemos una ventana diferente a las ventanas cuadradas aburridas : ).

Personalizar tus ventanas en Qt::Ventanas sin marcos (con movilidad en el escritorio)

En el ejemplo anterior Personalizar tus ventanas en Qt::Ventanas sin marcos se logroó que la ventana se comportara como se queria; sin los marcos por defecto del sistema.

Ahora este nuevo ejemplo, basado en el anterior, trae unas nuevas características para el manejo de nuestra ventana sin marcos.

Si bien ya tenemos nuestra ventana sin marcos, no podemos moverla por nuestro escritorio, cosa que por demás desagrada, si tomamos en cuenta que queremos cambiarla de posición.

Pues aquí, está la solución, solo tenemos que adicionar estas lineas de código en nuestro ejemplo anterior.

Archivo cabecera

protected:
  void mouseMoveEvent(QMouseEvent *event);
  void mousePressEvent(QMouseEvent *event);
 
  private:
  QPoint dragPosition;


Archivo CPP

void SinMarco::mousePressEvent(QMouseEvent *event) {//PARA MOVER LA APLICACION POR EL ESCRITORIO
  if (event->button() == Qt::LeftButton) {
  dragPosition = event->globalPos() - frameGeometry().topLeft();
  event->accept();
  }
}

void SinMarco::mouseMoveEvent(QMouseEvent *event) {
  if (event->buttons() & Qt::LeftButton) {
  move(event->globalPos() - dragPosition);
  event->accept();
  }
}

Personalizar tus ventanas en Qt::Ventanas sin marcos

Hola amigos, que tal?.

En mi pasar por la programación con Qt, he ido realizando algunas modificaciones a los componentes básicos para darle un aspecto diferente a mis aplicaciones.

Hoy les quiero mostrar parte de esas cosas que he hecho.

Ahora bien lo más importante... el código.

Archivo Cabecera

#ifndef SINMARCO_H
#define SINMARCO_H
#include
class SinMarco : public QWidget {
    Q_OBJECT
    public:
        SinMarco(QWidget *parent = 0);//CONSTRUCTOR, DEFINE QUE LA VENTANA SERA SIN MARCOS
        QSize sizeHint() const;//DEFINE EL TAMAÑO INICIAL DE LA VENTANA ESTA LINEA DE CODIGO ES OPCIONAL
};
#endif



Archivo CPP

#include "sinmarco.h"
SinMarco::SinMarco(QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint) { //DEFINE QUE LA VENTANA SERA SIN MARCOS
    // LA BANDERA Qt::FramelessWindowHint EN EL CONSTRUCTOR QWidget 
    // ES LO UNICO QUE NECESITAMOS PARA HACER QUE NUESTRA APLICACIÓN NO POSEA EL MARCO DE VENTANAS (NI DEL SISTEMA NI DEL LENGUAJE)
}
QSize SinMarco::sizeHint() const {//DEFINE EL TAMAÑO INICIAL DE LA VENTANA OPCIONAL
    return QSize(1000, 130);
    // ESTOS VALORES PUEDEN SER MODIFICADOS A NUESTRO GUSTO

}

Archivo MAIN

#include
#include "sinmarco.h"
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    SinMarco Ventana_Sin_Marco;
    Ventana_Sin_Marco.show();
    return app.exec();
}


Y así hemos concluido nuestra ventana sin marcos.

martes, 16 de diciembre de 2008

Usando el framework Phonon en mi aplicación

Estoy haciendo una aplicación multimedia para KDE, para reproducir video, audio, podcast, radio y más, por tal razón me encuentro realizando algunas pruebas al marco de trabajo phonon, por lo que he compilado el ejemplo musicplayer de qt4.

Todo corre perfecto, solo cuando ejecuto, me da la siguiente advertencia:

WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
Phonon::createPath: Cannot connect Phonon::MediaObject(no objectName) to Phonon::AudioOutput(no objectName).
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded


Luego cuando cargo un archivo (mp3, wav u otro), me da la siguiente advertencia:

WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded

Buscando un poco más detenidamente, con la sugerencia de algunos amigos, devele unas dudas que tenía.

Si bien es cierto que phonon viene con y para KDE4, y que en teoría solo trabaja para KDE4 por eso de que KDE3 y KDE4 son incompatibles (que no es del todo cierto, pues tengo algunos modulos de KDE4 instalados en mi KDE3 y hasta ahora no he tenido ningún problema), Qt4 trae consigo el framework PHONON.

De lo que me he dado cuenta es que mi problema se presento porque instalé el phonon de KDE4 y no el de Qt4, y cuando busca hacer los enlaces no consigue el plugin porque Qt4 no lo tiene.

El problema se resuelve con solo esta linea


ln -s /usr/lib/kde4/plugins/phonon_backend /usr/lib/qt/plugins

Pero tuve que modificarla por esta, pues por tener KDE3 me instala el qmake de Qt3 y como instale Qt4 ahora tengo los 2.

ln -s /usr/lib/kde4/plugins/phonon_backend /usr/lib/qt4/plugins

Ahora mi aplicación esta trabajando al jorno.

Más adelante iré publicando nuevas soluciones a errores que se me vayan presentando con el framework PHONON.