PDA

View Full Version : Customize the QLineEdit, Cursor can't move one char by LeftButton / RightButton.



zimang
29th November 2010, 02:26
I draw the QLineEdit by paintEnvent(), but the cursor can't move one by one throught the left or right button. I press the right button, it moves to the end, and the beginning when I pressing the left button. But the cursor's real point is right, beacause I can backspace the character by pressing Backspace.

It seems the show problem.

Thanks a lot.


#include <QtGui>
#include <QtCore>

class Edit : public QLineEdit{

public:

Edit(const QString &t, QWidget *pParent = 0) : QLineEdit(t, pParent){
font = QFont("Sans");
font.setPixelSize(26);
setFixedSize(640, 220);
setTextMargins(4, 0, 4, 0);
}

protected:
void paintEvent(QPaintEvent *pEvent){
QPainter painter(this);
QRect r = rect();
//frame
int x2 = r.width() - 1, y2 = r.height() - 1;
painter.fillRect(r, QBrush(QColor(79, 79, 104, 255)));
painter.setPen(QPen(QColor(64, 64, 64, 255), 1));
painter.drawLine(0, 0, x2, 0);

painter.drawLine(0, 0, 0, y2);
painter.setPen(QPen(QColor(92, 92, 92, 255), 1));
painter.drawLine(x2, y2, 1, y2);
painter.drawLine(x2, y2, x2, 1);
painter.setPen(QPen(QColor(19, 19, 19, 255), 1));
painter.drawRect(QRect(1, 1, r.width() - 3, r.height() - 3));

//set clipping
int lm, tm, rm, bm;
getTextMargins(&lm, &tm, &rm, &bm);
r.setX(r.x() + lm);
r.setY(r.y() + tm);
r.setRight(r.right() - rm);
r.setBottom(r.bottom() - bm);
painter.setClipRect(r);

painter.setPen(QPen(QColor(196, 196, 196, 255), 1));
QFontMetrics fm(font);
QTextLayout tl(text(), font, this);
tl.beginLayout();
QTextLine line = tl.createLine();
if( !line.isValid() ){ return; }

tl.endLayout();
QRect lineRect(r.x(), r.y() + (r.height() - qRound(line.height()) + 1) / 2,
r.width() - 1, qRound(line.height()));
//painter.drawRect(lineRect);
int ccc = cursorPosition();
int cix = qRound(line.cursorToX(&ccc));
int minLB = qMax(0, -fm.minLeftBearing());
int minRB = qMax(0, -fm.minRightBearing());
int widthUsed = qRound(line.naturalTextWidth()) + 1 + minRB;
int hscroll;

if( (minLB + widthUsed) <= lineRect.width() ){
//hscroll = 0;
Qt::Alignment va = QStyle::visualAlignment(layoutDirection(), QFlag(this->alignment()));
va &= ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask);
switch (va) {
case Qt::AlignRight:
hscroll = widthUsed - lineRect.width() + 1;
break;
case Qt::AlignHCenter:
hscroll = (widthUsed - lineRect.width()) / 2;
break;
default:
// Left
hscroll = 0;
break;
}
hscroll -= minLB;
}else if( cix - hscroll >= lineRect.width() ){
hscroll = cix - lineRect.width() + 1;
}else if( cix - hscroll < 0 && hscroll < widthUsed ){
hscroll = cix;
}else if( widthUsed - hscroll < lineRect.width() ){
hscroll = widthUsed - lineRect.width() + 1;
}
QPoint topLeft = lineRect.topLeft() - QPoint(hscroll, line.ascent() - fm.ascent());

QVector<QTextLayout::FormatRange> selections;

QTextLayout::FormatRange o;
if( hasSelectedText() ){

o.start = selectionStart();
o.length = selectedText().length();
o.format.setBackground(QColor(88, 101, 134, 255));
o.format.setForeground(QColor(196, 196, 196, 255));
selections.append(o);
}

tl.draw(&painter, topLeft, selections);
painter.setPen(QPen(QColor(200, 0, 0, 255), 2));
//painter.drawLine(cix, lineRect.y(), cix, lineRect.y() + lineRect.height());
tl.drawCursor(&painter, topLeft, cix, 2);

}

private:
QFont font;
};

int main(int argc, char *argv[]){
QApplication a(argc, argv);

QWidget *w = new QWidget;

w->setPalette(QPalette(QColor(77, 77, 77, 255)));
QHBoxLayout *l = new QHBoxLayout(w);
Edit *e1 = new Edit(QString("test1"));
e1->setAlignment(Qt::AlignCenter);

QLineEdit *e2 = new QLineEdit(QString("test2"));

e2->setFixedSize(640, 220);

e2->setAlignment(Qt::AlignCenter);

l->addWidget(e1);
l->addWidget(e2);
w->show();

return a.exec();
}

high_flyer
29th November 2010, 11:08
Can you explain in words the logic in the calculation of 'topLeft' in your code?