Search code examples
pythonqt4pyqt4

Python/PyQT: How can I truncate a text in QLineEdit


I am looking for a solution for my problem. What did I do? I wrote a subclass named ExtendedTruncateTextLineEdit that inherits from QLineEdit. What I want? Well, I want to truncate a text in a Qwidget named QLineEdit, when you resize the window and the QLineEdit is getting smaller than content. The following code does work, but the QLineEdit-widget looks like a QLabel. What I have to do, that the following code draws also my QLineEdit?

import sys
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QApplication,\
                        QLineEdit,\
                        QLabel,\
                        QFontMetrics,\
                        QHBoxLayout,\
                        QVBoxLayout,\
                        QWidget,\
                        QIcon,\
                        QPushButton,\
                        QToolTip,\
                        QBrush,\
                        QColor,\
                        QFont,\
                        QPalette,\
                        QPainter

qt_app = QApplication(sys.argv)

class Example(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.setMinimumWidth(100)

        self.init_ui()


    def init_ui(self):
        v_layout = QVBoxLayout()
        v_layout.addStretch(1)

        lbl = ExtendedTruncateTextLabel("This is a really, long and poorly formatted runon sentence used to illustrate a point", self)
        #lbl.setText("This is a really, long and poorly formatted runon sentence used to illustrate a point")

        lbl_1 = ExtendedTruncateTextLabel(self)
        lbl_1.setText("Dies ist ein normaler Text")

        l_text = ExtendedTruncateTextLineEdit()
        l_text.setText("In the widget namend QLineEdit is also a very long text")


        v_layout.addWidget(lbl)
        v_layout.addWidget(lbl_1)
        v_layout.addWidget(l_text)

        self.setLayout(v_layout)

    def run(self):
        self.show()
        qt_app.exec_()

class ExtendedTruncateTextLineEdit(QLineEdit):   
    def __init(self, parent):
        QLineEdit.__init__(self, parent)

    def paintEvent(self, event):

        """ Handle the paint event for the title bar.

        This paint handler draws the title bar text and title buttons.

        """
        super(ExtendedTruncateTextLineEdit, self).paintEvent(event)
        painter = QPainter(self)

        metrics = QFontMetrics(self.font())
        elided  = metrics.elidedText(self.text(), Qt.ElideMiddle, self.width())

        painter.drawText(self.rect(), self.alignment(), elided)

if __name__ == '__main__':
    app = Example()
    app.run()

Solution

  • Here is a crude version of what you probably want. I cooked this up in around 10 mins so is very crude. Note that this in no way is any where near complete. It still has several things left to be done. In this case, the text is elided when the QLineEdit loses focus. The text has to be restored when it gains focus. That part is not yet implemented. or change of fonts will result in erroneous eliding, since QFontMentrics object will not get changed, etc, etc...

    class ElidingLineEdit( QLineEdit ) :
        """Eliding text lineedit
        """
    
        def __init__( self, text = QString(), parent = None ) :
            """Class initialiser
            """
    
            QLineEdit.__init__( self, parent )
            self.mText = text;
    
            self.fm = QFontMetrics( self.font() )
    
            self.textEdited[ QString ].connect( self.saveText )
            self.editingFinished.connect( self.shortenText )
    
        def setText( self, txt ) :
            """setText( QString ) -> None
    
            Override the QLineEdit::setText to display the shortened text
    
            @return None
            """
    
            QLineEdit.setText( self, self.fm.elidedText( self.mText, Qt.ElideRight, self.width() ) )
    
        def resizeEvent( self, rEvent ) :
            """resizeEvent( QResizeEvent ) -> None
    
            Override the resizeevent to shorten the text
    
            @return None
            """
    
            QLineEdit.setText( self, self.fm.elidedText( self.mText, Qt.ElideRight, rEvent.size().width() ) )
    
            rEvent.accept()
    
        def saveText( self, newText ) :
            """saveText() -> None
    
            Save the text as it is changing
    
            @return None
            """
    
            self.mText = newText
    
        def shortenText( self ) :
            """saveText() -> None
    
            Save the text as it is changing
    
            @return None
            """
    
            QLineEdit.setText( self, self.fm.elidedText( self.mText, Qt.ElideRight, self.width() ) )