6

I need help inserting a button inside in a QLineEdit that can call a function.

For example, like this google image:

Button in line edit

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Andrew Zhuk
  • 500
  • 8
  • 23

6 Answers6

13

Below is a nearly direct translation of the Qt code from here.

Differences:

  • button is always visible
  • clicking on the button emits buttonClicked(bool) signal

Code:

from PyQt4 import QtGui, QtCore

class ButtonLineEdit(QtGui.QLineEdit):
    buttonClicked = QtCore.pyqtSignal(bool)

    def __init__(self, icon_file, parent=None):
        super(ButtonLineEdit, self).__init__(parent)

        self.button = QtGui.QToolButton(self)
        self.button.setIcon(QtGui.QIcon(icon_file))
        self.button.setStyleSheet('border: 0px; padding: 0px;')
        self.button.setCursor(QtCore.Qt.ArrowCursor)
        self.button.clicked.connect(self.buttonClicked.emit)

        frameWidth = self.style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
        buttonSize = self.button.sizeHint()

        self.setStyleSheet('QLineEdit {padding-right: %dpx; }' % (buttonSize.width() + frameWidth + 1))
        self.setMinimumSize(max(self.minimumSizeHint().width(), buttonSize.width() + frameWidth*2 + 2),
                            max(self.minimumSizeHint().height(), buttonSize.height() + frameWidth*2 + 2))

    def resizeEvent(self, event):
        buttonSize = self.button.sizeHint()
        frameWidth = self.style().pixelMetric(QtGui.QStyle.PM_DefaultFrameWidth)
        self.button.move(self.rect().right() - frameWidth - buttonSize.width(),
                         (self.rect().bottom() - buttonSize.height() + 1)/2)
        super(ButtonLineEdit, self).resizeEvent(event)

Usage:

import sys
from PyQt4 import QtGui

def buttonClicked():
    print 'You clicked the button!'

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)

    main = ButtonLineEdit('/path/to/my_fancy_icon.png')
    main.buttonClicked.connect(buttonClicked)
    main.show()

    sys.exit(app.exec_())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Avaris
  • 35,883
  • 7
  • 81
  • 72
  • 4
    As of Qt 5.2 there is [QLineEdit.addAction()](http://doc.qt.io/qt-5/qlineedit.html#addAction) which is a built-in way to do that. Also [QLineEdit.setClearButtonEnabled()](http://doc.qt.io/qt-5/qlineedit.html#clearButtonEnabled-prop) adds a cross button to the right (as on certain OSX controls) to clear the widget's contents. – blameless75 Mar 02 '16 at 11:02
  • @Avaris I have adapted your solution to my needs but there is a slight problem. When the content of the QLineEdit is too long it overlaps with the button. I managed to mitigate the problem to some extent by setting the background color of the button to white. The problem with this approach though is that part of the contents disappear behind the button. One cannot scroll to e right with the cursor or mouse to reveal the rest of the contents. How can I solve this problem? Thanks. – Giuseppe May 17 '20 at 09:47
10

Here is the runnable code:

enter image description here

from PyQt4.QtGui import *
from PyQt4.QtCore import *
from sys import argv, exit

class ButtonInLineEdit(QLineEdit):
    def __init__(self,parent=None):
        QLineEdit.__init__(self,parent)

        self.ButtonShowKeyboard = QToolButton(self)
        self.ButtonShowKeyboard.setCursor(Qt.PointingHandCursor)

        self.ButtonShowKeyboard.setFocusPolicy(Qt.NoFocus)
        self.ButtonShowKeyboard.setIcon(QIcon("icons/myIcon.png"))
        self.ButtonShowKeyboard.setStyleSheet("background: transparent; border: none;")

        layout = QHBoxLayout(self)
        layout.addWidget(self.ButtonShowKeyboard,0,Qt.AlignRight)

        layout.setSpacing(0)
        layout.setMargin(5)

        self.ButtonShowKeyboard.setToolTip(QApplication.translate("None", "Show virtual keyboard", None, QApplication.UnicodeUTF8))

def MyFunction(arg=None):
    print "MyFunction() called: arg = %s"%arg

a=QApplication(argv)
LineEdit = ButtonInLineEdit()
LineEdit.connect(LineEdit.ButtonShowKeyboard, SIGNAL("clicked()"), MyFunction)
LineEdit.show()
exit(a.exec_())
alphanumeric
  • 17,967
  • 64
  • 244
  • 392
  • Hey there, I am doing something similar, however I am trying to append such 'button' onto the UI that I have created in Qt Designer. Was wondering if it is possible to do so using your solution? – yan Mar 12 '15 at 08:18
9

As of Qt 5.2 there is QLineEdit.addAction() which is a built-in way to do that. Also QLineEdit.setClearButtonEnabled() adds a cross button to the right (as on certain OSX controls) to clear the widget's contents.

blameless75
  • 2,148
  • 2
  • 19
  • 14
0

Thanks to our colleague, Avaris, But his example is did not convince me and I decided to make a on another more easier to and less code. Go to learn!

#this code for example in btninlineedit.py

from PyQt4.QtGui import *
from PyQt4.QtCore import Qt
from PyQt4 import QtCore, QtGui
#Andrey Zhuk.
#####
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class ButtonInLineEdit(QLineEdit):
    def __init__(self,parent=None):
        QLineEdit.__init__(self,parent)

        self.ButtonShowKeyboard = QToolButton(self)
        self.ButtonShowKeyboard.setCursor(Qt.PointingHandCursor)
        #self.ButtonShowKeyboard.show()
        self.ButtonShowKeyboard.setFocusPolicy(Qt.NoFocus)
        self.ButtonShowKeyboard.setIcon(QtGui.QIcon("images/YourIcon.svg"))
        self.ButtonShowKeyboard.setStyleSheet("background: transparent; border: none;")

        layout = QHBoxLayout(self)
        layout.addWidget(self.ButtonShowKeyboard,0,Qt.AlignRight)

        layout.setSpacing(0)
        layout.setMargin(5)
        # ToolTip 
        self.ButtonShowKeyboard.setToolTip(QtGui.QApplication.translate("None", "Show virtual keyboard", None, QtGui.QApplication.UnicodeUTF8))


#this code for example in main.py            
class main(/////****///**/): 
    def __init__(self):
     #blablablablaaaa

        self.KeyboardShow = False

self.connect(self.LineEdit.ButtonShowKeyboard, QtCore.SIGNAL("clicked()"), self.KeyboardShowHide)


def KeyboardShowHide(self):
    try:
        if self.KeyboardShow:
            self.KeyboardShow = False
            self.WidgetKeyboard.hide()
        else:
            self.KeyboardShow = True
            self.WidgetKeyboard.show()
    except:
            debug ("ошибка при вызове функции скрытые или показа клавиатуры (Main Window)")
#this code for example in btninlineedit.py

from forms.btninlineedit import ButtonInLineEdit



        self.LineEdit = ButtonInLineEdit()
Andrew Zhuk
  • 500
  • 8
  • 23
0

In qt C++, I can drag and drop pushButton in the left of LineEdit. After that, I just need to set styleSheet for LineEdit with this code:

int FramWidth = lineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);

lineEdit->setStyleSheet(QString("QLineEdit{padding-right: %1px; }").arg(ui->pushButton->sizeHint().width() + FramWidth +5));

And it works for me. Hope it can help.

Antimony
  • 2,230
  • 3
  • 28
  • 38
0
class LineEditFileDialogWidget(QtWidgets.QLineEdit):
    def __init__(self, parent=None):
        super(LineEditFileDialogWidget, self).__init__(parent)
        self.setReadOnly(True)

        icon = QtWidgets.QApplication.style().standardIcon(QtWidgets.QStyle.SP_DirIcon)
        self.action = self.addAction(icon, QtWidgets.QLineEdit.TrailingPosition)
        self.action.triggered.connect(some function)

Here is an example of using the icon along with QLineEdit