动态调整QIcon的大小,而无需调用setSizeIcon() [英] Dynamically resize QIcon without calling setSizeIcon()

查看:2291
本文介绍了动态调整QIcon的大小,而无需调用setSizeIcon()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在努力解决一个容易解决的问题.许多小部件都支持某种 QSizePolicy .其中包括 QPushbutton .在我的情况下,我在网格布局中有多个按钮,所有按钮的QSizePolicy(用于垂直和水平)调整大小均设置为扩展.这会导致根据网格布局所包含的小部件的大小来调整按钮大小的麻烦结果.

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

这似乎有点过大,尤其是因为QPushbutton支持QSizePolicy,并且开发人员根本不需要修改这个部门,除非他/她希望进行一些特殊的调整大小.同样,这也与对可以在 QIcon 中使用的SVG文件的支持相矛盾,因为众所周知,SVG =矢量图形=您可以随意拉伸它们而不会降低质量.

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

PS:我也研究了QPixmap-仍然存在相同的问题.

我忘了提到一种发现自己想要做的事情的方法(但是结果并不像我想要的那样漂亮)-使用样式表中的 image 属性QPushbutton.但是,这不会创建图标!如果真的不需要真正的图标,而只需要使用绘画按钮,则使用此属性可以在调整大小方面提供极大的灵活性,尤其是在使用SVG时.

@div的注释中,

解决方案

子类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_())

这将导致:

图标的最大尺寸受QIcon中用作输入的png的尺寸限制.如果将svg用作QIcon的输入,则图标的缩放比例将不受大小限制.但是,Windows 7中似乎不支持svg图标,而Ubuntu中则支持.

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

I'm currently struggling with what should be an easy issue to solve. Many widgets support some sort of QSizePolicy. This includes the QPushbutton. In my case I have multiple buttons in a grid layout all of which have their QSizePolicy for both vertical and horizontal resizing set to expanding. This leads to the nead result of the buttons being resized according to the size of the widget which the grid layout is part of.

The problem comes from the way icons seem to be handled in Qt. QIcon does not have a QSizePolicy property (or at least I was unable to find one in the official documentation of Qt4 about QIcon and QAbstractButton). The only way seems to be using setIconSize() where you can give the maximum size of the icon. In addition one has to manually implement a routine on how the size is to be updated. In this case it would be (abstract writing here) icon.size == button.size-CONSTANT, where CONSTANT is some kind of a predefined factor (>= 0). Predefining various sizes (a list of QIcons) for the selected icon is also possible but still not a good option (read below why).

This seems to be a little bit of an overkill especially since QPushbutton supports QSizePolicy and the developer doesn't have to tinker in this departement at all unless he/she wants some special resizing going on. Also this sort of contradicts the support for SVG files that can be used in QIcon since, as we know, SVG = vector graphics = you can stretch those as much as you like without loss of quality.

Does anyone know an easy way to do that without the need to add additional even handles for resizing, providing a list of scales of the chosen icon or restricting the size to a maximum size?

PS: I have also looked into QPixmap - still the same issues there.

EDIT: I forgot to mention one way I found out how to do what I wanted (the results are however not as pretty as I want them to be) - using the image property in the stylesheet for QPushbutton. This however does not create an icon! If one doesn't really require a real icon and can just use a painted button using this property allows a huge flexibility in terms of resizing especially when using SVG.

解决方案

Sub-classing QPushButton, as suggested by @Pavel in a comment, seems like a reasonable option to solve your issue. Below I provide a simple example that shows how this can be done in 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_())

Which results in:

The maximum size of the icon is limited by the size of the png used as input in QIcon. If a svg is used as input for the QIcon, the scaling of the icon won't be limited in size. However, svg icons seems not to be supported in Windows7, but they are in Ubuntu.

The code above would need to be expanded if a label is added to the button. Moreover, it would be possible to also scale the font size of the label to the button size if desired.

这篇关于动态调整QIcon的大小,而无需调用setSizeIcon()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