将模型设置为QTableWidget

9
我想编写一个可以访问数据库表的应用程序。我选择了QSqlTableModel作为表格的模型组件。
QTableView的问题在于它似乎没有返回表格中当前选定记录的方法,所以我选择了继承自QTableView的QTableWidget类。
但是,当我尝试使用-setModel()将模型设置到此表格小部件时,我会收到以下错误消息:
c:/Qt/qt/include/QtGui/../../src/gui/itemviews/qtablewidget.h:337: error: `virtual void QTableWidget::setModel(QAbstractItemModel*)' is private.
消息说“setModel”方法是私有的。查看文档告诉我它是公共的。
我该怎么办?

我需要获取单元格中的记录,而不是它的坐标。 - crew4ok
5个回答

8

正如其他人所指出的那样,你不需要使用 QTableWidget,而是需要使用 QTableView。获取记录的方法如下:

static QList<QSqlRecord> selected_records( const QTableView * tv ) {
    // make sure we're really dealing with what we think we're dealing with:
    assert( static_cast<QSqlTableModel*>( tv->model() )
            == qobject_cast<QSqlTableModel*>( tv->model() );
    const QSqlTableModel * const tm = static_cast<QSqlTableModel*>( tv->model() );
    const QModelIndexList mil = tv->selectionModel()->selectedRows();
    QList<QSqlRecord> result;
    Q_FOREACH( const QModelIndex & mi, mil )
        if ( mi.isValid() )
            result.push_back( tm->record( mi.row() ) );
    return result;
}

如果你正在处理连接到QTableView(实际上是QAbstractItemView)的信号,比如说clicked(QModelIndex),那么这段代码就是你需要的:

void slotClicked( const QModelIndex & mi ) {
    // make sure we're really dealing with what we think we're dealing with:
    assert( static_cast<QSqlTableModel*>( tableView->model() )
            == qobject_cast<QSqlTableModel*>( tableView->model() );
    const QSqlRecord rec = static_cast<QSqlTableModel*>( tableView->model() )
               ->record( mi.row() );
    // use 'rec'
} 

是的,Qt 可以内置此功能,特别是 QSqlTableModel 可以有一种更方便的方式将 QModelIndex 映射回 QSqlRecord,但这就是现状。

据我所了解,我必须在clicked()信号中使用它。但是当我检查QList是否为空时,我发现它是空的。=/ - crew4ok
如果您使用 QAbstractItemView::clicked(QModelIndex),则会将 QModelIndex 作为信号参数传递。上述代码是用于查看所选记录的情况。在 clicked() 的情况下,您只需要 Q_FOREACH 中的两行代码,其中 mi 是来自信号的 QModelIndex - Marc Mutz - mmutz

2

这个方法在 QAbstractItemView 级别上是公开的,但 QTableWidget 有一个内置模型,您无法更改。

要获取选择项,您必须调用 selectedItems()(它是 QAbstractItemView 的一个方法,而不是 QTableView,所以您在文档中错过了它)。


我需要使用QTableView因为它有公共的setModel()函数,但是它没有selectedItems()函数。 - crew4ok
就像Aaron所说的那样,selectedItems()是QTableView的一部分——它是基类QAbstractItemView的一部分。 - swongu
我在QAbstractItemView中也没有看到selectedItems。请参阅:http://doc.trolltech.com/4.5/qabstractitemview-members.html。 - Jesse Vogt
上面有个错别字:应该说QTableWidget具有内置模型,而不是QTableView。 - Ropez

1

QTableWidget:详情

QTableWidget类提供了一个基于项的表格视图和一个默认模型。

表格小部件为应用程序提供标准的表格显示功能。QTableWidget中的项目由QTableWidgetItem提供。

如果您想要使用自己的数据模型的表格,应该使用QTableView而不是这个类。

如果您想使用自己的模型,View类会处理模型本身。

您是正确的,TableView或SQLModel似乎没有方法来知道选择。您可以从TableView派生自己的类,并通过selectionChanged slot跟踪当前选择。

或者

使用QTableView::selectionModel()并调用selection()。这类似于mmutz的答案。确保阅读该代码以了解实际获取记录的详细信息。

小心。你不想在这里使用selectionModel:那是用于通过Shift-click等方式处理选择视图中项目的类型。内部数据模型只是视图的model属性。 - quark

0

我只用过一次模型-视图架构,但我会试着给你一些关于这个架构的一般见解,因为我觉得你还没有很好地理解它。所以这可能会不完整和简化,但希望还是基本正确的。

如果你使用一个视图,你可以提供自己的模型。如果你使用一个小部件,那么你就不使用Qt模型,而是自己插入项目。最好使用模型来解耦事物(这样你可以为同一个模型拥有多个视图,或者稍后更改模型...)

当你使用一个模型时,视图本身会知道如何向你提供的模型填充数据(使用data函数)。从视图中获取选择项有几种方法:我通过连接视图在用户点击视图时发出的clicked信号来处理它,连接到我自己编写的槽函数上。clicked信号提供了一个表/列表的索引,我将其映射到该槽函数中我的模型中的一个项目。

可能还有其他方法来做到这一点,但这就是我做的方式,而且运行得很好。

要对Qt模型-视图架构有一个总体了解:

http://doc.trolltech.com/4.5/model-view-programming.html


-1

在QTableWidget中它是私有的

class Q_GUI_EXPORT QTableWidget : public QTableView
{
...
...
private:
    void setModel(QAbstractItemModel *model);
...

这是在QAbstractItemView中公开的。

所以你不能从这里调用这个函数...

请检查include\Qt\qtablewidget.h中的qtablewidget.h文件。

也许这不是一个好答案,但至少它说明了为什么它不起作用...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接