Qt Model View 简便类(一)

小编:啊南 358阅读 2021.01.18

表格、列表和树型窗口部件是 GUI 开发中经常会用到的窗口部件。传统的方式是窗口部件本身包含用于存储数据的内置容器。这种方式非常符合直观感受,然而,在许多复杂的应用中,这将导致数据的同步问题。早期Qt使用的就是上述的方式。第二种方式是模型/视图编程,窗口部件无需维护内部的数据容器。它们通过标准的接口获取外部数据,也因此避免了数据的重复。

提到模型/视图编程,就不得不说一下Smalltalk语言设计的大数据集可视化方法—模型—视图—控制器(Model-View-Controller,MVC)。Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

Qt的Model /View可以理解是对MVC的变形,将MVC中的控制器替换成了稍微有些不同的抽象:委托(delegate)。Qt对每种类型的视图都提供了默认的委托,这对绝大多数应用程序而言已经足够了,所以通常我们不需要注意它。

对于Qt的Model /View我们可以简单的划分为3种使用级别:

①Model /View的简便类

②Model /View的预定义模型

③Model /View的自定义模型

简便类:如QListWidget、QTableWidget、QTreeWidget。

预定义模型:QStringListModel、QStanderItemModel、QFileSystemMode等模型以及数据库模型。

说了一大堆,也不是很理解。那么接下来我们用一个小例子来了解下Model /View简便类的使用。

运行环境:ubuntu、 Qt5.5.1

例子是C++ GUI Qt4 改成的Qt5,通过一个对话框显示用户可以编辑的(x,y)坐标。

一、构造函数

CoordinateSetter::CoordinateSetter(QList *coords,
                                   QWidget *parent)
    : QDialog(parent)
{
    coordinates = coords;

    tableWidget = new QTableWidget(0, 2);
    tableWidget->setHorizontalHeaderLabels(
            QStringList() << tr("X") << tr("Y"));

    for (int row = 0; row < coordinates->count(); ++row) {
        QPointF point = coordinates->at(row);
        slot_addRow();
        tableWidget->item(row, 0)->setText(QString::number(point.x()));
        tableWidget->item(row, 1)->setText(QString::number(point.y()));
    }

.
.
.
.
.
.
    setWindowTitle(tr("Coordinate Setter"));
}

QTableWidget中每一个项都使用一个QTableWidgetItem表示,slot_addRow()每次都会添加两个QTableWidgetItem用来显示坐标x和y,tableWidget->item()->setText()则用来设置QTableWidgetItem的内容。

默认情况下,QTableWidget允许编辑。如果需要防止用户编辑,可以调用setEditTriggers(QAbstractItemView::NoEditTriggers).

二、slot_addRow()

void CoordinateSetter::slot_addRow()
{
    int row = tableWidget->rowCount();

    tableWidget->insertRow(row);

    QTableWidgetItem *item0 = new QTableWidgetItem;
    item0->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
    tableWidget->setItem(row, 0, item0);

    QTableWidgetItem *item1 = new QTableWidgetItem;
    item1->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
    tableWidget->setItem(row, 1, item1);

    tableWidget->setCurrentItem(item0);
}

用户单击Add Row按钮时,就会触发这个槽函数,这种方式在构造函数中也经常使用。我们使用QTableWidget::insertRow()插入一个新行,使用QTableWidgetItem 创建两个Item,之后使用QTableWidget::setItem()将他们添加到列表中。

三、保存修改

void CoordinateSetter::done(int result)
{
    if (result == QDialog::Accepted) {
        coordinates->clear();
        for (int row = 0; row < tableWidget->rowCount(); ++row) {
            double x = tableWidget->item(row, 0)->text().toDouble();
            double y = tableWidget->item(row, 1)->text().toDouble();
            coordinates->append(QPointF(x, y));
        }
    }
    QDialog::done(result);
}

最后,用户点击Ok按钮时,则会清空传递给这个对话框的人坐标,并且根据这个QTableWidget的所有Item创建一个新的坐标集。运行结果如下:

如果将坐标存储到数据库,这样则会有更好的展示效果。以后有机会会结合之前的sqlite再做一次修改。

关联标签: