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

[SOLUCIONADO] Qt: Personalizar QLineEdit

Estas en el tema de Qt: Personalizar QLineEdit en el foro de C/C++ en Foros del Web. Hola Quiero hacer un QLineEdit personalizado, estoy buscando algo de documentación, pero todo lo que encontré es para hacer widgets personalizados a partir de QWidget. ...
  #1 (permalink)  
Antiguo 01/08/2016, 04:37
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Qt: Personalizar QLineEdit

Hola

Quiero hacer un QLineEdit personalizado, estoy buscando algo de documentación, pero todo lo que encontré es para hacer widgets personalizados a partir de QWidget.

Pero yo lo que quiero es añadir una nueva propiedad (float) al QLineEdit y que muestre un pequeño texto en base al valor de esa propiedad junto a lo que escribe el usuario (pegado al lado derecho había pensado).

Así que si tenéis algún link por ahí me sería de mucha ayuda :)

Un saludo
  #2 (permalink)  
Antiguo 01/08/2016, 09:33
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 6 meses
Puntos: 10
Respuesta: Qt: Personalizar QLineEdit

Te comentaría que es tan fácil como crear una clase derivada a partir de QLineEdit y añadir o modificar los aspectos que quieras, pero como sabes 1000 veces más que yo de Qt asumo que no he entendido la pregunta
__________________
Mi calculadora en Qt

Última edición por dehm; 01/08/2016 a las 10:15
  #3 (permalink)  
Antiguo 01/08/2016, 10:19
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 2 meses
Puntos: 27
Respuesta: Qt: Personalizar QLineEdit

Yo lo haría así, seguramente haya más maneras de hacerlo.

Para asegurarte de que sea float puedes:
  • Utilizar un QLineEdit y utilizar un validator.
  • Utilizar un QDoubleSpinBox.

Para implementarlo podemos hacer lo siguiente:
  1. Crea una clase nueva a partir de QWidget
  2. Añade la Q_PROPERTY e implementa lo que necesites para ello.
  3. En la clase nueva añade un QLabel(que tendrá el texto que necesites) y la opción superior que hayas tomado.
  4. En la clase nueva crear un QHBoxLayout para asegurar que una cosa está a la derecha de otra insertando ambos widgets en el layout en orden.
  5. Conecta la señal de cambio de la opción superior con un slot privado que modifique el valor de la propiedad.
  6. Conecta la señal del Notify de la propiedad con un slot privado nuevo que crees en la clase.
  7. La implementación del slot consistirá en modificar el valor del QLabel en función del valor que recibas de la propiedad.

Con spinbox sería algo así:
Código C++:
Ver original
  1. class A : public QWidget {
  2.     Q_OBJECT
  3.     Q_PROPERTY(double number READ getNumber WRITE setNumber NOTIFY numberChanged)
  4. public:
  5.     A() {
  6.         lay = new QHBoxLayout(this);
  7.         spin = new QDoubleSpinBox(this);
  8.         spin->setMinimum(-100);
  9.         label = new QLabel(this);
  10.  
  11.         lay->addWidget(spin);
  12.         lay->addWidget(label);
  13.         connect(spin, SIGNAL(valueChanged(double)), this, SLOT(setNumber(double)));
  14.         connect(this, SIGNAL(numberChanged(double)), this, SLOT(setLabel(double)));
  15.     }
  16.  
  17.     double getNumber() {
  18.         return spin->text().toDouble();
  19.     }
  20.  
  21. private:
  22.     // UI
  23.     QLabel* label;
  24.     QDoubleSpinBox* spin;
  25.     QHBoxLayout* lay;
  26.  
  27.     // Properties
  28.     double m_number;
  29.  
  30. signals:
  31.     void numberChanged(double);
  32.  
  33. private slots:
  34.     void setNumber(double a) {
  35.         qDebug() << "Cambiando propiedad a " << a;
  36.         m_number = a;
  37.         emit numberChanged(a);
  38.     }
  39.  
  40.     void setLabel(double a) {
  41.         qDebug() << "Cambiando label";
  42.         if (a == 0)
  43.             label->setText("PRUEBA 1");
  44.         else if (a < 0)
  45.             label->setText("ASBDAD");
  46.         else
  47.             label->setText("CCCCCCCC");
  48.  
  49.     }
  50. };

Última edición por xKuZz; 01/08/2016 a las 10:51 Razón: Añadir código ejemplo
  #4 (permalink)  
Antiguo 01/08/2016, 12:22
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Respuesta: Qt: Personalizar QLineEdit

Hola

Cita:
Iniciado por dehm Ver Mensaje
Te comentaría que es tan fácil como crear una clase derivada a partir de QLineEdit y añadir o modificar los aspectos que quieras, pero como sabes 1000 veces más que yo de Qt asumo que no he entendido la pregunta
Ufff, ando prácticamente desconectado de la programación desde hace meses, lo único que he hecho en meses es un par de proyectos para Android (ahora estoy con uno), pero tengo que actualizar un programa que hice hace tiempo y sería una mejora muy "chula" ese QLineEdit personalizado.

Sí, eso es lo que quiero, hacer una clase derivada de QLineEdit, pero es un tema que nunca toqué y ando un poco perdido, estaba buscando algún ejemplo para orientarme.

Cita:
Iniciado por xKuZz Ver Mensaje
Yo lo haría así, seguramente haya más maneras de hacerlo.
Para asegurarte de que sea float puedes:
  • Utilizar un QLineEdit y utilizar un validator.
  • Utilizar un QDoubleSpinBox.
Me perdí un poco con el QDoubleSpinBox, el valor float que necesito poder asignarle al QLineEdit no tengo que mostrarlo, si no el resultado de multiplicar ese valor por el número que introduzca el usuario.

Voy a revisar tu ejemplo :)

Un saludo
  #5 (permalink)  
Antiguo 01/08/2016, 12:32
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 2 meses
Puntos: 27
Respuesta: Qt: Personalizar QLineEdit

Se puede hacer con un QLineEdit perfectamente, hasta esta noche 23h-24h (hora de España )no podré volver a ponerme con el pc, ¿podrías cuál es la funcionalidad exacta (más o menos) que buscas del QLineEdit para poder ayudarte mejor?

Saludos.
  #6 (permalink)  
Antiguo 01/08/2016, 12:53
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Qt: Personalizar QLineEdit

Solo un detalle, xKuZz.

Q_PROPERTY únicamente es necesario usarlo si vas a acceder a la clase a través de metadatos, por ejemplo para hacerla accesible por scripting, o para que la propiedad sea visible desde QtCreator... aunque para esto último también habría que crear el plugin específico...

Lo comento porque esa parte es quizás la menos necesaria de todas... aunque sea una tontería su implementación :)

jc_moj, quizás sería más sencillo si hicieses un pequeño montaje con el paint o gimp añadiendo todo lujo de explicaciones al boceto para hacernos una idea de lo que quieres hacer.

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.
  #7 (permalink)  
Antiguo 01/08/2016, 13:58
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Respuesta: Qt: Personalizar QLineEdit

Hola

Cita:
Iniciado por eferion Ver Mensaje
jc_moj, quizás sería más sencillo si hicieses un pequeño montaje con el paint o gimp
Sí, creo que será mejor :



Lo que yo quiero añadirle por código serían esos números rojos, bueno, no tienen que ser tan grandes, los puse así para que se vean bien (y por que soy muy malo con gimp ) y la posición más o menos esa.

Ese número iría cambiando a medida que el usuario introduce un numero (solo aceptaría números enteros el QLineEdit) y sería el resultado de multiplicar el número que haya tecleado el usuario por el valor de la nueva propiedad de tipo float que debería tener el QlineEdit. Además tendría que implementar un getter que me de ese número sobreimpreso.

