【问题标题】:Qt - is there a way to transform a graphic item into a pixmap?Qt - 有没有办法将图形项目转换为像素图?
【发布时间】:2018-10-25 18:42:16
【问题描述】:

我想从一个图形对象创建一个像素图,所以我可以将像素图设置为一个图标

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

Block *block = new Block();

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

QPixmap pixmapItem;
pixmapItem.copy(rect);

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

但像素图似乎是空的。

有没有办法从图形对象或图形项中获取图像/图标?

【问题讨论】:

  • 据我所知,您对块所做的唯一事情是获取其边界矩形,然后使用该矩形获取 pixmapItem 的子集(为空)。

标签: c++ qt qt5 qgraphicsitem


【解决方案1】:

你必须使用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();
}

【讨论】:

  • painter.end() 是不必要的,因为它是一个“自关闭”的 RAII 类,就像 QFile 等一样。
  • 将像素图传递给列表小部件数据非常好!
  • @KubaOber 是的,我知道,我忘了删除它,谢谢你告诉我。 :D
  • 如果您的 GraphicsItem 的左上角不在 (0,0) 处,您可能需要添加 painter.translate(-item-&gt;boundingRect().x(),-item-&gt;boundingRect().y()); 以偏移画家,并避免裁剪图像
【解决方案2】:

应该可以为此使用QGraphicsItem::paint

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

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

【讨论】:

    【解决方案3】:

    这是因为边界矩形仅包含有关您的 QGraphicsItem 的坐标和大小信息,而没有有关如何绘制它的更多信息。

    您可以尝试类似以下的操作:创建一个与您的block 大小相同的QImage,并使用它来初始化一个QPainter。然后QPainter 可以被block 用来在图像上绘图。这是使用paint 方法实现的,Block 继承自QGraphicsItem

    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());
    

    那么您的block 应该已经被绘制为image

    【讨论】:

    • 这里至少 painterQStyleOptionGraphicsItem 应该是自动变量 - 否则你的代码会泄漏内存!
    【解决方案4】:

    感谢@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;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-05
      • 2019-08-22
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 1970-01-01
      • 2019-06-18
      相关资源
      最近更新 更多