【问题标题】:Editable multi-color QLineEdit可编辑的多色 QLineEdit
【发布时间】:2014-07-24 20:30:40
【问题描述】:

我知道你可以改变一行编辑的颜色,只要所有的文本都是相同的颜色,但是可以为字符分配不同的颜色吗?也就是说,有些字符是红色的,有些是黑色的,或者只是每个字符都有不同的颜色。

这里有一个类似的问题 - How can I change color of part of the text in QLineEdit?,但在我的情况下还有一个额外的限制 - QLineEdit 在编辑时必须保留颜色位置,而输入的新文本采用一些默认颜色。另一个问题没有这个限制。

does have an answer 有点用处,但是颜色与文本分离 - 当您编辑行编辑时,恰好位于给定位置的任何符号都假定该位置的颜色和格式。也就是说,格式不锚定到文本。这里有两张截图,看看我在说什么:

我将自己解决这个缺点,当我准备好时,我会发布结果作为答案。

我将通过订阅textEdited() 信号或直接处理输入事件来做到这一点。每次更改文本时,我都会同步颜色位置。

与此同时,如果有人知道我错过了一个非常简单的解决方案,或者解决问题的更简单方法,请随时分享。

【问题讨论】:

标签: c++ qt qlineedit


【解决方案1】:

我最终实现了它,通过跟踪光标位置、最后选择的开始和长度以及最后的文本大小。当发出textEdited() 信号时,我使用它们来确定已插入和/或删除的文本,然后我在颜色数组中重放插入和/或删除以将其同步到文本。

您可以为用户插入的文本指定颜色。如果不指定,将使用系统默认值,具体取决于系统主题。

唯一的问题是它不支持Undo,因为我不知道如何区分textEdited()信号是否是由Undo操作引起的。


ColorLineEdit.h

#ifndef COLORLINEEDIT_H
#define COLORLINEEDIT_H

#include <QLineEdit>

class ColorLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit ColorLineEdit(QWidget *parent = 0);
    void setCharColors(const QList<QColor> &colors = QList<QColor>());
    void setColorForInsertedText(const QColor &colorForInsertedText) { this->colorForInsertedText = colorForInsertedText; }

signals:

private slots:
    void onSelectionChanged();
    void onTextEdited(const QString &text);

private:
    int lastTextSize;
    QList<QColor> colors;
    QColor colorForInsertedText;
    int lastSelectedTextSize;
    int lastSelectionStart;
};

#endif // COLORLINEEDIT_H

ColorLineEdit.cpp

#include "colorlineedit.h"
#include <QTextLayout>

ColorLineEdit::ColorLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
    connect(this, SIGNAL(selectionChanged()), SLOT(onSelectionChanged()));
    connect(this, SIGNAL(textEdited(QString)), SLOT(onTextEdited(QString)));
    lastSelectedTextSize = 0;
    lastSelectionStart = -1;
    lastTextSize = 0;
}

void ColorLineEdit::setCharColors(const QList<QColor> &colors)
{
    // See http://stackoverflow.com/questions/14417333/how-can-i-change-color-of-part-of-the-text-in-qlineedit.
    QList<QInputMethodEvent::Attribute> attributes;
    int size = colors.size();
    attributes.reserve(size);
    for (int ii = 0; ii < size ; ii++) {
        if (colors[ii].isValid()) {
            QTextCharFormat charFormat;
            charFormat.setForeground(QBrush(colors[ii]));
            const int start = ii - cursorPosition();
            const int length = 1;
            attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, start, length, charFormat));
        }
    }

    QLineEdit::inputMethodEvent(&QInputMethodEvent(QString(), attributes));

    lastTextSize = text().size();
    this->colors = colors;
}

void ColorLineEdit::onSelectionChanged()
{
    lastSelectionStart = selectionStart();
    lastSelectedTextSize = selectedText().size();
}

void ColorLineEdit::onTextEdited(const QString &text)
{
    if (!lastSelectedTextSize) {
        // We don't have a selection, so it's either
        // an insertion or deletion, but not both.
        int delta = text.size() - lastTextSize;
        if (delta > 0) {
            // User has inserted text.
            int pos = cursorPosition() - delta;
            for (int ii = 0; ii < delta; ii++) {
                colors.insert(pos, colorForInsertedText);
            }
        } else {
            // User has erased text.
            int pos = cursorPosition();
            colors.erase(colors.begin() + pos, colors.begin() + pos - delta);
        }
    } else {
        // There was a selection, so we have both removed
        // and inserted text.
        int pos = lastSelectionStart;
        int removedCount = lastSelectedTextSize;
        int insertedCount = cursorPosition() - pos;
        colors.erase(colors.begin() + pos, colors.begin() + pos + removedCount);
        for (int ii = 0; ii < insertedCount; ii++) {
            colors.insert(pos, colorForInsertedText);
        }
    }

    setCharColors(colors);
}

使用示例

#include "colorlineedit.h"
#include <QApplication>

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

    ColorLineEdit lineEdit;
    QList<QColor> colors;
    colors.append(Qt::red);
    colors.append(Qt::red);
    colors.append(Qt::red);
    colors.append(Qt::red);
    lineEdit.setText("abcd");
    lineEdit.setColorForInsertedText(Qt::blue);
    lineEdit.setCharColors(colors);
    lineEdit.show();

    return a.exec();
}

:)

【讨论】:

  • 为什么要包含 QTextLayout?
  • 不知道,距离我发布它已经 5-6 个月了,坦率地说我不太记得了。
  • 啊,SO的祸根:人们很少评论他们在这里发布的代码sn-ps! :)
  • @Olumide 四年后,答案出来了! QTextCharFormat 类通常不是QLineEdit 的一部分。如您所料,它应该包含在#include &lt;QTextCharFormat&gt; 中,但我想QTextLayout 标头是其中之一,也恰好包含它。
猜你喜欢
  • 1970-01-01
  • 2023-04-06
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多