PyQt4: QTextEdit начинается с n-й строки

У меня есть всплывающее окно, содержащее только QTextEdit, в нем много текста, много строк. Я хочу, чтобы он прокручивался до определенной строки в QTextEdit на show(). Так что линия, которую я хочу, находится наверху.

Фрагмент кода:

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

Как я могу этого добиться?

Обновлять

Мне удалось заставить его показать n-ю строку внизу:

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

Например, для n=25 я получаю:

_______________________
.
.
.
.
25th line
_______________________

Но мне нужно, чтобы он был наверху...


person Bob Sacamano    schedule 10.11.2016    source источник
comment
Вам нужно работать с вертикальной полосой прокрутки. Зная размер страницы и количество строк в текстовом редактировании, вы можете рассчитать, насколько вы можете прокрутить текстовое редактирование вверх. См. несколько связанных: stackoverflow.com/questions/4939151/   -  person Alexander V    schedule 10.11.2016


Ответы (1)


У тебя почти получилось. Хитрость заключается в том, чтобы переместить текущий курсор вниз сначала, а затем сбросить курсор на целевую строку. Затем представление будет автоматически прокручиваться, чтобы сделать курсор видимым:

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

Кроме того, чтобы поместить курсор внизу, сначала переместите текущий курсор в начало:

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

Вот демонстрационный скрипт:

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_())
person ekhumoro    schedule 10.11.2016
comment
Хорошее решение. Одно но: все это работает, конечно, только если осталось достаточно строк (общее количество строк m минус желаемая строка n должно быть равно или больше количества отображаемых строк в окне просмотра). Также может не потребоваться прокрутка вниз, просто прокрутите достаточно далеко вниз (например, прокрутите до строки n + x (количество отображаемых строк в окне просмотра)). - person Trilarion; 10.11.2016
comment
@Триларион. Я не думаю, что QTextEdit имеет возможность прокручивать дальше последней строки, как это делают некоторые элементы управления редактора (например, Scintilla), поэтому первый пункт кажется спорным. Я также не вижу заметного влияния на производительность при перемещении курсора сначала в конец (я тестировал файл с 300 тыс. строк). - person ekhumoro; 10.11.2016
comment
Это решение звучит хорошо, но оно не работает для меня. Строка с курсором отображается последней в QTextEdit. Есть ли дополнительные требования? (Я использую PyQt 4.8 на python 2.7) - person ImportanceOfBeingErnest; 11.11.2016
comment
@ImportanceOfBeingErnest. У меня он отлично работает, используя PyQt-4.7, PyQt-4.9.5 и PyQt-4.11.4 с Python-2.7. Вы уверены, что используете QTextCursor.End? - person ekhumoro; 11.11.2016
comment
@ekhumoro Я просто скопировал три строки сверху и поместил их в метод init класса. И именно в этом, похоже, проблема. Таким образом, приведенный выше код будет работать, но только после того, как виджет будет нарисован. Напротив, метод из вопроса (установка курсора на строку внизу TextEdit) также будет работать до рисования. - person ImportanceOfBeingErnest; 11.11.2016
comment
@ImportanceOfBeingErnest. Я добавил полностью рабочий демонстрационный скрипт. - person ekhumoro; 11.11.2016
comment
@ekhumoro Это прекрасно работает. У меня другая проблема с изменением размера QTextEdit, stackoverflow.com/questions/40136655/ Может быть, вы хотите взглянуть на него? - person ImportanceOfBeingErnest; 15.11.2016