Найти - Пользователи
Полная версия: Оптимизация функции
Начало » GUI » Оптимизация функции
1 2
Devik
Может кто-то помочь с оптимизацией функции 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())
Rodegast
> Может кто-то помочь с оптимизацией функции capacity?

Можешь в двух словах описать то что эта функция должна делать?
Devik
Rodegast
> Может кто-то помочь с оптимизацией функции capacity? Можешь в двух словах описать то что эта функция должна делать?
Она должна “подстраивать” текст под текущие размеры textedit_bg, т.е нужно переходить на новую строку, если текст не умещается. Ну и проблема в том, что при изменении размеров она, я каждый раз прохожусь по всему тексту, что вызывает лаги, если увеличить его количество.
Rodegast
> т.е нужно переходить на новую строку, если текст не умещается.

QTextEdit сам должен переносить текст если он не умещается.
Devik
Rodegast
QTextEdit сам должен переносить текст если он не умещается.
Это я знаю, нужно включить WordWrap, но мне нужно как-то получить первую строку, как это можно сделать?
Вообще программа должна работать так: пользователь нажимает кнопку, появляется текст, он должен его переписывать, после написания первой строки, первая строка фонового текста удаляется, если текст заканчивает и количество его строк становится меньше 4, добавляется новый текст.
Ну и проблема автопереноса в том, что она выравнивает весь текст, а мне нужно только 4 строчки. Т.е если текст который ниже 4 строк будет длиннее, в первых 4 могут быть длинные пробелы.
Rodegast
> проблема автопереноса в том, что она выравнивает весь текст, а мне нужно только 4 строчки

Пробовал задать выравнивание через setAlignment ?

> Т.е если текст который ниже 4 строк будет длиннее, в первых 4 могут быть длинные пробелы.

Можешь скриншот показать?
Devik
Rodegast
Можешь скриншот показать?
Это я ошибся, на самом деле не так работает
Devik
Вообщем намудрил я тут. Но мне нужно чтобы показывалось только 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())
Rodegast
> Но мне нужно чтобы показывалось только 4 строки.

Для начала установи моноширинный шрифт, затем вычисли количество символов в строке, умножь его на 4 и срезом получай блок текста и устанавливай его в виджет. Это должно вполне эффективно работать.
Devik
Rodegast
> Но мне нужно чтобы показывалось только 4 строки.Для начала установи моноширинный шрифт, затем вычисли количество символов в строке, умножь его на 4 и срезом получай блок текста и устанавливай его в виджет. Это должно вполне эффективно работать.
У меня и так моноширинный шрифт. Это вполне может работать, но как мне определить, где заканчивается абзац? И мне кажется будут лаги, если менять размер окна.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB