Qt Jambi: QTreeView与自定义模型?



我试图使用Java在QT中创建一个树视图来显示类似于

的东西
+ Category A
| + Category AB
| | Item AB
|  Item A
+ Category B
|  Item B
 Item

使用自定义QAbstractItemModel,同时遵循指南。

Qt Jambi如何实现QModelIndex的包装器似乎有一些问题。似乎没有一种方法来创建它的新实例,就像你可以在Qt指南,它似乎是缺少功能包装(至少isValidinternalPointer)。

下面是我目前根据指南编写的代码:TreeModel

package playground;
import io.qt.core.*;
import java.util.stream.Stream;
public final class TreeModel extends QAbstractItemModel {
private final TreeItem rootItem;
public TreeModel(QString data, QObject parent) {
super(parent);
rootItem = new TreeItem(Stream.of(tr("Title"), tr("Summary")).map(QVariant::new).toList(), null);
setupModelData(data.split('n'), rootItem);
}
private void setupModelData(QStringList split, TreeItem rootItem) {
//TODO
}
@Override
public QModelIndex index(int row, int column, QModelIndex parent) {
if(!hasIndex(row, column, parent)) {
return new QModelIndex();
}
var parentItem = !parent.isValid() ? rootItem : parent.internalPointer();
var child = parentItem.child(row);
return child != null ? createIndex(row, column, childItem) : new QModelIndex();
}
@Override
public QModelIndex parent(QModelIndex index) {
if(!index.isValid()) {
return new QModelIndex();
}
var childItem = index.internalPointer();
var parentItem = childItem.parentItem();
if(parentItem == rootItem) {
return new QModelIndex();
}
return createIndex(parentItem.row(), 0, parentItem);
}
@Override
public int rowCount(QModelIndex parent) {
if(parent.column() > 0) {
return 0;
}
var parentItem = !parent.isValid() ? rootItem : parent.internalPointer();
return parentItem.childCount();
}
@Override
public int columnCount(QModelIndex parent) {
return (parent.isValid() ? parent.internalPointer() : rootItem).columnCount();
}
@Override
public Object data(QModelIndex index, int role) {
if(!index.isValid()) {
return new QVariant();
}
if(role != Qt.ItemDataRole.DisplayRole) {
return new QVariant();
}
var item = index.internalPointer();
return item.data(index.column());
}
@Override
public Qt.ItemFlags flags(QModelIndex index) {
return !index.isValid() ? new Qt.ItemFlags() : index.flags();
}
@Override
public Object headerData(int section, Qt.Orientation orientation, int role) {
if(orientation == Qt.Orientation.Horizontal && role == Qt.ItemDataRole.DisplayRole) {
return rootItem.data(section);
}
return new QVariant();
}
}

TreeItem:

package playground;
import io.qt.core.QVariant;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public final class TreeItem {
private final List<TreeItem> childItems = new ArrayList<>();
private final List<QVariant> itemData = new ArrayList<>();
private final TreeItem parentItem;
public TreeItem(List<QVariant> data, TreeItem parent) {
this.itemData.addAll(data);
this.parentItem = parent;
}
public void appendChild(TreeItem child) {
Objects.requireNonNull(child);
childItems.add(child);
}
public TreeItem child(int row) {
if(row < 0 || row >= childItems.size()) {
return null;
}
return childItems.get(row);
}
public int childCount() {
return childItems.size();
}
public int columnCount() {
return itemData.size();
}
public QVariant data(int column) {
if(column < 0 || column >= itemData.size()) {
return null;
}
return itemData.get(column);
}
public int row() {
if(parentItem != null) {
return parentItem.childItems.indexOf(this);
}
return 0;
}
public TreeItem parentItem() {
return parentItem;
}
}

好吧,有人在不同的平台上给我指出了正确的方向,我才明白了这个问题。

事实证明,您需要通过QAbstractItemModel方法来创建QModelIndex的实例,您还需要创建自己的" invalidate "索引而不是使用无参数方法。

代替new QModelIndex(),你需要使用QAbstractItemModel.createIndex(-1, -1, 0)。而不是QModelIndex.isValid,你需要做如下的事情:

public static boolean isIndexValid(QModelIndex index) {
return index != null && index.row() >= 0 && index.column() >= 0 && index.model() != null;
}

最后,而不是使用内部ID的东西,如果它是一个指针,你需要保持你自己的ID记录。我的基本实现如下:

private final Map<Long, TreeItem> idToItemMap = new HashMap<>();
private final Map<TreeItem, Long> itemToIdMap = new HashMap<>();
private long nextId = 1;
private long getId(TreeItem childItem) {
long id = itemToIdMap.getOrDefault(childItem, -1L);
if(id == -1) {
id = nextId++;
itemToIdMap.put(childItem, id);
idToItemMap.put(id, childItem);
}
return id;
}
private TreeItem getItem(QModelIndex index) {
var item = idToItemMap.get(index.internalId());
if(item == null) {
throw new NullPointerException("item was null: " + index);
}
return item;
}

(不要在可以从模型中删除项的产品代码中使用它,它会保留引用并泄漏内存。)

最新更新