Уведомления

Группа в Telegram: @pythonsu

#1 Апрель 28, 2024 05:34:40

Devik
Зарегистрирован: 2024-04-24
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация функции

Может кто-то помочь с оптимизацией функции 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)

Офлайн

#2 Апрель 28, 2024 11:30:09

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2710
Репутация: +  182  -
Профиль   Отправить e-mail  

Оптимизация функции

> Может кто-то помочь с оптимизацией функции capacity?

Можешь в двух словах описать то что эта функция должна делать?



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Апрель 28, 2024 18:06:14

Devik
Зарегистрирован: 2024-04-24
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация функции

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

Отредактировано Devik (Апрель 28, 2024 18:09:37)

Офлайн

#4 Апрель 28, 2024 19:01:39

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2710
Репутация: +  182  -
Профиль   Отправить e-mail  

Оптимизация функции

> т.е нужно переходить на новую строку, если текст не умещается.

QTextEdit сам должен переносить текст если он не умещается.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#5 Апрель 28, 2024 19:23:22

Devik
Зарегистрирован: 2024-04-24
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация функции

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

Отредактировано Devik (Апрель 28, 2024 19:30:10)

Офлайн

#6 Апрель 29, 2024 13:46:38

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2710
Репутация: +  182  -
Профиль   Отправить e-mail  

Оптимизация функции

> проблема автопереноса в том, что она выравнивает весь текст, а мне нужно только 4 строчки

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

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

Можешь скриншот показать?



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#7 Апрель 29, 2024 18:05:28

Devik
Зарегистрирован: 2024-04-24
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация функции

Rodegast
Можешь скриншот показать?
Это я ошибся, на самом деле не так работает

Офлайн

#8 Апрель 29, 2024 23:05:49

Devik
Зарегистрирован: 2024-04-24
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация функции

Вообщем намудрил я тут. Но мне нужно чтобы показывалось только 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)

Офлайн

#9 Апрель 30, 2024 15:33:32

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2710
Репутация: +  182  -
Профиль   Отправить e-mail  

Оптимизация функции

> Но мне нужно чтобы показывалось только 4 строки.

Для начала установи моноширинный шрифт, затем вычисли количество символов в строке, умножь его на 4 и срезом получай блок текста и устанавливай его в виджет. Это должно вполне эффективно работать.



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#10 Апрель 30, 2024 19:28:54

Devik
Зарегистрирован: 2024-04-24
Сообщения: 15
Репутация: +  0  -
Профиль   Отправить e-mail  

Оптимизация функции

Rodegast
> Но мне нужно чтобы показывалось только 4 строки.Для начала установи моноширинный шрифт, затем вычисли количество символов в строке, умножь его на 4 и срезом получай блок текста и устанавливай его в виджет. Это должно вполне эффективно работать.
У меня и так моноширинный шрифт. Это вполне может работать, но как мне определить, где заканчивается абзац? И мне кажется будут лаги, если менять размер окна.

Отредактировано Devik (Апрель 30, 2024 19:43:06)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version