Qt 添加许多 QGraphicsPixmapItem 到 QGraphicsScene
Qt add many QGraphicsPixmapItem to a QGraphicsScene
我正在尝试创建一个像大多数照片编辑器程序 (Photoshop) 一样的图层系统,我基本上是使用 QGraphicsPixmapItem::setPixmap(QPixmap *image) 绘制单个 QGraphicsPixmapItem;在 QGraphicsScene 上。我该怎么做,但我可以添加许多 QPixmaps 并随意删除它们。我尝试创建一个 QPixmaps 列表和一个 QGraphicsPixmapItems,但如果我删除或重新排列我的 QPixmaps 的顺序,它会变得混乱有没有更好的方法来做到这一点?
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(draw())); //calls the function below to redraw sc
timer->start(30);
这会每 30 毫秒更新一次 GraphicsScene,所以我在像素图 *image 上做的任何绘图都会被绘制出来,但现在我想获得一个 QPixmap 列表,并在每次调用 draw() 时将它们添加到场景中,但问题是我需要 QGraphicsPixmapItems 的列表,如果我删除一个图层或移动它们的顺序,我希望关联的 QGraphicsPixmapItem 也为 removed/moved。我想我可以做到,但它看起来很复杂,所以有什么建议吗?
void PaintArea::draw()
{
m_item->setPixmap(*image); //Do this but call layerManager.getListOfLayers() and add each to the scene
}
以下小示例应用展示了您可以如何继续。基本上,有两个模型和两个视图。模型是 QGraphicsScene 和标准 QStandardItemModel,而视图是 QListView 和 QGraphicsView。
主要任务是通过使用信号和插槽使两个模型保持同步。
可以使用“添加”按钮和上下文菜单修改模型。对于这个小应用程序,您只能添加、删除和更改您的像素图的图片。添加其他操作非常简单,例如通过拖放移动项目以及使用可检查操作和其他自定义用户角色 hide/visible 它们。
#include <QApplication>
#include <QFileDialog>
#include <QGraphicsPixmapItem>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QListView>
#include <QMenu>
#include <QPushButton>
#include <QStandardItemModel>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
auto frame = new QFrame;
frame->setLayout(new QHBoxLayout);
auto listView = new QListView;
frame->layout()->addWidget(listView);
auto graphicsView = new QGraphicsView;
frame->layout()->addWidget(graphicsView);
auto graphicsScene = new QGraphicsScene;
graphicsView->setScene(graphicsScene);
auto myModel = new QStandardItemModel;
auto btnAdd = new QPushButton("Add");
frame->layout()->addWidget(btnAdd);
QObject::connect(btnAdd, &QPushButton::clicked, [&]() {
auto item = new QStandardItem("Pixmap");
item->setData(QString("./data/test.png"), Qt::ItemDataRole::UserRole + 1);
myModel->appendRow(item);
});
listView->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
QObject::connect(listView, &QListView::customContextMenuRequested, [&](const QPoint& pos) {
auto index = listView->indexAt(pos);
QMenu menu;
auto remove = menu.addAction("Remove", [&]() {
myModel->removeRow(index.row(), index.parent());
});
if (!index.isValid()) remove->setEnabled(false);
auto changeImage = menu.addAction("Change...", [&]() {
auto file=QFileDialog::getOpenFileName(frame, "Select PNG file", "./data/", "(*.png)");
if (file.isEmpty()) return;
myModel->setData(index, file, Qt::ItemDataRole::UserRole + 1);
});
if (!index.isValid()) changeImage->setEnabled(false);
menu.exec(listView->mapToGlobal(pos));
});
QObject::connect(myModel, &QStandardItemModel::dataChanged, [&](const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles = QVector<int>()) {
if (auto item = myModel->itemFromIndex(topLeft)) {
if (auto pixItem = dynamic_cast<QGraphicsPixmapItem*>(graphicsScene->items()[topLeft.row()])) {
pixItem->setPixmap(QPixmap(item->data(Qt::ItemDataRole::UserRole + 1).toString()));
}
}
});
QObject::connect(myModel, &QStandardItemModel::rowsInserted, [&](const QModelIndex& parent, int first, int last) {
for (auto iter = first; iter <= last; iter++) {
auto index=myModel->index(iter, 0, parent);
auto pixmap=myModel->data(index, Qt::ItemDataRole::UserRole + 1).toString();;
auto item=graphicsScene->addPixmap(QPixmap(pixmap));
}
});
QObject::connect(myModel, &QStandardItemModel::rowsRemoved, [&](const QModelIndex& parent, int first, int last) {
auto items = graphicsScene->items();
for (auto iter = first; iter <= last; iter++) {
graphicsScene->removeItem(items[iter]);
}
});
listView->setModel(myModel);
frame->show();
return app.exec();
}
头文件:
...
QGraphicsScene *scene; QGraphicsItemGroup *itemGroup;
...
.cpp 文件:
void PaintArea::draw()
{
m_item->setPixmap(*image); m_item->setGroup(itemGroup); // Layers-related code
}
void PaintArea::deleteGroup(QGraphicsItemGroup *group)
{
scene->destroyItemGroup(group); // Layers-related code
}
我正在尝试创建一个像大多数照片编辑器程序 (Photoshop) 一样的图层系统,我基本上是使用 QGraphicsPixmapItem::setPixmap(QPixmap *image) 绘制单个 QGraphicsPixmapItem;在 QGraphicsScene 上。我该怎么做,但我可以添加许多 QPixmaps 并随意删除它们。我尝试创建一个 QPixmaps 列表和一个 QGraphicsPixmapItems,但如果我删除或重新排列我的 QPixmaps 的顺序,它会变得混乱有没有更好的方法来做到这一点?
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(draw())); //calls the function below to redraw sc
timer->start(30);
这会每 30 毫秒更新一次 GraphicsScene,所以我在像素图 *image 上做的任何绘图都会被绘制出来,但现在我想获得一个 QPixmap 列表,并在每次调用 draw() 时将它们添加到场景中,但问题是我需要 QGraphicsPixmapItems 的列表,如果我删除一个图层或移动它们的顺序,我希望关联的 QGraphicsPixmapItem 也为 removed/moved。我想我可以做到,但它看起来很复杂,所以有什么建议吗?
void PaintArea::draw()
{
m_item->setPixmap(*image); //Do this but call layerManager.getListOfLayers() and add each to the scene
}
以下小示例应用展示了您可以如何继续。基本上,有两个模型和两个视图。模型是 QGraphicsScene 和标准 QStandardItemModel,而视图是 QListView 和 QGraphicsView。
主要任务是通过使用信号和插槽使两个模型保持同步。
可以使用“添加”按钮和上下文菜单修改模型。对于这个小应用程序,您只能添加、删除和更改您的像素图的图片。添加其他操作非常简单,例如通过拖放移动项目以及使用可检查操作和其他自定义用户角色 hide/visible 它们。
#include <QApplication>
#include <QFileDialog>
#include <QGraphicsPixmapItem>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QListView>
#include <QMenu>
#include <QPushButton>
#include <QStandardItemModel>
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
auto frame = new QFrame;
frame->setLayout(new QHBoxLayout);
auto listView = new QListView;
frame->layout()->addWidget(listView);
auto graphicsView = new QGraphicsView;
frame->layout()->addWidget(graphicsView);
auto graphicsScene = new QGraphicsScene;
graphicsView->setScene(graphicsScene);
auto myModel = new QStandardItemModel;
auto btnAdd = new QPushButton("Add");
frame->layout()->addWidget(btnAdd);
QObject::connect(btnAdd, &QPushButton::clicked, [&]() {
auto item = new QStandardItem("Pixmap");
item->setData(QString("./data/test.png"), Qt::ItemDataRole::UserRole + 1);
myModel->appendRow(item);
});
listView->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
QObject::connect(listView, &QListView::customContextMenuRequested, [&](const QPoint& pos) {
auto index = listView->indexAt(pos);
QMenu menu;
auto remove = menu.addAction("Remove", [&]() {
myModel->removeRow(index.row(), index.parent());
});
if (!index.isValid()) remove->setEnabled(false);
auto changeImage = menu.addAction("Change...", [&]() {
auto file=QFileDialog::getOpenFileName(frame, "Select PNG file", "./data/", "(*.png)");
if (file.isEmpty()) return;
myModel->setData(index, file, Qt::ItemDataRole::UserRole + 1);
});
if (!index.isValid()) changeImage->setEnabled(false);
menu.exec(listView->mapToGlobal(pos));
});
QObject::connect(myModel, &QStandardItemModel::dataChanged, [&](const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles = QVector<int>()) {
if (auto item = myModel->itemFromIndex(topLeft)) {
if (auto pixItem = dynamic_cast<QGraphicsPixmapItem*>(graphicsScene->items()[topLeft.row()])) {
pixItem->setPixmap(QPixmap(item->data(Qt::ItemDataRole::UserRole + 1).toString()));
}
}
});
QObject::connect(myModel, &QStandardItemModel::rowsInserted, [&](const QModelIndex& parent, int first, int last) {
for (auto iter = first; iter <= last; iter++) {
auto index=myModel->index(iter, 0, parent);
auto pixmap=myModel->data(index, Qt::ItemDataRole::UserRole + 1).toString();;
auto item=graphicsScene->addPixmap(QPixmap(pixmap));
}
});
QObject::connect(myModel, &QStandardItemModel::rowsRemoved, [&](const QModelIndex& parent, int first, int last) {
auto items = graphicsScene->items();
for (auto iter = first; iter <= last; iter++) {
graphicsScene->removeItem(items[iter]);
}
});
listView->setModel(myModel);
frame->show();
return app.exec();
}
头文件:
...
QGraphicsScene *scene; QGraphicsItemGroup *itemGroup;
...
.cpp 文件:
void PaintArea::draw()
{
m_item->setPixmap(*image); m_item->setGroup(itemGroup); // Layers-related code
}
void PaintArea::deleteGroup(QGraphicsItemGroup *group)
{
scene->destroyItemGroup(group); // Layers-related code
}