是)我有的:
QTreeView
带有表数据的类QAbstractTableModel
模型问题:如何保存扩展的物品状态?有人已经完成了解决方案吗?
PS:我知道,我可以自己做这个代码,但是我没有太多时间,这不是我们项目的主要问题,但我们仍然需要它,因为app包含很多这样的表,并且每次扩展树项都是烦恼的过程...
mos*_*osg 13
首先,感谢拉齐了persistentIndexList
和isExpanded
方式.
其次,这是对我有用的代码就好了:-)
dialog.h文件:
class Dialog : public QDialog
{
Q_OBJECT;
TreeModel *model;
TreeView *view;
public:
Dialog(QWidget *parent = 0);
~Dialog(void);
void reload(void);
protected:
void createGUI(void);
void closeEvent(QCloseEvent *);
void saveState(void);
void restoreState(void);
};
Run Code Online (Sandbox Code Playgroud)
dialog.cpp文件:
Dialog::Dialog(QWidget *parent)
{
createGUI();
reload();
}
Dialog::~Dialog(void) {};
void Dialog::reload(void)
{
restoreState();
}
void Dialog::createGUI(void)
{
QFile file(":/Resources/default.txt");
file.open(QIODevice::ReadOnly);
model = new TreeModel(file.readAll());
file.close();
view = new TreeView(this);
view->setModel(model);
QVBoxLayout *mainVLayout = new QVBoxLayout;
mainVLayout->addWidget(view);
setLayout(mainVLayout);
}
void Dialog::closeEvent(QCloseEvent *event_)
{
saveState();
}
void Dialog::saveState(void)
{
QStringList List;
// prepare list
// PS: getPersistentIndexList() function is a simple `return this->persistentIndexList()` from TreeModel model class
foreach (QModelIndex index, model->getPersistentIndexList())
{
if (view->isExpanded(index))
{
List << index.data(Qt::DisplayRole).toString();
}
}
// save list
QSettings settings("settings.ini", QSettings::IniFormat);
settings.beginGroup("MainWindow");
settings.setValue("ExpandedItems", QVariant::fromValue(List));
settings.endGroup();
}
void Dialog::restoreState(void)
{
QStringList List;
// get list
QSettings settings("settings.ini", QSettings::IniFormat);
settings.beginGroup("MainWindow");
List = settings.value("ExpandedItems").toStringList();
settings.endGroup();
foreach (QString item, List)
{
// search `item` text in model
QModelIndexList Items = model->match(model->index(0, 0), Qt::DisplayRole, QVariant::fromValue(item));
if (!Items.isEmpty())
{
// Information: with this code, expands ONLY first level in QTreeView
view->setExpanded(Items.first(), true);
}
}
}
Run Code Online (Sandbox Code Playgroud)
祝你今天愉快!)
PS:这个例子基于C:\Qt\4.6.3\examples\itemviews\simpletreemodel
代码.
感谢Razi和mosg我能够让这个工作.我让它以递归方式恢复扩展状态,所以我想我会分享那部分.
void applyExpandState_sub(QStringList& expandedItems,
QTreeView* treeView,
QAbstractItemModel* model,
QModelIndex startIndex)
{
foreach (QString item, expandedItems)
{
QModelIndexList matches = model->match( startIndex, Qt::UserRole, item );
foreach (QModelIndex index, matches)
{
treeView->setExpanded( index, true );
applyExpandState_sub(expandedItems,
treeView,
model,
model->index( 0, 0, index ) );
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用像:
void myclass::applyExpandState()
{
m_treeView->setUpdatesEnabled(false);
applyExpandState_sub( m_expandedItems,
m_treeView,
m_model,
m_model->index( 0, 0, QModelIndex() ) );
m_treeView->setUpdatesEnabled(true);
}
Run Code Online (Sandbox Code Playgroud)
我在这里使用Qt :: UserRole,因为我的模型中的多个项目可能具有相同的显示名称,这会破坏展开状态恢复,因此UserRole为每个项目提供唯一标识符以避免该问题.
这两个函数通过使用循环应该为您做到这一点:
QModelIndexList QAbstractItemModel::persistentIndexList () const
bool isExpanded ( const QModelIndex & index ) const
Run Code Online (Sandbox Code Playgroud)
这是一种适用于任何基于 QTreeView 的小部件的通用方法,它使用某种 ID 系统来识别元素(我假设 ID 是一个 int,它存储在 中Qt::UserRole
):
void MyWidget::saveExpandedState()
{
for(int row = 0; row < tree_view_->model()->rowCount(); ++row)
saveExpandedOnLevel(tree_view_->model()->index(row,0));
}
void Widget::restoreExpandedState()
{
tree_view_->setUpdatesEnabled(false);
for(int row = 0; row < tree_view_->model()->rowCount(); ++row)
restoreExpandedOnLevel(tree_view_->model()->index(row,0));
tree_view_->setUpdatesEnabled(true);
}
void MyWidget::saveExpandedOnLevel(const QModelIndex& index)
{
if(tree_view_->isExpanded(index)) {
if(index.isValid())
expanded_ids_.insert(index.data(Qt::UserRole).toInt());
for(int row = 0; row < tree_view_->model()->rowCount(index); ++row)
saveExpandedOnLevel(index.child(row,0));
}
}
void MyWidget::restoreExpandedOnLevel(const QModelIndex& index)
{
if(expanded_ids_.contains(index.data(Qt::UserRole).toInt())) {
tree_view_->setExpanded(index, true);
for(int row = 0; row < tree_view_->model()->rowCount(index); ++row)
restoreExpandedOnLevel(index.child(row,0));
}
}
Run Code Online (Sandbox Code Playgroud)
而不是MyWidget::saveExpandedState()
andMyWidget::saveExpandedState()
也可以直接调用MyWidget::saveExpandedOnLevel(tree_view_->rootIndex())
and MyWidget::restoreExpandedOnLevel(tree_view_->rootIndex())
。我只使用了上面的实现,因为无论如何都会调用 for 循环,MyWidget::saveExpandedState()
并且MyWidget::saveExpandedState()
使用我的 SIGNAL 和 SLOT 设计看起来更干净。