Bob Sacamano
Bob Sacamano

Reputation: 439

PyQt4: QTextEdit start in nth line

I have a popup that only contains a QTextEdit, it has a lot of text in it, a lot of lines. I want it to scroll to a certain line in the QTextEdit on show(). So that the line I want is at the top.

Code snippet:

editor = QtGui.QTextEdit()
# fill the editor with text
# set the scroll to nth line
editor.show()

How can I achieve that?

Update

I've managed to get it to show the nth line at the bottom:

cursor = QtGui.QTextCursor(editor.document().findBlockByLineNumber(n))
editor.moveCursor(QtGui.QTextCursor.End)
editor.setTextCursor(cursor)

For example for n=25 I get:

_______________________
.
.
.
.
25th line
_______________________

But I need it to be at the top...

Upvotes: 4

Views: 2952

Answers (1)

ekhumoro
ekhumoro

Reputation: 120608

You almost have it. The trick is to move the current cursor to the bottom first, and then reset the cursor to the target line. The view will then automatically scroll to make the cursor visible:

editor.moveCursor(QtGui.QTextCursor.End)
cursor = QtGui.QTextCursor(editor.document().findBlockByLineNumber(n))
editor.setTextCursor(cursor)

By extension, to position the cursor at the bottom, move the current cursor to the start first:

editor.moveCursor(QtGui.QTextCursor.Start)
...

Here's a demo script:

from PyQt4 import QtCore, QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.edit = QtGui.QTextEdit(self)
        self.edit.setPlainText(
            '\n'.join('%04d - blah blah blah' % i for i in range(200)))
        self.button = QtGui.QPushButton('Go To Line', self)
        self.button.clicked.connect(self.handleButton)
        self.spin = QtGui.QSpinBox(self)
        self.spin.setRange(0, 199)
        self.spin.setValue(50)
        self.check = QtGui.QCheckBox('Scroll Top')
        self.check.setChecked(True)
        layout = QtGui.QGridLayout(self)
        layout.addWidget(self.edit, 0, 0, 1, 3)
        layout.addWidget(self.button, 1, 0)
        layout.addWidget(self.spin, 1, 1)
        layout.addWidget(self.check, 1, 2)
        QtCore.QTimer.singleShot(0, lambda: self.scrollToLine(50))

    def scrollToLine(self, line=0):
        if self.check.isChecked():
            self.edit.moveCursor(QtGui.QTextCursor.End)
        else:
            self.edit.moveCursor(QtGui.QTextCursor.Start)
        cursor = QtGui.QTextCursor(
            self.edit.document().findBlockByLineNumber(line))
        self.edit.setTextCursor(cursor)

    def handleButton(self):
        self.scrollToLine(self.spin.value())
        self.edit.setFocus()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 100, 400, 300)
    window.show()
    sys.exit(app.exec_())

Upvotes: 4

Related Questions