0

语境

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

在此处输入图像描述

要求:

  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,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需要 be virtual,令人沮丧的是事实并非如此)。
  • 我应该QIconEngine为每个创建一个实例QIcon吗?还是QIconEngine所有人共享的Icons
  • 我应该在QIconEngine或 中缓存图标的呈现QIcon吗?

问题:

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

4

0 回答 0