Pyside - Select all text when QLineEdit gets focus
Asked Answered
P

5

5

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_()
Prodigious answered 15/4, 2014 at 7:2 Comment(0)
U
9

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.

Unobtrusive answered 15/4, 2014 at 14:40 Comment(1)
Thanks. I used local variable and extended focusOut too to make sure that on second click text will be deselected and cursor will be positioned on the place clicked.Prodigious
P
3

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_()
Prodigious answered 16/4, 2014 at 7:14 Comment(2)
The self.deselect() call seems to be superfluous, but I'm using this inside a QGraphicsView so results may vary.Zygote
Indeed it seems unnecessary. Text is automatically deselected even without that line when out of focus.Prodigious
J
2

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()
Judicature answered 15/4, 2014 at 9:1 Comment(7)
There is a typo in method name. It must be 'focusInEvent'Masefield
Followed your suggestions. Still can't figure out What's wrong.Prodigious
Code is written fine on my side. What's the problem you're facing.Judicature
text is not being selected on focus.Prodigious
If I use other command, for example self.undo() in place of self.selectAll() it works. But for some reason, self.selectAll() is not working.Prodigious
__init__(self, parent=None): #self is required and colon is missing def focusInEvent(self, e): #self is required also this method doesn't work as explained by Danny. Anyways thanks for trying. your focusInEvent inspired my focusOutEvent.Prodigious
sorry for the mistakesJudicature
B
2

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.

Biopsy answered 14/4, 2016 at 7:40 Comment(0)
H
1

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
Howdah answered 12/5, 2022 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.