Foros del Web » Programación para mayores de 30 ;) » C/C++ »

Qt. Reutilizar widgets en distintas partes del programa

Estas en el tema de Qt. Reutilizar widgets en distintas partes del programa en el foro de C/C++ en Foros del Web. Bueno, el título no expresa exactamente la duda que tengo, voy a ver si me consigo explicar: Estoy "perpetrando" una BBDD en mis ratos libres. ...
  #1 (permalink)  
Antiguo 21/04/2016, 04:06
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Qt. Reutilizar widgets en distintas partes del programa

Bueno, el título no expresa exactamente la duda que tengo, voy a ver si me consigo explicar:

Estoy "perpetrando" una BBDD en mis ratos libres. El programa que la maneja accede en varios puntos del programa y con diálogos diferentes a cuadros idénticos. Por ejemplo, tengo unos QLineEdit donde están los datos de las personas, los cuales tienen están rellenos con los datos actuales para que funcione el autocompletado:
Algo como esto: (para QLineEdit)
Código C++:
Ver original
  1. QStringList *ListaValores = new QStringList();
  2.             QString cadenaConsulta = "SELECT DISTINCT "+campo[i]+" FROM socios order by "+campo[i];            
  3.             consulta.exec(cadenaConsulta);
  4.             while(consulta.next())
  5.             {
  6.                 *ListaValores << consulta.value(0).toStringList();                
  7.             }
  8.             completer = new QCompleter(*ListaValores);
  9.             completer->setCaseSensitivity(Qt::CaseInsensitive);
  10.             editor[i]->setCompleter(completer);

O esto (Para QComboBox):

Código C++:
Ver original
  1. QSqlQueryModel* modelZonas = new QSqlQueryModel();
  2.     QSqlQuery *consulta = new QSqlQuery ("SELECT zona FROM zonas ORDER BY id");
  3.     modelZonas->setQuery(*consulta);
  4.     comboZona->setModel(modelZonas);

La idea sería que esos mismos widgets aparecieran en otros diálogos, de forma que ya estarían rellenos y no tendría que volver a hacer la operación.

Confieso que cuando pensé en la idea me la imaginaba sencilla y sin ninguna complicación, y llevo unas cuantas horas y no doy con la tecla.

Saludos y gracias, como siempre!
__________________
Mi calculadora en Qt
  #2 (permalink)  
Antiguo 21/04/2016, 05:24
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Qt. Reutilizar widgets en distintas partes del programa

Código C++:
Ver original
  1. QStringList *ListaValores = new QStringList();
  2. QString cadenaConsulta = "SELECT DISTINCT "+campo[i]+" FROM socios order by "+campo[i];            
  3. consulta.exec(cadenaConsulta);
  4. while(consulta.next())
  5. {
  6.   *ListaValores << consulta.value(0).toStringList();                
  7. }
  8. completer = new QCompleter(*ListaValores);
  9. completer->setCaseSensitivity(Qt::CaseInsensitive);
  10. editor[i]->setCompleter(completer);

En esas líneas tienes una fuga de memoria. ListaValores es un puntero... a completer le pasas una copia del elemento asociado al puntero luego estás dejando memoria sin liberar.

Salvo que luego hagas cosas con ese punteor que no estén reflejadas en este código deberías dejar el código tal que:

Código C++:
Ver original
  1. QStringList ListaValores;
  2. QString cadenaConsulta = "SELECT DISTINCT "+campo[i]+" FROM socios order by "+campo[i];            
  3. consulta.exec(cadenaConsulta);
  4. while(consulta.next())
  5. {
  6.   ListaValores << consulta.value(0).toStringList();                
  7. }
  8. completer = new QCompleter(ListaValores);

Para reutilizar ese código tienes dos opciones:
  1. Creas un widget personalizado para la ocasión
  2. Creas una clase que encapsule este código y configure el widget que le pidas.

Crear un widget personalizado tiene la ventaja de que el propio widget se encargará de configurarse. La parte mala es que salvo que implementes un plugin para QtCreator el widget únicamente podrás usarlo en el diseñador mediante promoción.

No se dónde tienes pensado configurar el widget, pero podría ser algo tal que:

Código C++:
Ver original
  1. class CustomLineEdit: public QLineEdit
  2. {
  3.   Q_OBJECT
  4.  
  5.   public:
  6.  
  7.     CustomLineEdit(QWidget* parent)
  8.       : QLineEdit(parent)
  9.     {
  10.       ConfigurarCompleter();
  11.     }
  12.  
  13.     ~CustomLineEdit() = default;
  14.  
  15.   private:
  16.  
  17.     void ConfigurarCompleter()
  18.     {
  19.       QStringList ListaValores;
  20.       QString cadenaConsulta = "SELECT DISTINCT "+campo[i]+" FROM socios order by "+campo[i];            
  21.       consulta.exec(cadenaConsulta);
  22.       while(consulta.next())
  23.       {
  24.         ListaValores << consulta.value(0).toStringList();                
  25.       }
  26.       completer = new QCompleter(ListaValores,this);
  27.       completer->setCaseSensitivity(Qt::CaseInsensitive);
  28.       setCompleter(completer);
  29.     }
  30. };

La opción B, como te comenté, pasa por usar una clase externa que configure los widgets. Algo tal que:

Código C++:
Ver original
  1. struct CustomClass
  2. {
  3.     static void ConfigureCompleter(QLineEdit& widget)
  4.     {
  5.       QStringList ListaValores;
  6.       QString cadenaConsulta = "SELECT DISTINCT "+campo[i]+" FROM socios order by "+campo[i];            
  7.       consulta.exec(cadenaConsulta);
  8.       while(consulta.next())
  9.       {
  10.         ListaValores << consulta.value(0).toStringList();                
  11.       }
  12.       completer = new QCompleter(ListaValores,&widget);
  13.       completer->setCaseSensitivity(Qt::CaseInsensitive);
  14.       widget.setCompleter(completer);
  15.     }
  16. };

Y para el QComboBox más de lo mismo.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #3 (permalink)  
Antiguo 21/04/2016, 07:43
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 14 años, 1 mes
Puntos: 10
Respuesta: Qt. Reutilizar widgets en distintas partes del programa

Hola eferion:

Gracias como siempre.
Lo primero es que no, aunque había más código que el que he mostrado, no había liberado la memoria del puntero. A estas alturas todavía así....

Por otro lado, centrándonos en la cuestión, ciertamente la solución que propones es la más lógica, en cualquiera de las dos versiones. Pero mi idea era utilizar exactamente la misma instancia del widget, no una diferente, ya que la idea, además de tener el código legible y en condiciones era no repetir las consultas cada vez que hay que crear un widget.

Pero entiendo que esa es una idea absurda, pero te he "tomado prestada" tu solución, pero no para crear una instancia del widget sino de los completers y de los modelos.

Luego cada vez que necesite un nuevo QLineEdit o QComboBox sólo he de añadirle el completer o model

¿Qué te parece la idea? La verdad es que se ve una ligerísima mejora de rapidez a la hora de crear el diálogo así
__________________
Mi calculadora en Qt
  #4 (permalink)  
Antiguo 21/04/2016, 08:17
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Qt. Reutilizar widgets en distintas partes del programa

Cita:
Iniciado por dehm Ver Mensaje
A estas alturas todavía así....
Algunos gurús de C++ dicen que a estas alturas de la vida lo mejor es no usar nunca new salvo causas de fuerza mayor.

Para ayudarte en esa tarea tienes std::make_shared y std::make_unique, que te crean automáticamente instancias de punteros inteligentes... o crear los objetos locales en la pila para eso está :)

Cita:
Iniciado por dehm Ver Mensaje
Por otro lado, centrándonos en la cuestión, ciertamente la solución que propones es la más lógica, en cualquiera de las dos versiones. Pero mi idea era utilizar exactamente la misma instancia del widget, no una diferente, ya que la idea, además de tener el código legible y en condiciones era no repetir las consultas cada vez que hay que crear un widget.
Si no quieres repetir la query siempre puedes cachear el resultado... ahora que eso implica que has de preocuparte de actualizar dicha caché cada vez que esa tabla se actualize.

Cita:
Iniciado por dehm Ver Mensaje
Luego cada vez que necesite un nuevo QLineEdit o QComboBox sólo he de añadirle el completer o model

¿Qué te parece la idea?
En C++ como norma general no hay una única forma de hacer las cosas y sí muchos buenos caminos para conseguir lo mismo. Si has encontrado uno adelante con ello.

Por otro lado yo insisto. No te preocupes por el rendimiento salvo que estés desarrollando librerías para terceros. El motivo es que estás trabajando sobre un código inacabado que puede sufrir cambios... preocuparse ahora del rendimiento salvo que el problema sea bastante evidente es absurdo por varios motivos:
  • Si cambia el código puedes perder los beneficios de la optimización hasta el punto de resultar ésta perjudicial
  • Estás invirtiendo tiempo en algo que puede no aportar absolutamente nada. Un retardo de unas décimas de segundo en una interfaz de usuario es aceptable
  • Optimizar normalmente conlleva hacer código feo y poco legible y eso repercute en el mantenimiento de la aplicación.

En el caso de librerías para terceros la cosa cambia porque ya no puedes adivinar cómo va a ser usada esa librería, luego las mejoras de rendimiento se pueden realizar en cualquier momento siempre procurando que la funcionalidad no se vea alterada.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Etiquetas: cadena, distintas, funcion, partes, programa, string, widgets
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:32.