Qt 5.8 QTextEdit 文本光标颜色不会改变
Qt 5.8 QTextEdit Text Cursor Color Won't Change
我正在尝试使 QTextEdit 上的文本光标变为红色 (rgb(255,0,0))。尽管我尽了最大努力,它仍继续闪烁白色。
根据我的发现,样式 Sheet "color" 属性 应该会更改光标的颜色。不知道怎么了。
我的代码:
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();
}
事先与 OP 进行了一些交谈,因为我严重怀疑 QTextEdit
的颜色 属性 是否也与文本光标的颜色有关。
我在 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).
出于好奇,我摆弄了一下 QTextEdit
的颜色。
我可以重现 OP 描述的内容:
更改 QTextEdit
的文本颜色(例如使用 QTextEdit::setTextColor()
)会对之后输入的插入文本产生影响,但它不会改变文本光标颜色(至少,在我测试的平台上)。
在摆弄的过程中,我意识到另一个鼓励我写下这个答案的事实:
恕我直言,文本光标忽略任何颜色设置。相反,它会反转绘制的文本光标栏下的像素。
看看 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")
因此,黑色光标为白色光标,白色光标为黑色光标(与任何颜色设置无关)。假设我上面的陈述是正确的,青色背景 (#00ffff
) 应该是红色光标 (#ff0000
):
为了对比,我写了一个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")
(请注意,不同风格的引擎。)
Windows GDI 中的渲染明显表明字形像素也被反转了(但我在上面的 X11 测试中注意到了同样的情况):
综上所述,很明显使用中间灰色作为背景色不是一个好主意。例如的按位非#808080
是 #7f7f7f
并且这两种颜色之间几乎没有对比。 (我没有提供快照,因为我无法识别正确的时间来点击 Print 键来绘制文本光标的快照。)
OP 引用了另一个问答:SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color。虽然,这个答案被接受并赞成,但如上所述以任何其他方式改变我这边的光标颜色并没有帮助。这些是修改,我在我的样本上试过:
- 将
QTextEdit
替换为 QPlainTextEdit
- 更改文本光标宽度
qTextEdit.setCursorWidth()
- 使用样式表而不是修改调色板中的颜色
包括在链接答案中使用暴露的代码 "literally"。
在与 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
中被(重新)绘制成一个矩形。 (这只是简单地覆盖了已经呈现的内置文本光标。)
注:
小陷阱是 QPainter
在 TextEdit::paintEvent()
中的用法。因为 QTextEdit
派生自 QAbstractScrollArea
,所以 QPainter qPainter(this);
是错误的。相反,必须使用 QPainter qPainter(viewport());
。 Qt 文档中提到了这一点。 QAbstractScrollArea::paintEvent()
:
Note: If you open a painter, make sure to open it on the viewport().
应要求,我的另一个 :
中示例程序的 Python3 / PyQt5 端口
#!/usr/bin/python3
import sys
from PyQt5.QtCore import QT_VERSION_STR, QRect
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar
from PyQt5.QtGui import QPainter, QIcon, QPixmap, QFontMetrics, QPalette
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QPushButton, QColorDialog
class TextEdit(QTextEdit):
def __init__(self, parent=None):
QTextEdit.__init__(self, parent)
def paintEvent(self, event):
# use paintEvent() of base class to do the main work
QTextEdit.paintEvent(self, event)
# draw cursor (if widget has focus)
if self.hasFocus():
rect = self.cursorRect(self.textCursor())
painter = QPainter(self.viewport())
painter.fillRect(rect, self.textColor())
class ColorButton(QPushButton):
def __init__(self, text, custom_color, parent=None):
QPushButton.__init__(self, text, parent)
self.setColor(custom_color)
def color(self):
return self.custom_color
def setColor(self, custom_color):
self.custom_color = custom_color
font_metrics = QFontMetrics(self.font())
h = font_metrics.height()
pixmap = QPixmap(h, h)
pixmap.fill(self.custom_color)
self.setIcon(QIcon(pixmap))
def chooseColor(self):
self.setColor(QColorDialog().getColor(self.custom_color))
return self.custom_color
if __name__ == '__main__':
print("Qt Version: {}".format(QT_VERSION_STR))
app = QApplication(sys.argv)
print(app.style())
# build GUI
win = QMainWindow()
win.resize(250, 100)
win.setWindowTitle("Test Set Cursor Color")
text_edit = TextEdit()
text_edit.setCursorWidth(QFontMetrics(text_edit.font()).averageCharWidth())
win.setCentralWidget(text_edit)
tool_bar = QToolBar()
btn_color = ColorButton(
"Text Color", text_edit.palette().color(QPalette.Text))
tool_bar.addWidget(btn_color)
btn_color_bg = ColorButton(
"Background", text_edit.palette().color(QPalette.Base))
tool_bar.addWidget(btn_color_bg)
win.addToolBar(tool_bar)
win.show()
# install signal handlers
btn_color.clicked.connect(
lambda state: text_edit.setTextColor(btn_color.chooseColor()))
def on_click(state):
palette = text_edit.palette()
palette.setColor(QPalette.Base, btn_color_bg.chooseColor())
text_edit.setPalette(palette)
btn_color_bg.clicked.connect(on_click)
# runtime loop
sys.exit(app.exec_())
输出:
Qt Version: 5.9.3
<PyQt5.QtWidgets.QCommonStyle object at 0x6ffffd8dc18>
我正在尝试使 QTextEdit 上的文本光标变为红色 (rgb(255,0,0))。尽管我尽了最大努力,它仍继续闪烁白色。
根据我的发现,样式 Sheet "color" 属性 应该会更改光标的颜色。不知道怎么了。
我的代码:
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();
}
事先与 OP 进行了一些交谈,因为我严重怀疑 QTextEdit
的颜色 属性 是否也与文本光标的颜色有关。
我在 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).
出于好奇,我摆弄了一下 QTextEdit
的颜色。
我可以重现 OP 描述的内容:
更改QTextEdit
的文本颜色(例如使用QTextEdit::setTextColor()
)会对之后输入的插入文本产生影响,但它不会改变文本光标颜色(至少,在我测试的平台上)。在摆弄的过程中,我意识到另一个鼓励我写下这个答案的事实:
恕我直言,文本光标忽略任何颜色设置。相反,它会反转绘制的文本光标栏下的像素。
看看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")
因此,黑色光标为白色光标,白色光标为黑色光标(与任何颜色设置无关)。假设我上面的陈述是正确的,青色背景 (#00ffff
) 应该是红色光标 (#ff0000
):
为了对比,我写了一个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")
(请注意,不同风格的引擎。)
Windows GDI 中的渲染明显表明字形像素也被反转了(但我在上面的 X11 测试中注意到了同样的情况):
综上所述,很明显使用中间灰色作为背景色不是一个好主意。例如的按位非#808080
是 #7f7f7f
并且这两种颜色之间几乎没有对比。 (我没有提供快照,因为我无法识别正确的时间来点击 Print 键来绘制文本光标的快照。)
OP 引用了另一个问答:SO: Qt 5.3 QPlainTextEdit Change the QTextCursor color。虽然,这个答案被接受并赞成,但如上所述以任何其他方式改变我这边的光标颜色并没有帮助。这些是修改,我在我的样本上试过:
- 将
QTextEdit
替换为QPlainTextEdit
- 更改文本光标宽度
qTextEdit.setCursorWidth()
- 使用样式表而不是修改调色板中的颜色
包括在链接答案中使用暴露的代码 "literally"。
在与 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
中被(重新)绘制成一个矩形。 (这只是简单地覆盖了已经呈现的内置文本光标。)
注:
小陷阱是 QPainter
在 TextEdit::paintEvent()
中的用法。因为 QTextEdit
派生自 QAbstractScrollArea
,所以 QPainter qPainter(this);
是错误的。相反,必须使用 QPainter qPainter(viewport());
。 Qt 文档中提到了这一点。 QAbstractScrollArea::paintEvent()
:
Note: If you open a painter, make sure to open it on the viewport().
应要求,我的另一个
#!/usr/bin/python3
import sys
from PyQt5.QtCore import QT_VERSION_STR, QRect
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar
from PyQt5.QtGui import QPainter, QIcon, QPixmap, QFontMetrics, QPalette
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QPushButton, QColorDialog
class TextEdit(QTextEdit):
def __init__(self, parent=None):
QTextEdit.__init__(self, parent)
def paintEvent(self, event):
# use paintEvent() of base class to do the main work
QTextEdit.paintEvent(self, event)
# draw cursor (if widget has focus)
if self.hasFocus():
rect = self.cursorRect(self.textCursor())
painter = QPainter(self.viewport())
painter.fillRect(rect, self.textColor())
class ColorButton(QPushButton):
def __init__(self, text, custom_color, parent=None):
QPushButton.__init__(self, text, parent)
self.setColor(custom_color)
def color(self):
return self.custom_color
def setColor(self, custom_color):
self.custom_color = custom_color
font_metrics = QFontMetrics(self.font())
h = font_metrics.height()
pixmap = QPixmap(h, h)
pixmap.fill(self.custom_color)
self.setIcon(QIcon(pixmap))
def chooseColor(self):
self.setColor(QColorDialog().getColor(self.custom_color))
return self.custom_color
if __name__ == '__main__':
print("Qt Version: {}".format(QT_VERSION_STR))
app = QApplication(sys.argv)
print(app.style())
# build GUI
win = QMainWindow()
win.resize(250, 100)
win.setWindowTitle("Test Set Cursor Color")
text_edit = TextEdit()
text_edit.setCursorWidth(QFontMetrics(text_edit.font()).averageCharWidth())
win.setCentralWidget(text_edit)
tool_bar = QToolBar()
btn_color = ColorButton(
"Text Color", text_edit.palette().color(QPalette.Text))
tool_bar.addWidget(btn_color)
btn_color_bg = ColorButton(
"Background", text_edit.palette().color(QPalette.Base))
tool_bar.addWidget(btn_color_bg)
win.addToolBar(tool_bar)
win.show()
# install signal handlers
btn_color.clicked.connect(
lambda state: text_edit.setTextColor(btn_color.chooseColor()))
def on_click(state):
palette = text_edit.palette()
palette.setColor(QPalette.Base, btn_color_bg.chooseColor())
text_edit.setPalette(palette)
btn_color_bg.clicked.connect(on_click)
# runtime loop
sys.exit(app.exec_())
输出:
Qt Version: 5.9.3
<PyQt5.QtWidgets.QCommonStyle object at 0x6ffffd8dc18>