Hace tiempo creo recordar que vi algo parecido, solo que ahí iba mostrándose el número de caracteres que se iban tecleando, pero no encuentro ese ejemplo ahora :(

Un saludo
  #8 (permalink)  
Antiguo 01/08/2016, 16:14
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 2 meses
Puntos: 27
Respuesta: Qt: Personalizar QLineEdit

Ahora se ve bastante más claro:
  1. La nueva clase herederá de QLineEdit, si queremos que utilice las mismas funciones que QLineEdit utilizaremos herencia pública, posteriormente si utilizas C++11 o superior, consideramos eliminar algunas de las funciones públicas que pueden modificar el comportamiento buscado.
  2. En la parte privada de la clase añadimos un QHBoxLayout* (para la parte visual) y un QLabel* (para mostrar el número multiplicado).
  3. Empezamos el constructor llamando al constructor de QLineEdit en la lista de inicialización pasado como argumento el Widget superior.
  4. Para permitir sólo números enteros utilizamos la función setValidator de QLineEdit con un QIntValidator en el constructor.
  5. En el constructor inicializamos el Label con el valor nulo y le damos el valor deseado
  6. Para conseguir el efecto visual deseado haremos los siguiente. El Layout lo inicializamos tomando como padre al widget actual (this) y al layout le añadimos el label con alineación a la derecha.
  7. Por último conectamos la señal de cambio del QLineEdit heredada con un slot que creamos para modificar el label.
  8. Añade todo lo demás que te haga falta.

Código C++:
Ver original
  1. // Considera si quieres herencia o agregación para el uso que le vayas a dar
  2. class myLineEdit : public QLineEdit {
  3.     Q_OBJECT
  4. public:
  5.     myLineEdit(QWidget* parent) : QLineEdit(parent) {
  6.         // Permitimos sólo números enteros
  7.         QLineEdit::setValidator(new QIntValidator(this));
  8.         // Creamos un QLabel para poner el número multiplicado
  9.         label = new QLabel("0.00",this);
  10.         // Usamos CSS para ponerlo en rojo
  11.         label->setStyleSheet("color: DarkRed");
  12.  
  13.         // Creamos un Layout sobre el QLineEdit y añadimos el label en la derecha
  14.         myLay = new QHBoxLayout(this);
  15.         myLay->addWidget(label,0,Qt::AlignRight);
  16.  
  17.         // Conectamos la señal de cambio en el QLineEdit con el slot que está a continuación
  18.         connect(this,SIGNAL(textChanged(QString)), this, SLOT(setLabel(QString)));
  19.     }
  20.     // Considera quitar el acceso público a algunas opciones si has determinado usar herencia
  21.     void setValidator(const QValidator *) = delete;
  22.     void setInputMask(const QString &inputMask) = delete;
  23.  
  24. private slots:
  25.     // El siguiente slot modifica el valor del labe
  26.     void setLabel(QString s) {
  27.         double numero = s.toInt() * propiedad;
  28.         label->setText(QString::number(numero));
  29.     }
  30.  
  31. private:
  32.     QLabel* label;
  33.     QHBoxLayout* myLay;
  34.     float propiedad = 5.02;
  35. };
  #9 (permalink)  
Antiguo 01/08/2016, 16:32
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Qt: Personalizar QLineEdit

Veo que xKuZz se me adelantó por unos minutos... aun así te pongo mi propuesta para que no caiga en saco roto :)

Las dos versiones son bastante parecidas aunque cada una tiene sus ventajas.

Código C++:
Ver original
  1. #include <QLineEdit>
  2.  
  3. class QLabel;
  4.  
  5. class LineEdit2
  6.     : public QLineEdit
  7. {
  8.     Q_OBJECT
  9.  
  10. public:
  11.     LineEdit2(
  12.             QWidget* parent = nullptr);
  13.  
  14.     ~LineEdit2();
  15.  
  16.     void SetLabelOffset(int offset);
  17.  
  18.     int GetLabelOffset() const;
  19.  
  20.     void SetMultiplier(double value);
  21.  
  22.     double GetMultiplier() const;
  23.  
  24.     double GetValue() const;
  25.  
  26. private:
  27.  
  28.     QLabel* _label;
  29.     int _labelOffset;
  30.  
  31.     double _multiplier;
  32.  
  33.     void resizeEvent(QResizeEvent *event) override;
  34.  
  35. private slots:
  36.  
  37.     void UpdateValue();
  38.     void UpdatePosition();
  39. };
  40.  
  41. LineEdit2::LineEdit2(QWidget *parent)
  42.     : QLineEdit(parent),
  43.       _label(new QLabel(this)),
  44.       _labelOffset(50),
  45.       _multiplier(1.0)
  46. {
  47.   _label->setText("0.00");
  48.   _label->setAlignment(Qt::AlignRight | Qt::AlignHCenter);
  49.   _label->setStyleSheet("color: darkred");
  50.  
  51.   setValidator(new QIntValidator(this));
  52.  
  53.   connect(this,SIGNAL(editingFinished()),SLOT(UpdateValue()));
  54. }
  55.  
  56. LineEdit2::~LineEdit2()
  57. {
  58.  
  59. }
  60.  
  61. void LineEdit2::SetLabelOffset(int offset)
  62. {
  63.   if( _labelOffset != offset )
  64.   {
  65.     _labelOffset = offset;
  66.     UpdatePosition();
  67.   }
  68. }
  69.  
  70. int LineEdit2::GetLabelOffset() const
  71. {
  72.   return _labelOffset;
  73. }
  74.  
  75. void LineEdit2::SetMultiplier(double value)
  76. {
  77.   if( _multiplier != value )
  78.   {
  79.     _multiplier = value;
  80.     UpdateValue();
  81.   }
  82. }
  83.  
  84. double LineEdit2::GetMultiplier() const
  85. {
  86.   return _multiplier;
  87. }
  88.  
  89. double LineEdit2::GetValue() const
  90. {
  91.   return _label->text().toDouble();
  92. }
  93.  
  94. void LineEdit2::resizeEvent(QResizeEvent *event)
  95. {
  96.   QLineEdit::resizeEvent(event);
  97.   UpdatePosition();
  98. }
  99.  
  100. void LineEdit2::UpdateValue()
  101. {
  102.   auto value = text().toDouble();
  103.   auto text = QString::number(value*_multiplier,'f',2);
  104.   auto pos = text.indexOf('.');
  105.   if( pos < 0 )
  106.     text += ".00";
  107.   else
  108.     text += QString(pos+3-text.length(),'0');
  109.  
  110.   _label->setText(text);
  111. }
  112.  
  113. void LineEdit2::UpdatePosition()
  114. {
  115.   _label->move(width()-_labelOffset,1);
  116.   _label->resize(_labelOffset-1,height()-2);
  117. }

Lo de deshabilitar el acceso a los métodos no lo he puesto porque tirando de polimorfismo se pueden seguir llamando a las funciones, aunque no deja de ser una pequeña barrera para evitar accesos no deseados:

Código C++:
Ver original
  1. struct Base
  2. {
  3.     void func(){}
  4. };
  5.  
  6. struct Derivada : public Base
  7. {
  8.     void func() = delete;
  9. };
  10.  
  11. int main()
  12. {
  13.     Derivada* d = new Derivada;
  14.     Base* b = d;
  15.    
  16.     d->func(); // Error de compilación
  17.     b->func(); // OK
  18. }

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.
  #10 (permalink)  
Antiguo 01/08/2016, 16:56
 
Fecha de Ingreso: septiembre-2010
Mensajes: 494
Antigüedad: 13 años, 6 meses
Puntos: 10
Respuesta: Qt: Personalizar QLineEdit

Qué máquinas sois.
Yo me estaba peleando porque no se me veía el label con los valores actualizados (la cosa de perder la poca costumbre que tenía manejando los layouts a mano :( )

Pero creo que xKuZz ha acertado con la señal...de forma que cada vez que se actualiza cualquier dígito en el QLineEdit, se muestra el valor actualizado en el label :D (será porque yo también había usado esa señal ) Aunque yo ni siquiera había puesto un validador.


Por cierto, creo que es la primera vez que veo el uso de delete para evitar accesos a algunos métodos.(menos aún la forma de saltárse la restricción) Lo dicho, sois unos máquinas.
__________________
Mi calculadora en Qt
  #11 (permalink)  
Antiguo 02/08/2016, 02:37
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Respuesta: Qt: Personalizar QLineEdit

Hola

Cita:
Iniciado por dehm Ver Mensaje
Qué máquinas sois.
Pues sí @dehm, unos auténticos máquinas :)

En cuanto pueda voy a ver las dos propuestas detenidamente.

