在不调用setSizeIcon()的情况下动态调整QIcon的大小

时间:2015-07-31 09:03:12

标签: c++ qt svg pyqt4 autoresize

我目前正在努力解决一个容易解决的问题。许多小部件支持某种 QSizePolicy 。这包括 QPushbutton 。在我的情况下,我在网格布局中有多个按钮,所有这些按钮的QSizePolicy都将垂直和水平调整大小设置为展开。这导致按钮的大小结果根据网格布局所属的小部件的大小进行调整。

问题来自于Qt中图标的处理方式。 QIcon没有QSizePolicy属性(或者至少我无法在Qt4的官方文档中找到关于QIconQAbstractButton的文档。唯一的方法似乎是使用 setIconSize(),您可以在其中给出图标的最大大小。另外,必须手动实现关于如何更新大小的例程。在这种情况下,它将是(这里抽象写) icon.size == button.size-CONSTANT ,其中CONSTANT是某种预定义因子(> = 0)。为所选图标预定义各种尺寸(QIcons列表)也是可能的,但仍然不是一个好的选择(请参阅下面的原因)。

这似乎有点过分,特别是因为QPushbutton支持QSizePolicy并且开发人员根本不需要修改这个部分,除非他/她想要进行一些特殊的调整。这也与可以在 QIcon 中使用的SVG文件的支持相矛盾,因为正如我们所知,SVG =矢量图形=您可以在不损失质量的情况下尽可能多地拉伸这些文件。

有没有人知道一种简单的方法,无需添加额外的偶数句柄来调整大小,提供所选图标的比例列表或将大小限制为最大尺寸?

PS:我也研究过QPixmap - 那里的问题仍然存在。

修改 我忘了提一种方法,我发现了如何做我想做的事情(然而结果并不像我希望的那样漂亮) - 在{{1}的样式表中使用 image 属性}。但是,这不会创建图标!如果一个人真的不需要一个真正的图标,并且可以使用这个属性使用绘制的按钮,那么在调整大小时就会有很大的灵活性,特别是在使用SVG时。

2 个答案:

答案 0 :(得分:3)

@Pavel在评论中建议的子类QPushButton似乎是解决问题的合理选择。下面我提供一个简单的示例,说明如何在PySide中完成此操作。

import sys
from PySide import QtGui, QtCore

class myContainter(QtGui.QWidget):
    def __init__(self, parent=None):
        super(myContainter, self).__init__(parent)

        icon = QtGui.QIcon('process-stop.png')

        grid = QtGui.QGridLayout()

        for i in range(3):
            button = myPushButton()
            button.setIcon(icon) 

            grid.addWidget(button, i, 0)

            grid.setRowStretch(i, i)

        self.setLayout(grid)


class myPushButton(QtGui.QPushButton):
    def __init__(self, label=None, parent=None):
        super(myPushButton, self).__init__(label, parent)

        self.pad = 4     # padding between the icon and the button frame
        self.minSize = 8 # minimum size of the icon

        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
                                       QtGui.QSizePolicy.Expanding)
        self.setSizePolicy(sizePolicy)

    def paintEvent(self, event):

        qp = QtGui.QPainter()
        qp.begin(self)

        #---- get default style ----

        opt = QtGui.QStyleOptionButton()
        self.initStyleOption(opt)

        #---- scale icon to button size ----

        Rect = opt.rect

        h = Rect.height()
        w = Rect.width()
        iconSize = max(min(h, w) - 2 * self.pad, self.minSize)

        opt.iconSize = QtCore.QSize(iconSize, iconSize)

        #---- draw button ----

        self.style().drawControl(QtGui.QStyle.CE_PushButton, opt, qp, self)

        qp.end()

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    instance = myContainter()  
    instance.show()    

    sys.exit(app.exec_())

结果是:

enter image description here

图标的最大尺寸受png中用作输入的QIcon尺寸的限制。如果将svg用作QIcon的输入,则图标的缩放不会受到大小限制。但是,在Windows7中似乎不支持svg图标,但它们在Ubuntu中。

如果向按钮添加标签,则需要扩展上面的代码。此外,如果需要,还可以将标签的字体大小缩放到按钮大小。

答案 1 :(得分:0)

对于使用C ++工作的人。非常感谢!

pushbuttoniconautoresize.h

#ifndef PUSHBUTTONIMAGEAUTOMATICRESIZE_H
#define PUSHBUTTONIMAGEAUTOMATICRESIZE_H

#include <QPushButton>

class PushButtonIconAutoResize : public QPushButton
{
    Q_OBJECT

public:
    PushButtonIconAutoResize(const QString &text, QWidget *parent=0);
    ~PushButtonIconAutoResize();

private:
    void paintEvent(QPaintEvent *event);

    int pad;
    int minSize;
};

#endif // PUSHBUTTONIMAGEAUTOMATICRESIZE_H

pushbuttoniconautoresize.cpp

#include "pushbuttoniconautoresize.h"

#include <QSize>
#include <QSizePolicy>
#include <QStylePainter>
#include <QStyleOptionButton>
#include <QtGlobal>

PushButtonIconAutoResize::PushButtonIconAutoResize(const QString &text, QWidget *parent)
    : QPushButton(text, parent)
{
    pad = 4;
    minSize = 8;

    this->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
}

PushButtonIconAutoResize::~PushButtonIconAutoResize()
{

}

void PushButtonIconAutoResize::paintEvent( QPaintEvent *event )
{
    QStylePainter painter(this);

    QStyleOptionButton opt;
    this->initStyleOption(&opt);

    QRect r = opt.rect;

    int h = r.height();
    int w = r.width();
    int iconSize = qMax(qMin(h, w) - 2 * this->pad, this->minSize);

    opt.iconSize = QSize(iconSize, iconSize);

    painter.drawControl(QStyle::CE_PushButton, opt);
}