我尝试添加QML
N Items
new Item
Items
,以添加和删除 a {{1}在给定的索引。
我做了以下示例,但问题是当我移动一些DataList
时,当我尝试插入一个新的时,位置可能不正确并且我没有线索为什么。当我在cpp model
中检查new or deleted items
时,位置是正确的,但inserted
不会 deleted
/ new Item
在正确的位置。
似乎当我插入move
,然后我delete
时出现错误,然后我尝试Item
这个insert
或{{ 1}}新Item
旁边的Item
。
这是一个简单的例子(如果需要,你可以运行它)。我拨打了Items Data
:Blocks
#include "mainwindow.h"
#include <QApplication>
#include <QtQml>
#include <QQuickView>
#include <QQuickWidget>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
的main.cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "model.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void addItem(int index);
~MainWindow();
private slots:
private:
QList<QObject*> dataList;
Ui::MainWindow *ui;
BlockModel model;
int cpt = 0;
};
#endif // MAINWINDOW_H
mainwindow.h
#include <QtQml>
#include <QQuickView>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QQuickWidget"
#include <QStringList>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
int nbItems = 5;
for(; cpt < nbItems; cpt ++) {
Block a = Block(QString("Item ")+QString::number(cpt));
model.addBlock(a);
}
ui->setupUi(this);
QQuickWidget *view = new QQuickWidget;
QQmlContext *ctxt = view->rootContext();
ctxt->setContextProperty("myModel", &model);
view->setSource(QUrl::fromLocalFile("main.qml"));
view->setGeometry(0, 200, 600, 400);
view->setResizeMode(QQuickWidget::SizeRootObjectToView);
ui->dockWidget_3->setWidget(view);
}
MainWindow::~MainWindow()
{
delete ui;
}
mainwindow.cpp
#include <QAbstractListModel>
#include <QStringList>
#include <qqmlcontext.h>
#include <QDebug>
#include <QStringList>
//![0]
class Block
{
public:
Block(){
}
Block(const QString &name);
QString nameBlock() const;
void setName(QString n) {
m_name = n;
}
private:
QString m_name;
};
class BlockModel : public QAbstractListModel
{
Q_OBJECT
public:
Block* getBlock(QString name);
Q_INVOKABLE void moveBlock(int from,int to);
Q_INVOKABLE void insertBlock(int index);
Q_INVOKABLE void deleteBlock(int index);
enum BlockRoles {
nameRole = Qt::UserRole + 1,
};
BlockModel(QObject *parent = 0);
void setContext(QQmlContext *ctx) {
m_ctx = ctx;
}
void setName(const QString &name);
void addBlock(const Block &Block);
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
QHash<int, QByteArray> roleNames() const;
private:
QList<Block> m_blocks;
QQmlContext* m_ctx;
int cpt = 0;
};
mode.h
#include "model.h"
#include "qDebug"
Block::Block(const QString &name)
: m_name(name)
{
}
QString Block::nameBlock() const
{
return m_name;
}
BlockModel::BlockModel(QObject *parent)
: QAbstractListModel(parent)
{
}
void BlockModel::addBlock(const Block &Block)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_blocks << Block;
endInsertRows();
}
int BlockModel::rowCount(const QModelIndex & parent) const {
Q_UNUSED(parent);
return m_blocks.count();
}
void BlockModel::moveBlock(int from, int to) {
m_blocks.move(from,to);
}
void BlockModel::insertBlock(int index) {
Block b =(Block(QString("New Item ")+QString::number(cpt)));
beginInsertRows(QModelIndex(),index+1,index+1);
m_blocks.insert(index+1,b);
endInsertRows();
cpt++;
}
void BlockModel::deleteBlock(int index) {
beginRemoveRows(QModelIndex(),index,index);
m_blocks.removeAt(index);
endRemoveRows();
}
QVariant BlockModel::data(const QModelIndex & index, int role) const {
if (index.row() < 0 || index.row() >= m_blocks.count())
return QVariant();
const Block &Block = m_blocks[index.row()];
if (role == nameRole)
return Block.nameBlock();
return QVariant();
}
//![0]
QHash<int, QByteArray> BlockModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[nameRole] = "nameBlock";
return roles;
}
model.cpp
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QtQml.Models 2.2
import QtQuick.Controls.Styles 1.4
Rectangle {
id : rootRectangle
visible: true
ScrollView {
anchors.fill:parent
ListView{
id: root
width: parent.width; height: parent.height
property int visualIndex: -1
displaced: Transition {
NumberAnimation { properties: "y"; easing.type: Easing.OutQuad }
}
model: DelegateModel {
id: visualModel
model: myModel
delegate: Component {
MouseArea {
id: delegateRoot
property int visualIndex: DelegateModel.itemsIndex
cursorShape: Qt.PointingHandCursor
width: root.width; height: 100
drag.target: icon
drag.axis: Drag.YAxis
Behavior on height {
PropertyAnimation { duration: 100 }
}
Rectangle {
anchors.top: delegateRoot.top
anchors.left: delegateRoot.left
id: icon
objectName: nameBlock
width: root.width-5; height: 100
color: "skyblue"
radius: 3
Text {
objectName: "rect"
id: title
anchors.fill: parent
anchors.margins: 10
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: nameBlock
}
Drag.active: delegateRoot.drag.active
Drag.source: delegateRoot
Drag.hotSpot.x: 36
Drag.hotSpot.y: 36
Button {
id : buttonAdd
text: "Add Block"
anchors{
right: parent.right
top: parent.top
bottom: parent.bottom
margins: 30
}
onClicked: {
myModel.insertBlock(visualIndex)
}
}
Button {
id : buttonDelete
text: "Delete Block"
anchors{
right: buttonAdd.left
top: parent.top
bottom: parent.bottom
margins: 30
}
onClicked: {
myModel.deleteBlock(visualIndex)
}
}
states: [
State {
when: icon.Drag.active
ParentChange {
target: icon
parent: root
}
AnchorChanges {
target: icon;
anchors.horizontalCenter: undefined;
anchors.verticalCenter: undefined
}
}
]
transitions: Transition {
// Make the state changes smooth
ParallelAnimation {
ColorAnimation { property: "color"; duration: 500 }
NumberAnimation { duration: 300; properties: "detailsOpacity,x,contentY,height,width,font.pixelSize,font.bold,visible" }
}
}
}
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
visualModel.items.move(drag.source.visualIndex, delegateRoot.visualIndex)
myModel.moveBlock(drag.source.visualIndex,delegateRoot.visualInde)
}
}
}
}
}
}
}
}
main.qml
你知道我做错了什么吗? 非常感谢,祝你有个美好的一天!
答案 0 :(得分:1)
移动物品时有两个错误。在DropArea.onEntered
中,如果您在drag.source.visualIndex
之前和之后打印delegateRoot.visualIndex
和visualModel.items.move
,则会在移动后看到值已被修改。这意味着您在调用myModel.moveBlock
时移动了错误的行。要解决此问题,请在移动项目之前保存该值:
DropArea {
anchors { fill: parent; margins: 15 }
onEntered: {
var from = drag.source.visualIndex;
var to = delegateRoot.visualIndex;
visualModel.items.move(from, to);
myModel.moveBlock(from, to);
}
}
在C ++模型中移动项目时,应该像插入/移除项目一样调用QAbstractItemModel::beginMoveRows
。否则,QML DelegateModel
无法正确显示您的模型。请记住,在实施BlockModel::moveBlock
时,模型的目标行与源列表m_blocks
的目标行不同。有关详细信息,请参阅QAbstractItemModel::beginMoveRows
documentation中的最后一个示例。
void BlockModel::moveBlock(int from, int to) {
if (from == to)
return;
auto modelFrom = from;
auto modelTo = to + (from < to ? 1 : 0);
beginMoveRows(QModelIndex(), modelFrom, modelFrom, QModelIndex(), modelTo);
m_blocks.move(from,to);
endMoveRows();
}