18

There is a Search field with the magnification-lens and a greyed out "search" keyword at the top right corner of stackoverflow.com web site:

enter image description here

I wonder if it is possible to achieve a same appearance with QLineEdit. If so then how?

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
alphanumeric
  • 17,967
  • 64
  • 244
  • 392
  • 3
    Theres are a few ways of doing this, but one simple way that I think would work, is to add a `QLabel` and a `QLineEdit` in a `QFrame`, remove the borders from the `QLineEdit` and make its background transparent. Then set a pixmap to the label. Then you just set a frame style and the background color for your `QFrame` object. Should be simple enough. – thuga Jan 15 '15 at 07:29
  • possible duplicate of [How to do - inside in QlineEdit insert the button.\[pyqt4\]](http://stackoverflow.com/questions/12462562/how-to-do-inside-in-qlineedit-insert-the-button-pyqt4) – NoDataDumpNoContribution Jan 29 '15 at 08:30

7 Answers7

21
QLineEdit* _lineEdit = new QLineEdit();
_lineEdit->setClearButtonEnabled(true);
_lineEdit->addAction(":/resources/search.ico", QLineEdit::LeadingPosition);
_lineEdit->setPlaceHolderText("Search...");

extracted from: http://saurabhg.com/programming/search-box-using-qlineedit/

lifeisfoo
  • 15,478
  • 6
  • 74
  • 115
laurapons
  • 971
  • 13
  • 32
17

Simple Way for Dummies

  1. Add a QLineEdit, and set it frameless by QLineEdit::setFrame
  2. Add a QLabel with background color in white (by stylesheet) and a icon
  3. Combine the line edit and the label with a layout, set spacing to 0
  4. Set placeholder text with QLineEdit::setPlaceholderText

Result

enter image description here


Advanced Way

Check this thread: "Can QLineEdit do this?"

And the related python code: http://bazaar.launchpad.net/~henning-schroeder/%2Bjunk/qtwidgets/annotate/head:/qtwidgets/lineedit.py

Or

"How to do - inside in QLineEdit insert the button.[pyqt4]"

Basically customized a QLineEdit by painting a widget(label, button or even combobox) onto it. Then reset the margin, cursor, padding and the paint event. No magics!

Community
  • 1
  • 1
Tay2510
  • 5,748
  • 7
  • 39
  • 58
  • 1
    I would probably prefer the do the simple way first. It's not clear if the advanced way would look or react better, but it's more complex. The simple way might be the better way. – NoDataDumpNoContribution Jan 29 '15 at 08:27
  • @Trilarion: I fully agree. With the second solution, you end up replicating layout code, there is one more special class in your code base and you lose flexibility. What if you want to have an additional icon on the right? I think this also shows what's wrong with "modern" GUIs and why they are so bloated: too many special cases for the same, general idea (i.e., context menus, lists and table views, dockable widgets, which are essentially all about arrangements of graphical items). Functional Geometry is a far better approach, I wish that this idea would have broader adoption in practice... – ftl Feb 12 '19 at 16:50
16

Here is an alternate simple way:

Set the placeholderText to "" and the font Family to Seqoe UI Symbol or other font that can be found on your target systems that include the U+1F50D LEFT-POINTING MAGNIFYING GLASS glyph.

demo of result

Zak
  • 936
  • 10
  • 19
11

Here's a way to achieve this with stylesheets only:

QLineEdit {
    background: #f3f3f3;
    background-image: url(:Images/search.svg); /* actual size, e.g. 16x16 */
    background-repeat: no-repeat;
    background-position: left;
    color: #252424;
    font-family: SegoeUI;
    font-size: 12px;
    padding: 2 2 2 20; /* left padding (last number) must be more than the icon's width */
}

Here's the result:

A QLineEdit search field

It's still not perfect. You don't have much influence over the icon's position.

i know nothing
  • 951
  • 1
  • 10
  • 27
  • 2
    Here is an example with some influence on the icon's position: QLineEdit { background-color: white; padding-right: 8px; padding-left: 16px; background-image: url("%s"); background-repeat: no-repeat; background-position: right; background-origin: content; } QLineEdit:disabled { /* same with different bgcolor */} Using the origin position content ensures your padding applies to the image. – PiRK Jan 16 '19 at 10:04
  • 1
    @PiRK, tried your example but it does not produce the desired example (Qt 5.12). It's aligned to the right, if I change it to left, the icon and text are painted on top of each other. I have tried for ages to hack Qt via stylesheet and proxystyle, to paint these icons and text in an identical way for both QLineEdit, QComboBox and editable QComboBox (with QLineEdit). Can you revisit and repost with working example. Thanks :) – bleze May 14 '20 at 08:08
  • In my example the search icon is supposed to be on the right. And my line edit is always long enough, and the search string short enough, that users don’t notice the icon and text overlap. Sorry that I cannot be of more help. – PiRK May 15 '20 at 11:40
10

To have a result like this:
Qt icon QLineEdit

You can subclass the QLineEdit.
So your header should look something like this:

#ifndef LINEEDITICON_H
#define LINEEDITICON_H

#include <QLineEdit>
#include <QIcon>

class LineEditIcon : public QLineEdit
{
    Q_OBJECT

public:
    LineEditIcon(const QIcon icon, QWidget *parent = Q_NULLPTR);
    ~LineEditIcon();
    void setIcon(QIcon icon);    
protected:
    virtual void paintEvent(QPaintEvent *event);    
private:
    QIcon m_icon;       
};

#endif // LINEEDITICON_H

And your source file look like:

#include "lineediticon.h"
#include <QPainter>

LineEditIcon::LineEditIcon(const QIcon icon, QWidget *parent)
    : QLineEdit(parent)
{
    setIcon(icon);
}

LineEditIcon::~LineEditIcon()
{    
}

void LineEditIcon::setIcon(QIcon icon)
{
    m_icon = icon;
    if (m_icon.isNull())
        setTextMargins(1, 1, 1, 1);
    else
        setTextMargins(20, 1, 1, 1);
}

void LineEditIcon::paintEvent(QPaintEvent * event)
{
    QLineEdit::paintEvent(event);
    if (!m_icon.isNull()) {
        QPainter painter(this);
        QPixmap pxm = m_icon.pixmap(height() - 6, height() - 6);
        int x = 2, cx = pxm.width();

        painter.drawPixmap(x, 3, pxm);
        painter.setPen(QColor("lightgrey"));
        painter.drawLine(cx + 2, 3, cx + 2, height() - 4);
    }
}

Edit: A possible solution is to use a custom plugin to use it directly in QtDesigner.

thibsc
  • 3,747
  • 2
  • 18
  • 38
8

QT5 addAction

```

const QIcon passwordIcon(":/new/icons/res/passwd.png");
ui->password->setClearButtonEnabled(true);
ui->password->addAction(passwordIcon, QLineEdit::LeadingPosition);

```

KunMing Xie
  • 1,613
  • 17
  • 15
2

From QT 5.2 onwards you can do something like this. You should use pointers if you want to make it more flexible:


QIcon *ico;
ico = new QIcon(":/images/search.ico");
searchEdit->addAction(*ico, QLineEdit::LeadingPosition);