Y yo que estaba "encabezonado" en que había que sobreescribir el método que se encarga de dibujar el control y en el dibujar el nuevo texto.

Un saludo
  #12 (permalink)  
Antiguo 02/08/2016, 12:26
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: Qt: Personalizar QLineEdit

Cita:
Iniciado por jc_moj Ver Mensaje
Y yo que estaba "encabezonado" en que había que sobreescribir el método que se encarga de dibujar el control y en el dibujar el nuevo texto.
Esa es la forma que menos rendimiento consume salvo que lo hagas desastrosamente mal... eso a costa de tener que reescribir un montón de código que ya está escrito en otros sitios... pero créeme que por poder, se puede.

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.
  #13 (permalink)  
Antiguo 02/08/2016, 13:13
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Respuesta: Qt: Personalizar QLineEdit

Hola

Cita:
Iniciado por eferion Ver Mensaje
Esa es la forma que menos rendimiento consume salvo que lo hagas desastrosamente mal... eso a costa de tener que reescribir un montón de código que ya está escrito en otros sitios... pero créeme que por poder, se puede.
Seguro que en alguna parte vi algún ejemplo así, de ahí que estuviese empeñado en hacerlo así.

Solo he tenido tiempo de hacer copy & paste, pero aquí está el resultado de las dos propuestas, sin tocar nada:



En ambos casos la etiqueta sigue en su sitio cuando se redimensiona, la versión de @xKuZz no coloca correctamente el texto, o es muy grande, pero no he tenido tiempo de mirarlo :(

A ver si mañana tengo un rato. Me gustaron las dos propuestas.

Un saludo
  #14 (permalink)  
Antiguo 02/08/2016, 13:48
Avatar de xKuZz  
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 2 meses
Puntos: 27
Respuesta: Qt: Personalizar QLineEdit

Perdona, lo puse sobre el centralWidget de un proyecto de prueba y no pensé en eso. Lo que impide que lo veas completamente es el margen por defecto del layout. Para solucionarlo al crear el layout en el constructor de myLineEdit le quitas el margen utilizando la función setMargin(0) y para que no se quede muy pegado al final añade espacio con addSpacing(int), algo así:

Código C++:
Ver original
  1. // Creamos un Layout sobre el QLineEdit y añadimos el label en la derecha
  2.         myLay = new QHBoxLayout(this);
  3.         myLay->setMargin(0);
  4.         myLay->addWidget(label,0,Qt::AlignRight);
  5.         myLay->addSpacing(5);
  #15 (permalink)  
Antiguo 02/08/2016, 14:30
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Respuesta: Qt: Personalizar QLineEdit

Hola

Cita:
Iniciado por xKuZz Ver Mensaje
Perdona, lo puse sobre el centralWidget de un proyecto de prueba y no pensé en eso. Lo que impide que lo veas completamente es el margen por defecto del layout. Para solucionarlo al crear el layout en el constructor de myLineEdit le quitas el margen utilizando la función setMargin(0) y para que no se quede muy pegado al final añade espacio con addSpacing(int), algo así:

Código C++:
Ver original
  1. // Creamos un Layout sobre el QLineEdit y añadimos el label en la derecha
  2.         myLay = new QHBoxLayout(this);
  3.         myLay->setMargin(0);
  4.         myLay->addWidget(label,0,Qt::AlignRight);
  5.         myLay->addSpacing(5);
Pues después de escribir mi anterior mensaje, ya en el coche, iba pensando que tenía que ser problema de márgenes.

Mañana lo pruebo y comento.

Un saludo
  #16 (permalink)  
Antiguo 03/08/2016, 02:40
Avatar de jc_moj  
Fecha de Ingreso: septiembre-2009
Ubicación: Andalucía
Mensajes: 137
Antigüedad: 14 años, 7 meses
Puntos: 12
Respuesta: Qt: Personalizar QLineEdit

Hola

Pues sí, era problema con el margen:



Las dos soluciones, aunque muy parecidas, cada una dibuja la etiqueta de una forma, funcionan de forma idéntica y muy bien :)

Un saludo

Etiquetas: personalizar
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 12:54.