简体   繁体   English

可编辑的多色QLineEdit

[英]Editable multi-color QLineEdit

I know that you can change the color of a line edit, so long as all the text is the same color, but is it possible to assign different colors to characters? 我知道您可以更改行编辑的颜色,只要所有文本都是相同的颜色,但是可以为字符分配不同的颜色吗? That is, some characters are red, and some are black, or simply every character has a different color. 也就是说,有些字符是红色的,有些是黑色的,或者只是每个字符都有不同的颜色。

There is a similar question here - How can I change color of part of the text in QLineEdit? 这里有一个类似的问题 - 如何在QLineEdit中更改部分文本的颜色? , but in my case there is an additional constraint - the QLineEdit must preserve color positions when edited, while new text that is entered assumes some default color. ,但在我的情况下还有一个额外的约束 - QLineEdit必须在编辑时保留颜色位置,而输入的新文本假定某些默认颜色。 The other question does not have that constraint. 另一个问题没有那个限制。

It does have an answer that is somewhat useful, however the colors are detached from the text - as you edit the line edit, whichever symbol that happens to be at a given position assumes that position's colors and formatting. 确实有一个有用的答案 ,但颜色与文本分离 - 当您编辑行编辑时,恰好在给定位置的符号假定该位置的颜色和格式。 That is, the formatting is not anchored to the text . 也就是说, 格式不会锚定到文本 Here are 2 screenshots to see what I'm talking about: 这是2个截图,看看我在说什么:

在此输入图像描述在此输入图像描述

I will be working on a solution to that shortcoming myself, and when I'm ready, I'll post the results as an answer. 我将自己解决这个缺点,当我准备好时,我会将结果作为答案发布。

I'll do that either by subscribing to the textEdited() signal, or by directly handling the input events. 我会通过订阅textEdited()信号或直接处理输入事件来做到这一点。 Each time the text is changed, I'll sync the color positions to it. 每次更改文本时,我都会将颜色位置同步到它。

In the meantime, if anyone know of a ridiculously easy solution that I've missed, or an easier approach to the problem, please feel free to share it. 与此同时,如果有人知道我错过了一个非常简单的解决方案,或者更容易解决问题,请随时分享。

I finally implemented it, by tracking the cursor position, the last selection start and length, and the last text size. 我最终通过跟踪光标位置,最后一个选择开始和长度以及最后一个文本大小来实现它。 When a textEdited() signal is emitted, I use them to figure out what text has been inserted and/or deleted, and then I replay the insertion and/or deletion in the color array in order to sync it to the text. 当发出textEdited()信号时,我使用它们来确定插入和/或删除了哪些文本,然后重放颜色数组中的插入和/或删除,以便将其同步到文本。

You can specify the color to be used for text inserted by the user. 您可以指定用于用户插入的文本的颜色。 If you don't specify it, the system default will be used, which will vary depending on the system theme. 如果未指定,将使用系统默认值,具体取决于系统主题。

The only problem is that it doesn't support Undo , because I have no idea how to distinguish if a textEdited() signal is caused by an Undo operation or not. 唯一的问题是它不支持Undo ,因为我不知道如何区分textEdited()信号是否是由Undo操作引起的。


ColorLineEdit.h 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 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);
}

Sample usage 样品用法

#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();
}

在此输入图像描述在此输入图像描述

:) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM