一行上有多种颜色的QPlainTextEdit

时间:2018-08-29 09:32:32

标签: c++ qt qt5 qplaintextedit

tl; dr:

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

有没有一种方法可以在收听当前QTextCharFormat时附加文本而无需插入换行符

详细信息

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

在我拥有颜色内容之前,我可以简单地执行以下操作:

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

颜色在文本中使用转义字符'\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 :(得分:1)

在这些情况下,最简单的方法是使用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