Как в QTextEdit изменять фон текста в разные цвета до конца строки?
Нужно вывести текст в графический интерфейс, обработать и изменить фон текста в разные цвета до конца строки.
Проблема возникла с последним. Простой "span background-color
" не доводит закраску до конца строки, а только до конца текста. "p
" и "div
" красит как нужно, но абсолютно все строки.
Благодарен за помощь.
import sys
import threading
from PyQt6.QtWidgets import QApplication,QMainWindow, QTextEdit
from PyQt6.QtCore import pyqtSignal
class MainWindow(QMainWindow):
# Создаем сигнал для обновления консольного окна
update_display = pyqtSignal(str)
def __init__(self):
super().__init__()
self.setup_ui()
def setup_ui(self):
self.setGeometry(700, 300, 200, 200)
self.output_display = QTextEdit(self)
self.output_display.setGeometry(10, 10, 180, 180)
# Подключаем сигнал к слоту для обновления окна вывода текста
self.update_display.connect(self.update_output_display)
def add_background_color(self, text, color):
#colored_text = f"<p style='background-color: {color};'>{text}</p>"
colored_text = f"<span style='background-color: {color};'>{text}</span>"
return colored_text
def update_output_display(self, text):
if "example" in text:
html_text = self.add_background_color(text, "green")
elif "primer" in text:
html_text = self.add_background_color(text, "blue")
else:
html_text = text
self.output_display.append(html_text)
def process_output_handler(window):
# для примера
window.update_display.emit("example")
window.update_display.emit("primer")
window.update_display.emit("example")
window.update_display.emit("primer")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
thread = threading.Thread(target=process_output_handler, args=(window,), daemon=True).start()
sys.exit(app.exec())
У меня сейчас получается как во втором примере, то есть цвет фона распространяется только за текстом. А мне нужно как в первом случае, чтобы цветовая полоска продолжалась дальше, до конца окна.
Ответы (2 шт):
Вам наверное нужно что то наподобии?
<style>
.red-text { color: #FF0000; }
.blue-text { color: #0000A0; }
</style>
<p>
Обычный текст <span class="red-text">красное слово</span> обычный текст <span> class="blue-text">синее слово</span>.
</p>
Ваша задача может выглядеть примерно так, см. ниже.
Обратите внимание, что я заменил виджет QTextEdit
на QListWidget
.
Вам не нужен модуль threading, в PyQt есть класс QThread
Попробуйте:
import sys
from random import choice
from PyQt5.Qt import *
class ListWidget(QListWidget):
def resizeEvent(self, event: QResizeEvent) -> None:
super().resizeEvent(event)
row = 0
while row < self.count():
lwi_item = self.item(row)
item_widget = self.itemWidget(lwi_item)
if not (item_widget is None) and (item_widget.wordWrap()):
width_int = self.width() \
- self.contentsMargins().left() \
- self.contentsMargins().right()
fm = self.fontMetrics()
text_str = item_widget.text()
max_rect = QRect(0, 0, width_int, 1000)
br = fm.boundingRect(max_rect, Qt.TextWordWrap, text_str)
font_br_size = br.size()
heigth_int = font_br_size.height()
total_height_int = heigth_int \
+ item_widget.contentsMargins().top() \
+ item_widget.contentsMargins().bottom()
widget_size_hint = QSize(width_int, total_height_int)
lwi_item.setSizeHint(widget_size_hint) # <---
row += 1
class Thread(QThread):
update_display = pyqtSignal(str)
def __init__(self):
super().__init__()
self.flag_run = True
self._list = [
'Этот текст содержит "example"',
'primer',
'У меня сейчас получается как во втором primerе, то есть цвет фона распространяется только за текстом.',
' А мне нужно как в первом случае, чтобы цветовая полоска продолжалась дальше, до конца окна.',
'example',
'Просто текст.',
'покрасить фон текста в разные цвета до конца строки'
]
def run(self):
while self.flag_run:
text = choice(self._list)
self.update_display.emit(text)
self.msleep(2000)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.list_widget = ListWidget()
self.list_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.list_widget.setResizeMode(QListView.Adjust)
self.list_widget.setUniformItemSizes(False)
self.list_widget.setWordWrap(True)
self.pushButton = QPushButton("Start Thread")
self.pushButton.clicked.connect(self.button_clicked)
self.pushButton.setCheckable(True)
self.layout = QGridLayout(self.centralWidget)
self.layout.addWidget(self.list_widget)
self.layout.addWidget(self.pushButton)
self.thread = Thread()
self.thread.update_display.connect(self.add_background_color)
def button_clicked(self, status):
if status:
self.pushButton.setText("Stop Thread")
self.thread.flag_run = True
self.thread.start()
else:
self.thread.flag_run = False
self.pushButton.setText("Start Thread")
def add_background_color(self, text):
item = QListWidgetItem(self.list_widget)
self.list_widget.addItem(item)
item_qlabel = QLabel(text)
item_qlabel.setSizePolicy(QSizePolicy.Expanding,
QSizePolicy.Expanding)
item_qlabel.setWordWrap(True)
if "example" in text:
bg_color = "#238b45"
elif "primer" in text:
bg_color = "#1d91c0"
else:
bg_color = "#edf8fb"
item_qlabel.setStyleSheet(
f"*{{background-color: {bg_color}; border: 1px solid #d90909;;}}")
item.setSizeHint(item_qlabel.sizeHint())
self.list_widget.setItemWidget(item, item_qlabel)
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setFont(QFont("Times", 12, QFont.Bold))
w = MainWindow()
w.resize(500, 400)
w.show()
sys.exit(app.exec())