View Full Version : Editable QLCDNumber
QDmitry
25th June 2013, 16:22
Hi guys
I'd like to hear you suggestions to the following problem.
I need an editable lcd editor in my GUI. I mean that I display some value in it and allow a user to edit it in a clickable way. For example, the current value is 123. A user clicks to the area of digit 2 and press some digit key on his keyboard to modify this digit.
The quick solution spinning in my mind is to implement a QButton over the QLCDNumber widget but it seems to be a dirty hack.
Are there any tested solutions for this case? If anyone could share an example I'd be highly appreciated. But anyhow I need a concept to start.
My environment : Qt4.7, no QML.
BR,
Dmitry
wysota
25th June 2013, 17:00
Subclass QLCDNumber, activate focus and reimplement key events.
QDmitry
26th June 2013, 14:42
Thx for the idea.
Could you please clarify the following items:
1. "activate focus" - do you mean setFocus() method?
2. "reimplement key events" -ok, this is quite clear. But how do I know the exact item position to be edited? I guess I should somehow track the mouse position and the desired digit position of the LCD, right? If yes, then what is the way to get the LCD item position?
Added after 1 20 minutes:
and
3. What is the right wat to highlight the "editable" item of the current LCD value?
Inside Qt help I see the following note : "It is not possible to retrieve the contents of a QLCDNumber object, although you can retrieve the numeric value with value()". Therefore my question : is it possible to find a solution based on QLCDNumber?
QDmitry
27th June 2013, 14:57
Ok, so here is my solution to this topic.
==============================
qeditablelcd.h
==============================
#ifndef QEDITABLELCD_H
#define QEDITABLELCD_H
#include <QLCDNumber>
#include <QPaintEvent>
#include <QKeyEvent>
#include <QRectF>
#include <QWheelEvent>
class qeditablelcd : public QLCDNumber
{
Q_OBJECT
public:
explicit qeditablelcd(QObject *parent = 0);
signals:
public slots:
protected :
void mousePressEvent ( QMouseEvent * e );
void keyPressEvent ( QKeyEvent * event );
void paintEvent( QPaintEvent * e );
void wheelEvent ( QWheelEvent * event );
private :
void setDigitAreaPressed( QMouseEvent * e, const int areaId = -1 );
void positionValueIncrement( const int numSteps );
QRectF mDigitRect;
int mDigitIdToChange;
};
#endif // QEDITABLELCD_H
======================
qeditablelcd.cpp
======================
#include <QMouseEvent>
#include <QBrush>
#include <QPainter>
#include <QString>
#include <QtCore/qmath.h>
#include "qeditablelcd.h"
qeditablelcd::qeditablelcd(QObject *parent) :
QLCDNumber()
{
/* Mouse selected digit item Id */
this->mDigitIdToChange = -1;
this->setFocusPolicy(Qt::ClickFocus);
}
void qeditablelcd::setDigitAreaPressed( QMouseEvent * e, const int areaId )
{
int ndigits = this->digitCount();
int digitSpace = this->smallDecimalPoint() ? 2 : 1;
int xSegLen = this->width()*5/(ndigits*(5 + digitSpace) + digitSpace);
int ySegLen = this->height()*5/12;
int segLen = ySegLen > xSegLen ? xSegLen : ySegLen;
int xAdvance = segLen*( 5 + digitSpace )/5;
int xOffset = ( this->width() - ndigits*xAdvance + segLen/5 )/2;
/* Use the predefined Id if necessary */
if ( areaId != -1 ) {
this->mDigitRect.setRect(xOffset + xAdvance*areaId, this->y(), xAdvance, this->height() );
return;
}
int xPos = e->pos().x();
int itemId = -1;
for ( int i = 0; i < ndigits; i++ ) {
if ((xPos >= xOffset + xAdvance*i) && (xPos < xOffset + xAdvance*(i + 1))) {
itemId = i;
this->mDigitRect.setRect(xOffset + xAdvance*itemId, this->y(), xAdvance, this->height() );
break;
}
}
this->mDigitIdToChange = itemId;
}
void qeditablelcd::mousePressEvent ( QMouseEvent * e )
{
this->setDigitAreaPressed(e);
update();
}
void qeditablelcd::paintEvent(QPaintEvent * e)
{
/* If are not selected - nothing to draw except lcdnumber itself */
/* Though never occured while testing */
if (!( this->mDigitIdToChange == -1 )) {
QPainter Painter(this);
Painter.setBrush(QBrush(Qt::black, Qt::Dense7Pattern));
Painter.drawRect(this->mDigitRect);
}
QLCDNumber::paintEvent(e);
}
void qeditablelcd::keyPressEvent ( QKeyEvent * event )
{
int key = event->key();
/* Filter out all non digit keys */
if (( key >= Qt::Key_0 ) && ( key <= Qt::Key_9 )) {
if ( this->mDigitIdToChange != -1 ) {
/* Convert double value to a string representation */
QString lcdStr;
lcdStr.setNum(int(this->value()));
/* Insert starting zeros in lcdStr representation */
int l = this->digitCount() - lcdStr.length();
for (int i = 0; i < l; i++) {
lcdStr.insert(0,"0");
}
/* Convert key value to string representation */
QString keyVal;
keyVal.setNum( key - Qt::Key_0 );
/* Replace selected digit with the desired one */
lcdStr.replace(this->mDigitIdToChange, 1, keyVal);
/* Update lcdnumber */
this->display(lcdStr.toDouble());
/* Switch to the next digit item */
if ( this->mDigitIdToChange == this->digitCount() - 1 ) {
this->mDigitIdToChange = 0;
} else {
this->mDigitIdToChange++;
}
this->setDigitAreaPressed(NULL, this->mDigitIdToChange);
update();
}
}
/* Enter + Esc press event handler */
if (( key == Qt::Key_Return ) || ( key == Qt::Key_Escape )) {
this->mDigitIdToChange = -1;
update();
}
}
void qeditablelcd::wheelEvent ( QWheelEvent * event )
{
if ( this->mDigitIdToChange != -1 ) {
/* Number of steps within a single event = delta() / (15*8) */
this->positionValueIncrement(event->delta()/(15*8));
}
}
void qeditablelcd::positionValueIncrement( const int numSteps )
{
/* Multiply rate */
qreal multiplyer = qPow( 10, this->digitCount() - 1 - this->mDigitIdToChange );
this->display(this->value() + numSteps*multiplyer );
}
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.