Qt - 有没有一种方法可以将图形项转换为像素图?

7

我希望从图形对象创建一个Pixmap,以便将其设置为图标。

我有一个从QGraphicsPathItem派生的Block类,并尝试使用:

Block *block = new Block();

QRect rect = block->boundingRect().toRect();

QPixmap pixmapItem;
pixmapItem.copy(rect);

QListWidgetItem *item = new QListWidgetItem;
item->setIcon(QPixmap(pixmapItem));

但是这个 pixmap 看起来是空的。

有没有办法从 graphicObject 或 graphicItem 中获取图像/图标?


2
据我所见,您正在使用块的唯一操作是获取其边界矩形,然后使用该矩形获取一个子集 pixmapItem(其中为空)。 - Marker
5个回答

7

您需要使用QGraphicsItempaint()方法来获取渲染:

static QPixmap QPixmapFromItem(QGraphicsItem *item){
    QPixmap pixmap(item->boundingRect().size().toSize());
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    QStyleOptionGraphicsItem opt;
    item->paint(&painter, &opt);
    return pixmap;
}

例子:

#include <QApplication>
#include <QGraphicsPathItem>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QListWidget>

static QPixmap QPixmapFromItem(QGraphicsItem *item){
    QPixmap pixmap(item->boundingRect().size().toSize());
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    QStyleOptionGraphicsItem opt;
    item->paint(&painter, &opt);
    return pixmap;
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    QHBoxLayout lay(&w);
    QListWidget listWidget;
    QGraphicsView view;
    QGraphicsScene scene;
    view.setScene(&scene);

    int counter = 0;
    for(const QColor & color : {QColor("red"), QColor("blue"), QColor("green")}){
        QPainterPath p;
        p.addRoundedRect(0, 0, 150, 50, 2, 2);
        QGraphicsPathItem *block = scene.addPath(p);
        block->setBrush(QBrush(color));
        block->setFlag(QGraphicsItem::ItemIsMovable);
        block->setFlag(QGraphicsItem::ItemIsSelectable);
        block->setPos(counter*QPointF(10, 10));

        // get QPixmap from item
        QPixmap pixmap = QPixmapFromItem(block); 

        QListWidgetItem *l_item = new QListWidgetItem(color.name());
        listWidget.addItem(l_item);
        l_item->setIcon(QIcon(pixmap));
        counter++;
    }
    lay.addWidget(&listWidget);
    lay.addWidget(&view);
    w.show();
    return a.exec();
}

enter image description here


2
painter.end()是不必要的,因为它是一个RAII类,就像QFile等一样会自动关闭。 - Kuba hasn't forgotten Monica
2
将像素图传递到列表小部件数据非常好! - Kuba hasn't forgotten Monica
@KubaOber 是的,我知道,我忘了删除它,谢谢你让我知道。 :D - eyllanesc
1
如果您的GraphicsItem不是在(0,0)处具有其左上角,则可能需要添加painter.translate(-item->boundingRect().x(),-item->boundingRect().y());来偏移绘图器,并避免裁剪图像。 - B. Decoster

3

可以使用QGraphicsItem::paint来实现此功能:

QSize itemSize = item->boundingRect()
QPixmap targetPixmap(item->boundingRect().size().toSize());

QPainter pixmapPainter(&targetPixmap);
QStyleOptionGraphicsItem styleOption;
item->paint(&pixmapPainter, &styleOption);

2
这是因为bounding rectangle仅包含关于您的QGraphicsItem的坐标和大小信息,但没有有关如何绘制它的进一步信息。
您可以尝试类似以下的操作:创建一个与您的“block”大小相同的QImage,并使用它来初始化一个QPainter。然后,该QPainter可由“block”用于在图像上绘制。这是通过“Block”从“QGraphicsItem”继承的“paint”方法实现的。
Block *block = new Block();
QSize size = block->boundingRect().toRect().toSize();
QImage* image = new QImage(size, QImage::Format_RGB32);
QPainter* painter = new QPainter(image);
block->paint(painter, new StyleOptionGraphicsItem());

然后您的应该被绘制到图像中。

2
这里至少应该将 painterQStyleOptionGraphicsItem 定义为自动变量 - 否则你的代码会泄露内存! - joe_chip

2

感谢@eyllanesc提供的好例子。此外,在某些情况下,翻译命令也是必要的。

 static QPixmap QPixmapFromItem(QGraphicsItem *item){
            QPixmap pixmap(item->boundingRect().size().toSize());
            pixmap.fill(Qt::transparent);
            QPainter painter(&pixmap);
            painter.setRenderHint(QPainter::Antialiasing);
            QStyleOptionGraphicsItem opt;
            painter.translate (-1 * (item->boundingRect ().topLeft ()));//THIS IS MANDATORY IN SOME CASES.
            item->paint(&painter, &opt);
            return pixmap;
        }

0

虽然这篇文章是很久以前解决的,但我想贡献一下Python和PyQt5中该函数的“翻译”:


    def convert( self, item: QGraphicsItem ):
        pixmap = QPixmap( item.boundingRect().size().toSize() )
        pixmap.fill( Qt.transparent )
        painter = QPainter( pixmap )
        # this line seems to be needed for all items except of a LineItem...
        painter.translate( -item.boundingRect().x(), -item.boundingRect().y())
        painter.setRenderHint( QPainter.Antialiasing, True )
        opt = QStyleOptionGraphicsItem()
        item.paint( painter, opt , self) # here in some cases the self is needed
        return pixmap


# The "some cases": Placing this function in a QGraphicsScene-Subclass was ok without the "self", but placing it in QWidget-Subclass needed this self.

感谢这里所有的回答 :-)

...但我必须承认,我并不真正理解在这一行中发生了什么:item.paint( painter, opt , self) 我会很高兴得到任何关于它如何工作的解释,但我也很高兴它能够工作 ;-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接