QPlainTextEdit с несколькими цветами на линии - PullRequest
0 голосов
/ 29 августа 2018

ТЛ; др:

QPlainTextEdit::appendPlainText(QString) добавляет новую строку в мой текстовый виджет. QPlainTextEdit::insertPlainText(QString) не похоже на setCurrentCharFormat().

Есть ли способ добавить текст при прослушивании текущей QTextCharFormat без вставки новой строки

Подробнее

У меня есть виджет в стиле терминала, который получает текст из stdout от дочернего процесса и отображает его в QPlainTextEdit.

До того, как я получил цветное содержимое, я мог бы просто сделать это:

void ProcessWidget::appendText(QString text)
{
    m_textedit->appendPlainText(text);
}

Цвета появляются в тексте с использованием escape-символа '\033', за которым следует цвет. Я могу определить цвет и правильно настроить палитру:

void ProcessWidget::appendText(QString text)
{
    Qt::GlobalColor colour = GetColour(text);

    QTextCharFormat tf = m_textedit->currentCharFormat();
    tf.setForeground(QBrush(colour));
    m_textedit->setCurrentCharFormat(tf);

    m_textedit->appendPlainText(text);
}

Это работает, если в каждой строке только один цвет, но если мой цвет меняется на полпути через каждую строку, то мне нужно быть немного сумасшедшим:

std::map<QString, Qt::GlobalColor>   m_colours;
QPlainTextEdit*                      m_textedit;
...

void ProcessWidget::AppendText(QString text)
{
    while(true)
    {
        int iColour = text.indexOf('\033');

        if (iColour == -1)
            break;

        QString pretext = text.mid(0, iColour);

        if (!pretext.isEmpty())
        {
            m_textedit->appendPlainText(pretext);
        }

        text.remove(0, iColour);

        for (auto pair : m_colours)
        {
            if ( text.startsWith(pair.first) )
            {
                QTextCharFormat tf = m_textedit->currentCharFormat();
                tf.setForeground(QBrush(pair.second));
                m_textedit->setCurrentCharFormat(tf);
                text.remove(0, pair.first.size());
                break;
            }
        }
    }

    if (!text.isEmpty())
    {
        m_textedit->appendPlainText(text);
    }
}

Однако, поскольку я использую appendPlainText(), каждый новый найденный цвет дает мне новую строку.

Я пытался заменить appendPlainText() на:

m_textedit->moveCursor (QTextCursor::End);
m_textedit->insertPlainText(text);
m_textedit->moveCursor (QTextCursor::End);

затем добавление '\n' в конце. Но в этом случае я больше не получаю цвета. Я также попробовал appendHtml(), но это, кажется, не имеет значения.

1 Ответ

0 голосов
/ 29 августа 2018

В этих случаях проще всего использовать HTML и вставить теги: <font color = "..."> </ font>

Пример:

#include <QApplication>
#include <QDateTime>
#include <QPlainTextEdit>
#include <QTimer>
#include <QVBoxLayout>
#include <QWidget>

const std::map<QString, QColor> m_colours {{"red", QColor(Qt::red)},
                                           {"blue", QColor(Qt::blue)},
                                           {"green", QColor(Qt::green)}
                                          };

class ProcessWidget: public QWidget{
    Q_OBJECT
public:
    ProcessWidget(QWidget *parent=nullptr):
        QWidget(parent),
        lay{this}
    {
        m_textedit.setReadOnly(true);
        lay.addWidget(&m_textedit);
    }
public slots:
    void appendText(const QString & text){
        QString html{text};
        int j = 0;
        bool start = true;
        QString textColor;

        while ((j = html.indexOf(QChar('\033'), j)) != -1) {
            html.remove(j, 1);
            QColor color;
            for(auto & pair : m_colours){
                if(html.mid(j).startsWith(pair.first)){
                    color = pair.second;
                    html.remove(j, pair.first.length());
                }
            }
            if(start){
                textColor = QString("<font color=\"%1\">").arg(color.name());
                start = false;
            }
            else
                textColor = QString("</font><font color=\"%1\">").arg(color.name());
            html.insert(j, textColor);
            j += 1+textColor.length();
        }
        html.append("</font>");
        m_textedit.appendHtml(html);
    }
private:
    QPlainTextEdit m_textedit;
    QVBoxLayout lay;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    ProcessWidget w;
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, [&w](){
        QString text = QString("\033redDateTime: %1 \033blueDate:%2 \033greenTime:%3")
                .arg(QDateTime::currentDateTime().toString())
                .arg(QDate().currentDate().toString())
                .arg(QTime::currentTime().toString());
        w.appendText(text);
    });
    timer.start(1000);
    w.show();
    return a.exec();
}

#include "main.moc"

enter image description here

...