2

I want to get the selected text from a QLineEdit widget. We get the selected text by clicking on a push button. It works if the text was programatically selected with selectAll. But it does not work if the text is selected with a mouse. In the latter case, an empty string is shown.

Why there text is such a difference and how to get the mouse selection working?

#!/usr/bin/python

import sys
from PyQt5.QtWidgets import (QWidget, QLineEdit, QPushButton, QHBoxLayout,
    QVBoxLayout, QApplication, QMessageBox)
from PyQt5.QtCore import Qt


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        vbox = QVBoxLayout()
        hbox1 = QHBoxLayout()

        self.qle = QLineEdit(self)
        self.qle.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
        self.qle.setText('There are 3 hawks in the sky')

        hbox1.addWidget(self.qle)

        selAllBtn = QPushButton('Select all', self)
        selAllBtn.clicked.connect(self.onSelectAll)

        deselBtn = QPushButton('Deselect', self)
        deselBtn.clicked.connect(self.onDeSelectAll)

        showSelBtn = QPushButton('Show selected', self)
        showSelBtn.clicked.connect(self.onShowSelected)

        hbox2 = QHBoxLayout()
        hbox2.addWidget(selAllBtn)
        hbox2.addSpacing(15)
        hbox2.addWidget(deselBtn)
        hbox2.addSpacing(15)
        hbox2.addWidget(showSelBtn)

        vbox.addLayout(hbox1)
        vbox.addSpacing(20)
        vbox.addLayout(hbox2)

        self.setLayout(vbox)

        self.setWindowTitle('Selected text')
        self.show()

    def onSelectAll(self):
        self.qle.selectAll()

    def onDeSelectAll(self):
        self.qle.deselect()

    def onShowSelected(self):
        QMessageBox.information(self, 'info', self.qle.selectedText())



def main():

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Jan Bodnar
  • 10,969
  • 6
  • 68
  • 77

1 Answers1

3

If the source code is revised:

void QLineEdit::focusOutEvent(QFocusEvent *e)
{
    // ...
    Qt::FocusReason reason = e->reason();
    if (reason != Qt::ActiveWindowFocusReason &&
        reason != Qt::PopupFocusReason)
        deselect();
    // ...

And in the case of pressing the button the reason for the QFocusEvent is Qt::MouseFocusReason so the selection will be removed.

A workaround would be to get the selected text before the selection is removed and set it again:

class LineEdit(QLineEdit):
    def focusOutEvent(self, e):
        start = self.selectionStart()
        length = self.selectionLength()
        super().focusOutEvent(e)
        self.setSelection(start, length)
self.qle = LineEdit(self)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241