Qt 5.8 QTextEdit文本光标颜色不会改变 [英] Qt 5.8 QTextEdit Text Cursor Color Won't Change

查看:465
本文介绍了Qt 5.8 QTextEdit文本光标颜色不会改变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将文本光标放在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-> setHorizo​​ntalScrollBarPolicy(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>

类TextEdit:公共TextEdit
{
Q_OBJECT
public:
显式TextEdit(QWidget * parent = nullptr);

私人:
QTimer * timer;
QPainter * pPainter;
bool bCursorVisible;

受保护:
虚拟void paintEvent(QPaintEvent * pEvent)覆盖;

信号:
sendUpdate();

公众席位:
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)
{
//使用基类的paintEvent()完成主要工作
QTextEdit :: paintEvent(事件);
//绘制光标(如果小部件具有焦点)
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;
}

发出sendUpdate();
}


解决方案

与OP进行了一些对话之前,由于我非常怀疑 QTextEdit 的color属性是否也负责文本光标的颜色。



我在



因此,黑色代表白色光标,白色会变成黑色光标(与任何颜色设置无关)。假设我的上述说法正确,青色背景(#00ffff )应该使红色光标(#ff0000 ):





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

 项目(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)

include_directories( $ {CMAKE_SOURCE_DIR})

add_executable(testQTextEditCursorColor testQTextEditCursorColor.cc)

target_link_libraries(testQTextEditCursorColor Qt5 :: Widgets)

和再次在VS2017中进行编译和测试:

  Qt版本:5.11.2 
QWindowsVistaStyle( 0x1c1ed936690,名称= windowsvista)

(请注意,不同样式的引擎。)





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








上面的想法很明显,使用中级是个坏主意灰色作为背景色,例如#808080 的按位非为#7f7f7f ,并且这两种颜色之间的对比度很小(我没有提供快照,因为我无法识别正确的时间来敲击 Print 键以绘制带有文本光标的快照。)






OP引用了另一个Q& A:



注意:



一个小陷阱是 TextEdit :: paintEvent() QPainter 的用法。因为 QTextEdit 是从 QAbstractScrollArea 派生的,所以 QPainter qPainter(this); 是错误的。相反,必须使用 QPainter qPainter(viewport()); 。这是在Qt文档中提到的。对于 QAbstractScrollArea :: paintEvent()


注意:如果您打开画家,请确保将其打开 viewport()



I am trying to make the text cursor on a QTextEdit red (rgb(255,0,0)). Despite my best efforts, it continues to blink white.

From what I've found, the Style Sheet "color" property is supposed to change the color of the cursor. Not sure what's wrong.

My Code:

    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);");

Edit: I encourage a full read of Scheff's answer. It's awesome. I noticed that the cursor created with his solution didn't blink, though, so I wanted to share a blinking version derived from Scheff's code with my (inexperienced) addition.

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

解决方案

There was some conversation with OP beforehand, as I had serious doubts whether the color property of the QTextEdit is responsible for the color of text cursor as well.

All I found in the Qt Style Sheets Reference:

The color used to render text.

This property is supported by all widgets that respect the QWidget::palette.

If this property is not set, the default is whatever is set for in the widget's palette for the QWidget::foregroundRole (typically black).

Out of curiosity, I fiddled a little bit with colors of QTextEdit.

  1. I could reproduce what OP described:
    Changing the text color of QTextEdit (e.g. with QTextEdit::setTextColor()) has an effect on inserted text typed afterwards but it didn't change the text cursor color (at least, on the platforms where I tested).

  2. While fiddling I realized another fact that encouraged me to write this answer:
    IMHO, the text cursor ignores any color setting. Instead, it inverts the pixels under the drawn text cursor bar.
    Have a look at QPainter::RasterOp_NotSource to see what I mean.

My sample application 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();
}

and the corresponding Qt project file testQTextEditCursorColor.pro:

SOURCES = testQTextEditCursorColor.cc

QT += widgets

Compiled and tested in cygwin64 on Windows 10:

$ 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")

So, black makes a white cursor, white makes a black cursor (independent of any color setting). Assuming my above statement is correct, cyan background (#00ffff) should make red cursor (#ff0000):

For a comparison, I wrote a CMake script 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)

and compiled and tested in VS2017 again:

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

(Please note, the different style engine.)

The rendering in the Windows GDI makes it obvious that glyph pixels are inverted as well (but I noticed the same in the X11 test above):


The above in mind, it becomes obvious that it's a bad idea to use middle gray as background color. The bitwise NOT of e.g. #808080 is #7f7f7f and there is little contrast between these two colors. (I don't provide a snapshot because I was not able to recognize the right time to hit the Print key for a snapshot with text cursor drawn.)


OP referred to another Q&A: SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color. Though, this answer was accepted and upvoted, it didn't help to change the cursor color on my side in any other way as described above. These are the modifications, I tried on my sample:

  • replacing QTextEdit by QPlainTextEdit
  • changing text cursor width with qTextEdit.setCursorWidth()
  • used style sheets instead of modifying the colors in palette

including using the exposed code in linked answer "literally".


After some conversation with thuga (the author of the accepted answer to SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color, it appeared that there is a bug report for Qt 5.8 concerning this:

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

which is marked as Unresolved at the time of writing. (Currently, Qt5.12 is the most recent version.)


After having long explained why it cannot work out-of-the-box, finally a sample how OPs intention can be achieved with a custom-painted cursor:

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

The QTextEdit is replaced by the derived TextEdit with an overridden paintEvent().

The QTextEdit::paintEvent() is called in TextEdit::paintEvent() to do the main work. Afterwards the cursor is (re-)painted with a rectangle in the textColor. (This simply over-paints the already rendered built-in text cursor.)

Note:

A smalls trap is the usage of QPainter in TextEdit::paintEvent(). Because QTextEdit is derived from QAbstractScrollArea, QPainter qPainter(this); would be wrong. Instead, QPainter qPainter(viewport()); has to be used. This is mentioned in the Qt doc. for QAbstractScrollArea::paintEvent():

Note: If you open a painter, make sure to open it on the viewport().

这篇关于Qt 5.8 QTextEdit文本光标颜色不会改变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