Question

I am new to Qt/PySide. I want QLineEdit to select all text in it when it gets focus. After getting focus and selecting all text, it should select all text only after focus is lost and gained again. It should not select all text when I change cursor position after QLineEdit gains focus. How do I do that?

Update: My current code improved as suggested by Ashwani Kumar. I still can't get it to work though:

import sys
from PySide.QtGui import QLineEdit, QApplication, QVBoxLayout, QWidget
class MyLineEdit(QLineEdit):
    def __init__(self, parent=None):
        super(MyLineEdit, self).__init__(parent)

    def focusInEvent(self, e):
        self.selectAll()      

app = QApplication(sys.argv)
top = QWidget()
layout = QVBoxLayout()
layout.addWidget(MyLineEdit())
layout.addWidget(MyLineEdit())
top.setLayout(layout)
top.show()
app.exec_()
Was it helpful?

Solution

With focusInEvent, when you click the widget, it gets executed, but since you click, it removes the selected text.

To overcome this, we must use the mousePressEvent, this can be done two ways:

import sys
from PySide.QtGui import QLineEdit, QApplication, QVBoxLayout, QWidget
class MyLineEdit(QLineEdit):
    def __init__(self, parent=None):
        super(MyLineEdit, self).__init__(parent)

    def mousePressEvent(self, e):
        self.selectAll()      

app = QApplication(sys.argv)
top = QWidget()
layout = QVBoxLayout()
layout.addWidget(MyLineEdit())
layout.addWidget(MyLineEdit())
top.setLayout(layout)
top.show()
app.exec_()

Or you can do it by simply overriding the base QLineEdit class:

txt_demo = QtGui.QLineEdit()
txt_demo.mousePressEvent = lambda _ : txt_demo.selectAll()

However, since we are modifying the mousePressEvent, whenever you try to click text, it will always select all first.

OTHER TIPS

For future visitors, I am posting code that is working for me. As I am a newbie I am not sure if the code contains any malpractices. If it does feel free to comment and I'll update my code/answer. Code:

import sys
from PySide.QtGui import QLineEdit, QApplication, QVBoxLayout, QWidget

class LineEdit(QLineEdit):
    def __init__(self, parent=None):
        super(LineEdit, self).__init__(parent)
        self.readyToEdit = True

    def mousePressEvent(self, e, Parent=None):
        super(LineEdit, self).mousePressEvent(e) #required to deselect on 2e click
        if self.readyToEdit:
            self.selectAll()
            self.readyToEdit = False

    def focusOutEvent(self, e):
        super(LineEdit, self).focusOutEvent(e) #required to remove cursor on focusOut
        self.deselect()
        self.readyToEdit = True

app = QApplication(sys.argv)
top = QWidget()
layout = QVBoxLayout()
layout.addWidget(LineEdit())
layout.addWidget(LineEdit())
top.setLayout(layout)
top.show()
app.exec_()

You have to subclass the QLineEdit and then use the new class instead of QLineEdit. e.g: -

class MyLineEdit(QtGui.QLineEdit):
    def __init__(self, parent=None)
        super(MyLineEdit, self).__init__(parent)

    def focusInEvent(self, e):
        self.selectAll()


lineedit = MyLineEdit()

QTimer solution as seen on QtCentre:

import types
from PyQt4 import QtCore

def bind(func, to):
    "Bind function to instance, unbind if needed"
    return types.MethodType(func.__func__ if hasattr(func, "__self__") else func, to)

...
self.txtSrc.focusInEvent = bind(lambda w, e: QtCore.QTimer.singleShot(0, w.selectAll), self.txtSrc)

Also the provided solution doesn't require to subclass QLineEdit.

These answers don't really provide the sort of standard ergonomics you'd probably want (and users might expect). For example, if you single-click once on a QLE which is not currently all-selected, and then single-click again, typically you'd want the first click to select-all, and the second click to allow you to place the cursor in the specific spot you have chosen.

This can be achieved simply by doing this:

def mousePressEvent(self, event):
    already_select_all = self.text() == self.selectedText()
    super().mousePressEvent(event)
    if not already_select_all:
        self.selectAll()

The question in fact asks about gaining focus, not specifically by mouse-clicking, and indeed, if you are a keyboardist or generally musophobic you'll probably also want the whole text to be selected any time the QLE gains focus, e.g. by tabbing or by use of a QLabel "buddy" mnemonic. This seems to do the job:

class MyLineEdit(QtWidgets.QLineEdit):
    def __init__(self, *args):
        super().__init__(*args)
        self.focus_in_reason = None
        
    def focusInEvent(self, event):
        super().focusInEvent(event)
        self.selectAll()
        self.focus_in_reason = event.reason()
    
    def mousePressEvent(self, event):
        super().mousePressEvent(event)
        if self.focus_in_reason == QtCore.Qt.MouseFocusReason:
            self.selectAll()
            self.focus_in_reason = None
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top