Qt добавляет много QGraphicsPixmapItem в QGraphicsScene - PullRequest
0 голосов
/ 07 октября 2019

Я пытаюсь создать систему слоев, как большинство программ для редактирования фотографий (Photoshop), и я в основном рисую один QGraphicsPixmapItem, используя QGraphicsPixmapItem :: setPixmap (QPixmap * image);на 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);

Это обновляет GraphicsScene каждые 30 мс, таклюбой рисунок, который я делаю на изображении pixmap *, рисуется, но теперь я хочу получить список QPixmap и добавлять их в сцену каждый раз, когда вызывается draw (), но проблема в том, что мне нужен список QGraphicsPixmapItems и, если я удаляю слой илиПереместить их порядок. Я хочу, чтобы связанный QGraphicsPixmapItem также был удален / перемещен. Я думаю, я могу сделать это, но это кажется очень сложным, так что любой совет?

void PaintArea::draw()
{
    m_item->setPixmap(*image); //Do this but call layerManager.getListOfLayers() and add each to the scene
}

Ответы [ 2 ]

0 голосов
/ 07 октября 2019

Заголовочный файл:

...
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
}
0 голосов
/ 07 октября 2019

Следующий небольшой пример приложения показывает, как вы можете продолжить. В основном, есть две модели и два вида. Модели - это QGraphicsScene и стандартная QStandardItemModel, а представления - это QListView и QGraphicsView.

Основная задача состоит в том, чтобы синхронизировать обе модели с помощью сигнала и слотов.

Модель можно изменить с помощью кнопки Добавить и контекстного меню. Для этого небольшого приложения можно только добавить, удалить и изменить изображение вашего растрового изображения. Действительно просто добавить другие действия, такие как перемещение элементов с помощью перетаскивания, а также скрыть / увидеть их с помощью проверяемого действия и другой пользовательской роли.

#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();
}
...