Qt 5.8 QTextEdit文本光标颜色不会改变

问题描述 投票:1回答:1

我试图将文本光标放在QTextEdit红色(rgb(255,0,0))上。尽管我付出了最大的努力,但它继续眨白了。

根据我的发现,样式表“颜色”属性应该改变光标的颜色。不确定是什么问题。

我的代码:

    textEntry = new QTextEdit();
    textEntry->setFont(QFont("Electrolize", 9, 1));
    textEntry->setMinimumHeight(25);
    textEntry->setMaximumHeight(25);
    textEntry->setLineWrapMode(QTextEdit::NoWrap);
    textEntry->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    textEntry->setStyleSheet("color: rgb(255, 0, 0);"
                             "border: 1px solid rgb(255, 0, 0);");

编辑:我鼓励全面阅读Scheff的回答。这很棒。我注意到用他的解决方案创建的光标没有闪烁,所以我想分享一个源自Scheff代码的闪烁版本和我的(没有经验的)添加。

TextEdit.h

#ifndef TEXTEDIT_H
#define TEXTEDIT_H

#include <QTextEdit>
#include <QTimer>

class TextEdit : public TextEdit
{
    Q_OBJECT
public:
    explicit TextEdit(QWidget *parent = nullptr);

private:
    QTimer *timer;
    QPainter *pPainter;
    bool bCursorVisible;

protected:
    virtual void paintEvent(QPaintEvent *pEvent) override;

signals:
    sendUpdate();

public slots:
    void timerSlot();
};

#endif // TEXTEDIT_H

TextEdit.cpp

#include "textedit.h"

#include <QPainter>
#include <QColor>
#include <QTimer>

TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent) {
    bCursorVisible = true;

    timer = new QTimer(this);
    timer->start(500);
    connect(this, SIGNAL(sendUpdate()), this, SLOT(update()));
    connect(timer, SIGNAL(timeout()), this, SLOT(timerSlot()));
}

void TextEdit::paintEvent(QPaintEvent *event)
{
  // use paintEvent() of base class to do the main work
  QTextEdit::paintEvent(event);
  // draw cursor (if widget has focus)
  if (hasFocus()) {
    if(bCursorVisible) {
        const QRect qRect = cursorRect(textCursor());
        QPainter qPainter(viewport());
        qPainter.fillRect(qRect, QColor(255, 0, 0, 255));
    } else {
        const QRect qRect = cursorRect(textCursor());
        QPainter qPainter(viewport());
        qPainter.fillRect(qRect, QColor(0, 0, 0, 255));
    }
  }
}

void TextEdit::timerSlot() {
    if(bCursorVisible) {
        bCursorVisible = false;
    } else {
        bCursorVisible = true;
    }

    emit sendUpdate();
}
qt colors caret qtextedit
1个回答
2
投票

之前有一些与OP的对话,因为我严重怀疑QTextEdit的颜色属性是否也是文本光标的颜色。

我在Qt Style Sheets Reference找到的所有内容:

用于渲染文本的颜色。

尊重QWidget :: palette的所有小部件都支持此属性。

如果未设置此属性,则默认值为QWidget :: foregroundRole(通常为黑色)的窗口小部件调色板中设置的内容。

出于好奇,我摆弄了QTextEdit的颜色。

  1. 我可以重现OP描述的内容: 更改QTextEdit的文本颜色(例如使用QTextEdit::setTextColor())会影响之后输入的插入文本,但它不会更改文本光标颜色(至少在我测试的平台上)。
  2. 在摆弄的同时,我意识到另一个鼓励我写这个答案的事实: 恕我直言,文本光标忽略任何颜色设置。相反,它会反转绘制的文本光标条下的像素。 看看QPainter::RasterOp_NotSource,看看我的意思。

我的示例应用程序testQTextEditCursorColor.cc

#include <QtWidgets>

class ColorButton: public QPushButton {
  private:
    QColor _qColor;

  public:
    explicit ColorButton(
      const QString &text, const QColor &qColor = Qt::black,
      QWidget *pQParent = nullptr):
      QPushButton(text, pQParent)
    {
      setColor(qColor);
    }
    virtual ~ColorButton() = default;
    ColorButton(const ColorButton&) = delete;
    ColorButton& operator=(const ColorButton&) = delete;

