语境
假设我想实现一个自定义 QWidget 类,它应该实现一个按钮(类似于 QPushButton)。
要求:
- 它应遵循操作系统的颜色(也是图标)
- 它应显示
QWidget::action
. 对于本练习,图标可以是使用 QPainter 手动绘制的简单矩形。在最终版本中,我使用 SvgRenderer 用操作系统颜色为图标着色。 - 它应允许不同的尺寸和分辨率。
注意:QPalette
有助于为多种目的获取操作系统颜色。重要的是不要保存调色板,而是QWidget::palette()
在需要时调用:这允许操作系统在用户更改操作系统上的颜色设置时正确更新 UI。
为了说明我的尝试,我将使用以下示例:
#include <QDebug>
#include <QAction>
#include <QApplication>
#include <QIconEngine>
#include <QPainter>
#include <QPaintEvent>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
class TestIconEngine: public QIconEngine
{
public:
void paint(QPainter* p, const QRect &rect, QIcon::Mode mode, QIcon::State state) override
{
p->fillRect(rect, QColor(128,0,0)); // I SHOULD USE QPALETTE HERE!!! <------
qDebug() << "icon engine paint: " << rect << mode << state;
}
QIconEngine* clone() const override
{
throw std::runtime_error("Not yet implemented");
}
};
class TestWidget: public QPushButton
{
Q_OBJECT
public:
explicit TestWidget( QWidget* parent=nullptr):QPushButton(parent){}
void paintEvent(QPaintEvent *event) override
{
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing, true);
p.setClipRect(event->rect());
const auto pal = palette();
p.setBrush(pal.color(QPalette::Button));
p.setPen(QPen(pal.color(QPalette::Highlight),2.0));
const auto r = rect();
p.drawRoundedRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2, 10.0, 10.0);
const auto& actList = actions();
if (actList.size()>0)
{
const QAction* act = actList[0];
const QRect iconRect(r.x()+5, r.y()+5, r.height()-10, r.height()-10);
act->icon().paint(&p, iconRect);
}
}
};
#include "main.moc"
int main(int argn, char* argv[])
{
QApplication app(argn, argv);
QWidget window;
window.resize(300, 200);
window.show();
QVBoxLayout layout(&window);
layout.setContentsMargins(10, 10, 10, 10);
window.setLayout(&layout);
TestWidget test(&window);
layout.addWidget(&test);
QAction act;
act.setIcon(QIcon(new TestIconEngine())); //This shit takes ownership of engine (!RAII)
test.addAction(&act);
return app.exec();
}
我的假设是QAction::icon
在小部件上放置一个图标。但我在努力理解它设计背后的尝试是什么,因为:
QPalette
没有传递给QIconEngine
,因此,我看不到如何使用正确的操作系统颜色呈现图标。我可能可以想象一些黑客将其保存QPalette
在一个static
变量中,但这似乎不是正确的方法。QIconEngine
似乎是自定义的方式QIcon
,当我可以通过扩展获得相同的结果时,为什么需要这样做QIcon
?(为此,QIcon
需要 bevirtual
,令人沮丧的是事实并非如此)。- 我应该
QIconEngine
为每个创建一个实例QIcon
吗?还是QIconEngine
所有人共享的Icons
? - 我应该在
QIconEngine
或 中缓存图标的呈现QIcon
吗?
问题:
如何使 QPalette 可访问,以便 QIconEngine 可以以正确的(OS)颜色绘制图标?