简体   繁体   English

如何响应 QStringListModel 的 QT 列表视图中的内部移动

[英]How to respond to internal move in QT's listview of a QStringListModel

My app is almost done.我的应用程序快完成了。 I'm stuck trying to update elements of my mainwindow when I move an item up or down in a simple listview model that has a QStringListModel as its backend.当我在以 QStringListModel 作为后端的简单列表视图模型中向上或向下移动项目时,我一直在尝试更新主窗口的元素。

Here is my model for allowing drag/drop:这是我允许拖放的模型:

#ifndef MYMODEL_H
#define MYMODEL_H

#include <QStringListModel>

class mymodel : public QStringListModel
{
public:
    mymodel(QObject * parent = nullptr);
    Qt::ItemFlags flags(const QModelIndex &index) const;
};
#endif // MYMODEL_H

The model implementation is:模型实现是:

#include "mymodel.h"

mymodel::mymodel(QObject *parent) : QStringListModel (parent) {}

Qt::ItemFlags mymodel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags defaultFlags = QStringListModel::flags(index);

    if (index.isValid())
    {
        return  Qt::ItemIsSelectable | Qt::ItemIsDragEnabled |
                Qt::ItemIsEnabled ;
    }
    else
    {
        return  Qt::ItemIsSelectable  | Qt::ItemIsDragEnabled |
                Qt::ItemIsDropEnabled | defaultFlags;
    }
}

Here is my implementation, which does work, except I cannot detect if I move a row up down.这是我的实现,它确实有效,但我无法检测到我是否向上移动一行。

    //create model
    model = new mymodel(this);

    //make some data
    QStringList List;
    List << "one" << "two" << "three";

   // populate the model
    model->setStringList(List);

    // create a list view
     QListView *lv = new QListView(this);

    // glue model and view together
    lv->setModel(model);

    // allow modifying the data in Listview
    lv->setDragDropMode(QAbstractItemView::InternalMove);
    lv->setDragDropOverwriteMode(false);
    lv->setEditTriggers(QAbstractItemView::AnyKeyPressed |
                        QAbstractItemView::DoubleClicked);

I've tried all of the following, they do compile, but don't do anything.我已经尝试了以下所有方法,它们确实可以编译,但什么也不做。

They are supposed to simply console print 'something happened', but they don't.他们应该简单地控制台打印“发生了一些事情”,但他们没有。

    // doesnt do anything! compiles
    connect(lv, &QListView::indexesMoved,
            this, &MainWindow::rowsMoved);

    // doesnt do anything! compiles
    connect(lv->model(), &QStringListModel::rowsMoved,
            this, &MainWindow::rowsMoved);

    // doesnt do anything! compiles
    connect(lv->model(), &QAbstractItemModel::rowsMoved,
            this, &MainWindow::rowsMoved);

The rowsMoved is declared in the headers with: rowsMo​​ved 在标题中声明为:

void rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row);
};

In the interim, I have found that adding to constructor:在此期间,我发现添加到构造函数中:

lv->installEventFilter(this);

In the cpp as well as later defined as:在cpp以及后来定义为:

bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
    if (object == lv)
    {
        if (event->type() == QEvent::ChildRemoved) {
            qDebug() << "drop event!";

        // iterate over the listview and print out it's data,
        // so if you wanted this back in your stringlist.. this is
        // where you'd do it:
        for (int i = 0; i < model->rowCount(); ++i)
        {
            qDebug().noquote() <<  model->index(i, 0).data(Qt::DisplayRole).toString();
        }
        return true;
        }
    }
    return false;
}

This gets me a 'poor mans notification' but it feels 'dirty'这让我收到了“穷人通知”,但感觉“很脏”

So grateful that eyllanesc helped me!非常感谢 eyllanesc 帮助了我! Thank you.谢谢你。

Posting this here, should any one need.在这里张贴,如果有人需要。

This code indeed does allow me edit items, move them up/down in the list view, and be notified when something in the list is changed by the user.这段代码确实允许我编辑项目,在列表视图中向上/向下移动它们,并在用户更改列表中的某些内容时收到通知。 In addition, not shown below, the below allows drag / drop operations from file manager which for my app I need.此外,下面没有显示,下面允许从我的应用程序需要的文件管理器中进行拖放操作。

If you were to compare my original post based on QStringListModel you'll notice they look almost exactly the same.如果您根据 QStringListModel 比较我的原始帖子,您会发现它们看起来几乎完全相同。 I am still perplexed why using that model did not work.我仍然困惑为什么使用该模型不起作用。 But facts are facts, this works and the other does not.但事实就是事实,这行得通,而另一个则行不通。

mymodel.h我的模型.h

#ifndef MYMODEL_H
#define MYMODEL_H

#include <QStandardItemModel>
class mymodel : public QStandardItemModel
{

public:
    mymodel(QObject * parent = nullptr);
    Qt::ItemFlags flags(const QModelIndex &index) const;
};

#endif // MYMODEL_H

mymodel.cpp我的模型.cpp

#include "mymodel.h"
#include <QDebug>

mymodel::mymodel(QObject *parent) : QStandardItemModel (parent) {}

Qt::ItemFlags mymodel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index);

    if (index.isValid())
    {
        return  Qt::ItemIsSelectable | Qt::ItemIsDragEnabled |
                Qt::ItemIsEnabled    | Qt::ItemIsEditable;
    }
    else
    {
        return  Qt::ItemIsSelectable  | Qt::ItemIsDragEnabled |
                Qt::ItemIsDropEnabled | defaultFlags;
    }
}

mainwindow.h主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QListView>
#include <QStandardItemModel>
#include <QStringList>

class MainWindow : public QWidget
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    QListView *lv;
    QStringList list;
    QStandardItemModel *model;

private slots:
    void itemChanged();
};
#endif // MAINWINDOW_H

mainwindow.cpp主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QBoxLayout>
#include <QDebug>
#include "mymodel.h"

MainWindow::MainWindow(QWidget *parent)
{
    lv = new QListView(this);
    model = new mymodel(lv);

    list << "one" << "two" << "three";
    for (int i=0; i < list.length(); ++i)
    {
        model->appendRow(new QStandardItem(list[i]));
    }

    lv->setModel(model);
    lv->setDragDropMode(QAbstractItemView::InternalMove);
    lv->setDragDropOverwriteMode(false);
    QBoxLayout *lo = new QBoxLayout(QBoxLayout::LeftToRight);
    lo->addWidget(lv);
    setLayout(lo);

    connect(model, &QStandardItemModel::itemChanged,
            this,  &MainWindow::itemChanged);
}

MainWindow::~MainWindow()
{
}

void MainWindow::itemChanged()
{
    qDebug().noquote() << "an item changed";
}

mainwindow.h主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QListView>
#include <QStandardItemModel>
#include <QStringList>

class MainWindow : public QWidget
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    QListView *lv;
    QStringList list;
    QStandardItemModel *model;

private slots:
    void itemChanged();
};
#endif // MAINWINDOW_H

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM