Форум сайта python.su
Может кто-то помочь с оптимизацией функции capacity?
Если увеличить количество текста в списке texts, и изменять размер окна, начинаются лаги.
from sys import argv, exit from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * from random import shuffle texts = ['Contented you dearest pleased happiness afraid use. Bachelor entirely vanity alone out travelling terms ' 'along. Otherwise open prepared prosperous weddings tastes. Cousin engage knew confined distrusts. Fifteen ' 'around adapted doubtful opinions ten boy introduced merits late those admire.', 'Attacks diminution if prosperous stand insensible too innate. Collected rapid share. Goodness concluded yet ' 'inhabiting lovers. Principles minutes disposing abode arranging. Answered result steepest promise ' 'remaining. '] class CustomSyntaxHighlighter(QSyntaxHighlighter): def __init__(self, document=None, parent=None): super().__init__(document) self.parent = parent self.index = [] self.format_letter = QTextCharFormat() self.format_letter.setForeground(QColor('red')) self.format_space = QTextCharFormat() self.format_space.setBackground(QColor('red')) def highlightBlock(self, text): text_bg = self.parent.textedit_bg.toPlainText().split('\n')[0] text_no_mistakes = '\n'.join(self.parent.practice_text[0:4]) text_entered = '' if len(text) <= len(text_bg): for i, t in enumerate(text_no_mistakes[:len(text)].strip('¶')): if t != text[i]: text_entered += text[i] self.setFormat(i, 1, self.format_space if text[i] == ' ' else self.format_letter) continue text_entered += t self.parent.textedit_bg.setText(text_entered + text_no_mistakes[len(text):]) class Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.setWindowTitle('TextEdit') self.setMinimumSize(820, 0) self.centralwidget = QWidget(self) self.centralwidget.setObjectName(u"centralwidget") self.setCentralWidget(self.centralwidget) self.layout = QGridLayout(self.centralwidget) self.layout.setObjectName(u"layout") self.textedit_bg = QTextEdit(self) self.textedit_bg.setObjectName(u"textedit_bg") self.textedit_bg.setStyleSheet(''' #textedit_bg { background-color: #FF7F50; color: #FFFF00; font: 16pt "Cascadia Mono ExtraLight"; } ''') self.textedit_bg.setWordWrapMode(QTextOption.NoWrap) self.textedit = QTextEdit(self) # !!! lineedit self.textedit.setObjectName(u"textedit") self.textedit.setStyleSheet(''' #textedit { background-color: transparent; color: #0000CD; font: 16pt "Cascadia Mono ExtraLight"; } ''') self.textedit.setWordWrapMode(QTextOption.NoWrap) self.textedit.cursorPositionChanged.connect(self._change_cursor) self.textedit.selectionChanged.connect(self._change_selection) self.layout.addWidget(self.textedit_bg, 1, 1) self.layout.addWidget(self.textedit, 1, 1) self.button = QPushButton('Create Text', self) self.layout.addWidget(self.button, 2, 1) self.textedit_bg.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit_bg.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit_bg.setFixedHeight(132) self.textedit.setFixedHeight(132) self.textedit.setFocus() self.practice_text = '' self.text_width = 800 self.highlighter = CustomSyntaxHighlighter(self.textedit.document(), self) self.button.clicked.connect(lambda: self.get_text(True)) self.textedit.textChanged.connect(self.result) def result(self): text = self.textedit.toPlainText() text_bg = self.textedit_bg.toPlainText().split('\n')[0] if len(text) > len(text_bg.strip('¶')): if ('¶' in self.practice_text[0] and text[-1] != '\n' or text[-1] != ' ' and '¶' not in self.practice_text[0]): self.textedit.textCursor().deletePreviousChar() return del self.practice_text[0] self.get_text() return if text and len(text) != len(text_bg) and text[-1] in ('\n', '\t'): self.textedit.textCursor().deletePreviousChar() return def get_text(self, dev=False, resize=False): if dev and self.practice_text: del self.practice_text[0] if not self.practice_text: shuffle(texts) self.practice_text = self.capacity(texts) if resize and self.practice_text: self.practice_text = self.capacity(' '.join(self.practice_text).split('¶')[:-1]) if len(self.practice_text) <= 3: shuffle(texts) self.practice_text += self.capacity(texts) self.textedit_bg.setText('\n'.join(self.practice_text)) self.textedit.clear() self.textedit.setFocus() def capacity(self, text): result = [] for item in text: line = '' for w in item.split(): if self.text_width < self.__get_pixels_wide(line + w): result.append(line.strip()) line = '' line += w + ' ' result.append(line.strip() + '¶') return result def resizeEvent(self, event): if self.isVisible(): self.text_width = self.textedit.width() - 20 self.get_text(resize=True) def _change_cursor(self): cursor = self.textedit.textCursor() if cursor.positionInBlock() < len(self.textedit.document().toPlainText()): cursor.movePosition(QTextCursor.End) self.textedit.setTextCursor(cursor) def _change_selection(self): cursor = self.textedit.textCursor() cursor.clearSelection() self.textedit.setTextCursor(cursor) def __get_pixels_wide(self, words): return self.textedit_bg.fontMetrics().boundingRect(words).width() if __name__ == "__main__": app = QApplication(argv) window = Window() window.show() exit(app.exec())
Отредактировано Devik (Апрель 28, 2024 18:12:54)
Офлайн
> Может кто-то помочь с оптимизацией функции capacity?
Можешь в двух словах описать то что эта функция должна делать?
Офлайн
RodegastОна должна “подстраивать” текст под текущие размеры textedit_bg, т.е нужно переходить на новую строку, если текст не умещается. Ну и проблема в том, что при изменении размеров она, я каждый раз прохожусь по всему тексту, что вызывает лаги, если увеличить его количество.
> Может кто-то помочь с оптимизацией функции capacity? Можешь в двух словах описать то что эта функция должна делать?
Отредактировано Devik (Апрель 28, 2024 18:09:37)
Офлайн
> т.е нужно переходить на новую строку, если текст не умещается.
QTextEdit сам должен переносить текст если он не умещается.
Офлайн
RodegastЭто я знаю, нужно включить WordWrap, но мне нужно как-то получить первую строку, как это можно сделать?
QTextEdit сам должен переносить текст если он не умещается.
Отредактировано Devik (Апрель 28, 2024 19:30:10)
Офлайн
> проблема автопереноса в том, что она выравнивает весь текст, а мне нужно только 4 строчки
Пробовал задать выравнивание через setAlignment ?
> Т.е если текст который ниже 4 строк будет длиннее, в первых 4 могут быть длинные пробелы.
Можешь скриншот показать?
Офлайн
RodegastЭто я ошибся, на самом деле не так работает
Можешь скриншот показать?
Офлайн
Вообщем намудрил я тут. Но мне нужно чтобы показывалось только 4 строки. А если расширять окна текст должен добавляться. Ну или можно уменьшить высоту окна, но нужно тогда расширить расстояние между строк, т.к например, букву й будет видно, если она ниже 4 строки.
from sys import argv, exit from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * from random import shuffle from text.texts import practice_eng texts = ['Neat believed cordial fine jennings wrong luckily longer increasing attacks. Such continue whether ' 'musical almost. Game promotion attempted help mrs manor lady rose woman. Way income overcame ' 'happiness on song cordial understood provision. Conveying dull music meant general within.'] def split_by_lines(doc: QTextDocument): ret = [] tb: QTextBlock = doc.begin() while tb.isValid(): blockText = tb.text() for i in range(tb.layout().lineCount()): line: QTextLine = tb.layout().lineAt(i) ret.append(blockText[line.textStart():line.textStart() + line.textLength()].strip('¶')) ret.append('¶\n') tb = tb.next() return ret[:-2] class CustomSyntaxHighlighter(QSyntaxHighlighter): def __init__(self, document=None, parent=None): super().__init__(document) self.parent = parent self.format_letter = QTextCharFormat() self.format_letter.setForeground(QColor('red')) self.format_space = QTextCharFormat() self.format_space.setBackground(QColor('red')) def highlightBlock(self, text): text_bg = self.parent.practice_text[0] text_no_mistakes = ''.join(self.parent.practice_text[0:5]) text_entered = '' if text and len(text) <= len(text_bg): for i, t in enumerate(text_no_mistakes[:len(text)]): if t != text[i]: text_entered += text[i] self.setFormat(i, 1, self.format_space if text[i] == ' ' else self.format_letter) continue text_entered += t self.parent.textedit_bg.setText(text_entered + text_no_mistakes[len(text):]) else: self.parent.textedit_bg.setText(text_no_mistakes) class Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.setWindowTitle('TextEdit') self.setMinimumSize(820, 0) self.centralwidget = QWidget(self) self.centralwidget.setObjectName(u"centralwidget") self.setCentralWidget(self.centralwidget) self.layout = QGridLayout(self.centralwidget) self.layout.setObjectName(u"layout") self.textedit_bg = QTextEdit(self) self.textedit_bg.setObjectName(u"textedit_bg") self.textedit_bg.setStyleSheet(''' #textedit_bg { background-color: #FF7F50; color: #FFFF00; font: 16pt "Cascadia Mono ExtraLight"; } ''') self.textedit_bg.setWordWrapMode(QTextOption.WordWrap) self.textedit = QTextEdit(self) # !!! lineedit self.textedit.setObjectName(u"textedit") self.textedit.setStyleSheet(''' #textedit { background-color: transparent; color: #0000CD; font: 16pt "Cascadia Mono ExtraLight"; } ''') self.textedit.setWordWrapMode(QTextOption.NoWrap) self.textedit.cursorPositionChanged.connect(self._change_cursor) self.textedit.selectionChanged.connect(self._change_selection) self.layout.addWidget(self.textedit_bg, 1, 1) self.layout.addWidget(self.textedit, 1, 1) self.button = QPushButton('Create Text', self) self.layout.addWidget(self.button, 2, 1) self.textedit_bg.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit_bg.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.textedit_bg.setFixedHeight(250) self.textedit.setFixedHeight(250) self.textedit.setFocus() self.practice_text = '' self.text_width = 0 self.highlighter = CustomSyntaxHighlighter(self.textedit.document(), self) self.button.clicked.connect(lambda: self.get_text(True)) self.textedit.textChanged.connect(self.result) def result(self): text = self.textedit.toPlainText() text_bg = self.practice_text[0].strip() if len(text) > len(text_bg.strip('¶')): if ('¶\n' in self.practice_text[0:2] and text[-1] != '\n' or text[-1] != ' ' and '¶\n' not in self.practice_text[0:2]): self.textedit.textCursor().deletePreviousChar() return self.get_text(True) self.textedit.clear() return if text and len(text) != len(text_bg) and text[-1] in ('\n', '\t'): self.textedit.textCursor().deletePreviousChar() return def resizeEvent(self, event): if self.isVisible(): self.get_text(resize=True) def get_text(self, dev=False, resize=False): if dev and self.practice_text: if '¶\n' in ''.join(self.practice_text[0:2]): del self.practice_text[0:2] else: del self.practice_text[0] self.textedit_bg.setText(''.join(self.practice_text[0:5])) if not self.practice_text: shuffle(texts) self.textedit_bg.setText(''.join(i + '¶\n' for i in texts)) self.practice_text = split_by_lines(self.textedit_bg.document()) if resize and self.practice_text: self.practice_text = split_by_lines(self.textedit_bg.document()) print(self.practice_text[0:4]) if len(self.practice_text) <= 5: shuffle(texts) text = ''.join(self.practice_text) + ''.join(i + '¶\n' for i in texts) self.textedit_bg.setText(text) def _change_cursor(self): cursor = self.textedit.textCursor() if cursor.positionInBlock() < len(self.textedit.document().toPlainText()): cursor.movePosition(QTextCursor.End) self.textedit.setTextCursor(cursor) def _change_selection(self): cursor = self.textedit.textCursor() cursor.clearSelection() self.textedit.setTextCursor(cursor) def __get_pixels_wide(self, words): return self.textedit_bg.fontMetrics().boundingRect(words).width() if __name__ == "__main__": app = QApplication(argv) window = Window() window.show() exit(app.exec())
Отредактировано Devik (Апрель 29, 2024 23:12:16)
Офлайн
> Но мне нужно чтобы показывалось только 4 строки.
Для начала установи моноширинный шрифт, затем вычисли количество символов в строке, умножь его на 4 и срезом получай блок текста и устанавливай его в виджет. Это должно вполне эффективно работать.
Офлайн
RodegastУ меня и так моноширинный шрифт. Это вполне может работать, но как мне определить, где заканчивается абзац? И мне кажется будут лаги, если менять размер окна.
> Но мне нужно чтобы показывалось только 4 строки.Для начала установи моноширинный шрифт, затем вычисли количество символов в строке, умножь его на 4 и срезом получай блок текста и устанавливай его в виджет. Это должно вполне эффективно работать.
Отредактировано Devik (Апрель 30, 2024 19:43:06)
Офлайн