How to set the PlaceHolderText for QTextEdit
Asked Answered
E

4

7

I want to set placeholder text of a QTextEdit. I know how to set it for a QLineEdit, there is a property setPlaceHolderText. But this property is not available for QTextEdit. Please give your valuable suggestions to solve this.

Enactment answered 12/11, 2012 at 17:7 Comment(1)
Unlike forum sites, we don't use "Thanks", or "Any help appreciated", or signatures on Stack Overflow. See "Should 'Hi', 'thanks,' taglines, and salutations be removed from posts?.Trilateration
R
3

Use setTextCursor(QTextCursor&) function of QTextEdit. Use the following logic.

  QTextCursor textCursor;
  textCursor.setPosistion(0, QTextCursor::MoveAnchor); 
  textedit->setTextCursor( textCursor );
Reichsmark answered 11/12, 2012 at 17:2 Comment(1)
How do you this actually?Iquique
D
3

Since Qt 5.3, The property was added, so you now simply need to call setPlaceholderText

Diaphony answered 21/12, 2017 at 13:26 Comment(0)
I
3

I found the answer by Rafe to be a little lacking as it was unable to correctly format the text. From jpo38's answer though, I found the source code of it in Qt5 and re-implemented what I could in Python.

It's got one or two changes, but overall seems to work nicely, it puts the text in the correct place and supports using \n for new lines.

Note: This is tested in PySide with Qt.py, if not using that file, you will need to remap QtWidgets back to QtGui.

class QPlainTextEdit(QtWidgets.QPlainTextEdit):
    """QPlainTextEdit with placeholder text option.
    Reimplemented from the C++ code used in Qt5.
    """
    def __init__(self, *args, **kwargs):
        super(QPlainTextEdit, self).__init__(*args, **kwargs)

        self._placeholderText = ''
        self._placeholderVisible = False
        self.textChanged.connect(self.placeholderVisible)

    def placeholderVisible(self):
        """Return if the placeholder text is visible, and force update if required."""
        placeholderCurrentlyVisible = self._placeholderVisible
        self._placeholderVisible = self._placeholderText and self.document().isEmpty() and not self.hasFocus()
        if self._placeholderVisible != placeholderCurrentlyVisible:
            self.viewport().update()
        return self._placeholderVisible

    def placeholderText(self):
        """Return text used as a placeholder."""
        return self._placeholderText

    def setPlaceholderText(self, text):
        """Set text to use as a placeholder."""
        self._placeholderText = text
        if self.document().isEmpty():
            self.viewport().update()

    def paintEvent(self, event):
        """Override the paint event to add the placeholder text."""
        if self.placeholderVisible():
            painter = QtGui.QPainter(self.viewport())
            colour = self.palette().text().color()
            colour.setAlpha(128)
            painter.setPen(colour)
            painter.setClipRect(self.rect())
            margin = self.document().documentMargin()
            textRect = self.viewport().rect().adjusted(margin, margin, 0, 0)
            painter.drawText(textRect, QtCore.Qt.AlignTop | QtCore.Qt.TextWordWrap, self.placeholderText())
        super(QPlainTextEdit, self).paintEvent(event)

If you need the text to remain up until the point you start typing, just remove the not self.hasFocus() part.

Immaculate answered 6/2, 2019 at 12:25 Comment(2)
Found this kind of funny - I needed to do this again as I forgot where I put my code last time. I came across the answer by Rafe, but it didn't work too well so I scrolled down and saw this, and was really happy someone had taken the time to improve it. I tried to upvote and found out it was my own answer.Immaculate
Coding works in mysterious ways. We can be glad to have a site like this! You made my day. :DWindhover
S
2

I was able to do this by subclassing and overriding the paint event:

class PlainTextEditWithPlaceholderText(QtGui.QPlainTextEdit):
    def __init__(self, parent=None):
        super(PlainTextEditWithPlaceholderText, self).__init__(parent)
        self.placeholderText = ""  # Qt-style camelCase

    def setPlaceholderText(self, text):
        self.placeholderText = text

    def paintEvent(self, _event):
        """
        Implements the same behavior as QLineEdit's setPlaceholderText()
        Draw the placeholder text when there is no text entered and the widget 
        doesn't have focus.
        """
        if self.placeholderText and not self.hasFocus() and not self.toPlainText():
            painter = QtGui.QPainter(self.viewport())

            color = self.palette().text().color()
            color.setAlpha(128)
            painter.setPen(color)

            painter.drawText(self.geometry().topLeft(), self.placeholderText)

        else:
            super(PlainTextEditWithPlaceholderText, self).paintEvent(event)
Somebody answered 10/5, 2017 at 1:7 Comment(1)
I had to tack on a self.viewport().update() and reposition the text a bit, but otherwise works great! Thank you!Chuck

© 2022 - 2024 — McMap. All rights reserved.