c++qtqwidgetqlineeditqframe

QLineEdit with custom button


I need to implement LineEdit widget with possibility to add tool buttons at the right end of text area. I know two ways of doing that but both solutions seems ugly.

1) add tool buttons as child widgets of QLineEdit and handle resizeEvent to position them correctly. The main disadvantage is that if text is enough long it may appear under tool buttons.

2) Another solution is to put line edit and buttons inside frame and overwrite style to hide lineEdits frame and make QFrame look like QLineEdit.

I need a best way to implement such widget. Also my widget should be style aware.


Solution

  • The original blog post is gone now, but Trolltech once posted an example of a clear button for Qt 4.

    Results

    Line edit with no text:

    Line edit with some text (button appears):

    Line edit full of text (doesn’t go underneath button):

    Source

    lineedit.h

    /****************************************************************************
    **
    ** Copyright (c) 2007 Trolltech ASA <info@trolltech.com>
    **
    ** Use, modification and distribution is allowed without limitation,
    ** warranty, liability or support of any kind.
    **        
    ****************************************************************************/
    
    #ifndef LINEEDIT_H
    #define LINEEDIT_H
    
    #include <QLineEdit>
    
    class QToolButton;
    
    class LineEdit : public QLineEdit
    {
        Q_OBJECT
    
    public:
        LineEdit(QWidget *parent = 0);
    
    protected:
        void resizeEvent(QResizeEvent *);
    
    private slots:
        void updateCloseButton(const QString &text);
    
    private:
        QToolButton *clearButton;
    };
    
    #endif // LIENEDIT_H
    

    lineedit.cpp

    /****************************************************************************
    **
    ** Copyright (c) 2007 Trolltech ASA <info@trolltech.com>
    **
    ** Use, modification and distribution is allowed without limitation,
    ** warranty, liability or support of any kind.
    **
    ****************************************************************************/
    
    #include "lineedit.h"
    #include <QToolButton>
    #include <QStyle>
    
    LineEdit::LineEdit(QWidget *parent)
        : QLineEdit(parent)
    {
        clearButton = new QToolButton(this);
        QPixmap pixmap("fileclose.png");
        clearButton->setIcon(QIcon(pixmap));
        clearButton->setIconSize(pixmap.size());
        clearButton->setCursor(Qt::ArrowCursor);
        clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
        clearButton->hide();
        connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
        connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(updateCloseButton(const QString&)));
        int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
        setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(clearButton->sizeHint().width() + frameWidth + 1));
        QSize msz = minimumSizeHint();
        setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2),
                       qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2));
    }
    
    void LineEdit::resizeEvent(QResizeEvent *)
    {
        QSize sz = clearButton->sizeHint();
        int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
        clearButton->move(rect().right() - frameWidth - sz.width(),
                          (rect().bottom() + 1 - sz.height())/2);
    }
    
    void LineEdit::updateCloseButton(const QString& text)
    {
        clearButton->setVisible(!text.isEmpty());
    }