    const QColor& color() const { return _qColor; }
    void setColor(const QColor &qColor)
    {
      _qColor = qColor;
      QFontMetrics qFontMetrics(font());
      const int h = qFontMetrics.height();
      QPixmap qPixmap(h, h);
      qPixmap.fill(_qColor);
      setIcon(qPixmap);
    }

    QColor chooseColor()
    {
      setColor(QColorDialog::getColor(_qColor, this, text()));
      return _qColor;
    }
};

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  qDebug() << app.style();
  // setup GUI
  QMainWindow qWin;
  qWin.resize(250, 100);
  qWin.setWindowTitle("Test Set Cursor Color");
  QTextEdit qTextEdit;
  qWin.setCentralWidget(&qTextEdit);
  QToolBar qToolBar;
  ColorButton qBtnColor("Text Color", qTextEdit.palette().color(QPalette::Text));
  qToolBar.addWidget(&qBtnColor);
  ColorButton qBtnColorBg("Background", qTextEdit.palette().color(QPalette::Base));
  qToolBar.addWidget(&qBtnColorBg);
  qWin.addToolBar(&qToolBar);
  qWin.show();
  // install signal handlers
  QObject::connect(&qBtnColor, &QPushButton::clicked,
    [&]() { qTextEdit.setTextColor(qBtnColor.chooseColor()); });
  QObject::connect(&qBtnColorBg, &QPushButton::clicked,
    [&]() {
      QPalette qPal = qTextEdit.palette();
      qPal.setColor(QPalette::Base, qBtnColorBg.chooseColor());
      qTextEdit.setPalette(qPal);
    });
  // runtime loop
  return app.exec();
}

和相应的Qt项目文件testQTextEditCursorColor.pro

SOURCES = testQTextEditCursorColor.cc

QT += widgets

在Windows 10上的cygwin64中编译和测试:

$ qmake-qt5 testQTextEditCursorColor.pro

$ make && ./testQTextEditCursorColor
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQTextEditCursorColor.o testQTextEditCursorColor.cc
g++  -o testQTextEditCursorColor.exe testQTextEditCursorColor.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
Qt Version: 5.9.4
QFusionStyle(0x6000e10c0, name = "fusion")

Snapshot in X11 (white background) Snapshot in X11 (black background)

因此,黑色制作白色光标,白色制作黑色光标(独立于任何颜色设置)。假设我的上述陈述是正确的,青色背景(#00ffff)应该制作红色光标(#ff0000):

Snapshot in X11 (cyan background)

为了比较,我写了一个CMake脚本CMakeLists.txt

project(QTextEditCursorColor)

cmake_minimum_required(VERSION 3.10.0)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(Qt5Widgets CONFIG REQUIRED)

include_directories("${CMAKE_SOURCE_DIR}")

add_executable(testQTextEditCursorColor testQTextEditCursorColor.cc)

target_link_libraries(testQTextEditCursorColor Qt5::Widgets)

并在VS2017中再次编译和测试:

Qt Version: 5.11.2
QWindowsVistaStyle(0x1c1ed936690, name = "windowsvista")

(请注意,不同风格的引擎。)

Snapshot in Windows 10 (white background) Snapshot in Windows 10 (black background)

Windows GDI中的渲染很明显,字形像素也被反转(但我在上面的X11测试中注意到了相同的情况):

Cursor in Windows 10 (5× magnified)


考虑到上述情况,很明显使用中灰作为背景颜色是个坏主意。例如按位NOT #808080#7f7f7f,这两种颜色之间几乎没有对比。 (我没有提供快照,因为我无法识别正确的时间点击打印文本光标的快照的打印键。)


OP提到了另一个问答:SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color。虽然,这个答案被接受并被投票,但如上所述,以任何其他方式改变我身边的光标颜色也无济于事。这些是修改,我试过我的样本:

  • QTextEdit取代QPlainTextEdit
  • 使用qTextEdit.setCursorWidth()更改文本光标宽度
  • 使用样式表而不是修改调色板中的颜色

包括在字面上使用链接答案中的公开代码。


在与thuga(SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color接受的答案的作者)进行了一些对话后,似乎有关于此问题的Qt 5.8的错误报告:

Qt 5.8 no longer allows QPlainTextEdit's cursor color to be set

在撰写本文时被标记为Unresolved。 (目前,Qt5.12是最新版本。)


在长时间解释了为什么它无法开箱即用之后,最后一个示例如何使用自定义绘制的光标实现OP的意图:

#include <QtWidgets>

class TextEdit: public QTextEdit {
  protected:
    virtual void paintEvent(QPaintEvent *pEvent) override;
};

void TextEdit::paintEvent(QPaintEvent *pQEvent)
{
  // use paintEvent() of base class to do the main work
  QTextEdit::paintEvent(pQEvent);
  // draw cursor (if widget has focus)
  if (hasFocus()) {
    const QRect qRect = cursorRect(textCursor());
    QPainter qPainter(viewport());
    qPainter.fillRect(qRect, textColor());
  }
}

class ColorButton: public QPushButton {
  private:
    QColor _qColor;

  public:
    explicit ColorButton(
      const QString &text, const QColor &qColor = Qt::black,
      QWidget *pQParent = nullptr):
      QPushButton(text, pQParent)
    {
      setColor(qColor);
    }
    virtual ~ColorButton() = default;
    ColorButton(const ColorButton&) = delete;
    ColorButton& operator=(const ColorButton&) = delete;

    const QColor& color() const { return _qColor; }
    void setColor(const QColor &qColor)
    {
      _qColor = qColor;
      QFontMetrics qFontMetrics(font());
      const int h = qFontMetrics.height();
      QPixmap qPixmap(h, h);
      qPixmap.fill(_qColor);
      setIcon(qPixmap);
    }

    QColor chooseColor()
    {
      setColor(QColorDialog::getColor(_qColor, this, text()));
      return _qColor;
    }
};

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  qDebug() << app.style();
  // setup GUI
  QMainWindow qWin;
  qWin.resize(250, 100);
  qWin.setWindowTitle("Test Set Cursor Color");
  TextEdit qTextEdit;
  qWin.setCentralWidget(&qTextEdit);
  qTextEdit.setCursorWidth(QFontMetrics(qTextEdit.font()).averageCharWidth());
  QToolBar qToolBar;
  ColorButton qBtnColor("Text Color",
    qTextEdit.palette().color(QPalette::Text));
  qToolBar.addWidget(&qBtnColor);
  ColorButton qBtnColorBg("Background",
    qTextEdit.palette().color(QPalette::Base));
  qToolBar.addWidget(&qBtnColorBg);
  qWin.addToolBar(&qToolBar);
  qWin.show();
  // install signal handlers
  QObject::connect(&qBtnColor, &QPushButton::clicked,
    [&]() { qTextEdit.setTextColor(qBtnColor.chooseColor()); });
  QObject::connect(&qBtnColorBg, &QPushButton::clicked,
    [&]() {
      QPalette qPal = qTextEdit.palette();
      qPal.setColor(QPalette::Base, qBtnColorBg.chooseColor());
      qTextEdit.setPalette(qPal);
    });
  // runtime loop
  return app.exec();
}

QTextEdit被衍生的TextEdit取代,被覆盖的paintEvent()

QTextEdit::paintEvent()TextEdit::paintEvent()被称为主要工作。之后,光标在textColor上(重新)涂上一个矩形。 (这只是过度绘制已渲染的内置文本光标。)

Snapshot in cygwin with X11 Snapshot in Windows 10 with GDI

注意:

一个小陷阱是在QPainter中使用TextEdit::paintEvent()。因为QTextEdit来自QAbstractScrollAreaQPainter qPainter(this);将是错误的。相反,必须使用QPainter qPainter(viewport());。这在Qt doc中提到。对于QAbstractScrollArea::paintEvent()

注意:如果您打开画家,请务必在viewport()上打开它。

© www.soinside.com 2019 - 2024. All rights reserved.