QPlainTextEdit 一行有多种颜色

QPlainTextEdit with multiple colours on a line

tl;博士:

QPlainTextEdit::appendPlainText(QString) 将换行符附加到我的文本小部件。 QPlainTextEdit::insertPlainText(QString) 似乎不受 setCurrentCharFormat().

的影响

有没有办法在不插入换行符的情况下在收听当前 QTextCharFormat 的同时追加文本

详情

我有一个“终端”样式的小部件,它从子进程的标准输出中获取文本并将其显示在 QPlainTextEdit

在我有颜色内容之前,我可以简单地这样做:

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

文本中使用转义符 '3' 后跟颜色来显示颜色。我可以检测颜色并适当地设置调色板:

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('3');

        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() 但这似乎没有什么不同。

对于这些情况,最简单的方法是使用 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('3'), 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("3redDateTime: %1 3blueDate:%2 3greenTime:%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"