如何使 QIconEngine 可以访问 QPalette?

问题描述

上下文

假设我想实现一个自定义 QWidget 类,它应该实现一个按钮(类似于 QPushButton)。

enter image description here

要求:

  1. 它应遵循操作系统的颜色(也是图标)
  2. 它应显示来自 QWidget::action 的图标。在本练习中,图标可以是一个使用 QPainter 手动绘制的简单矩形。在最终版本中,我使用 SvgRenderer 用操作系统颜色为图标着色。
  3. 它应允许不同的尺寸和分辨率。

注意: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)); // 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);
    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();
}

Palette in light

Palette in dark

我的假设是 QAction::icon 的存在是为了在小部件上放置一个图标。但我很难理解它背后的设计尝试是什么,因为:

  • QPalette 没有传递给 QIconEngine,因此,我不知道如何使用适当的操作系统颜色呈现图标。我可能会想象一些黑客将 QPalette 保存在 static 变量中,但这似乎不是正确的方法
  • QIconEngine 似乎是自定义 QIcon 的方式,当我通过扩展 QIcon 可以获得相同的结果时,为什么需要这样做? (为此,QIcon 需要为 virtual,令人沮丧的是事实并非如此)。
  • 我是否应该为每个 QIconEngine 创建一个 QIcon 实例?还是在所有QIconEngine之间共享一个Icons
  • 我应该在 QIconEngineQIcon 中缓存图标的渲染吗?

问题:

如何使 QPalette 可访问,以便 QIconEngine 可以以适当的 (OS) 颜色绘制图标?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...