The article directories

  • 0 background
  • 1 the MVC knowledge
    • 1. 1 view
    • 1. 2 the agent
    • 1.3 model
  • 2 QTableVie Data presentation
    • 2.1 Using data models
      • 2.1.1 Use QStandardItemModel
      • 2.1.2 Using the QSqlQueryModel
    • 2.2 QTableView style design
    • 2.3 QTableView event
      • 2.3.1 Select events triggered by the model
      • 2.3.2 Events triggered by clicking the model
      • 2.3.3 Events triggered by the agent
          • 2.3.3.1 use setIndexWidget
          • 2.3.3.1 use QStyledItemDelegate

0 background

Because recently in the database, table aspects of the application, so used a lot of this knowledge, such as QTableView, QStandardItemModel, QItemSelectionModel, QSqlQUeryModel and so on. I consulted a lot of information and asked a lot of big wigs. This article is for the convenience of using this knowledge again in the future, so that I can quickly find the corresponding information.

1 the MVC knowledge

MV programming is model, View, control (Delegate) programming, is to separate the model and view.

1. 1 view

Views, such as QTableView, QListView, and QTreeView, are how the total data is presented.



For example, the effect is shown below.

1. 2 the agent

Proxy: Feeds changed values from the view into the model. Render the database in the model to the view.



For example, the product name and unit shown in the following figure are two different agents, one is QLineEdit (the default agent) and the other is QComboBox.

1.3 model

Model: divided into data model and selection model.

Data model (how data is organized) :



Because I mainly deal with the database, so commonly used database for QStandardItemModel, QSqlQueryModel, QSqlTableModel, QSqlRelationTableModel. (Note that Abstarct is an abstract class, so use a subclass that inherits pure virtual functions.)

The difference (the following model, further down, is more advanced) :

  • 1, QStandardItemModel: each item of data can store anything. Most flexible, but requires hand-written code to import each data into the model.
  • 2, QSqlQueryModel: the model used for SQL queries. (Automatically import all results of SQL statement query into the model)
  • 3, QSqlTableModel: encapsulates QSqlQueryModel, can only read and write one table at a time model. *4, QSqlRelationTableModel: encapsulates QSqlTableModel, provides support for foreign keys.

Select model (events after selecting/clicking model) :

QAbstractItemModel: Used to obtain the currently selected Model index

For example, an effect similar to the following is displayed



Image taken from (www.cnblogs.com/lvdongjie/p…

2 QTableVie Data presentation

2.1 Using data models

2.1.1 Use QStandardItemModel

  • 1. Define the model
    QStandardItemModel *theModel;// Data model
    QItemSelectionModel *theSelection;// Select the model
Copy the code
  • 2. Initialize the model
 	theModel = new QStandardItemModel(this);// Data model
    theSelection = new QItemSelectionModel(theModel);// Select the model
Copy the code
  • 3. Set up the model
ui->TableView->setModel(theModel);// Data model
ui->TableView->setSelectionModel(theSelection);// Select the model
Copy the code
  • 4. Populate the data to create a database connection and open the database
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"."connection1");
 db.setDatabaseName("/Users/mac/Qt/test.db");
 db.open(a);Copy the code

fill

QSqlDatabase db = QSqlDatabase::database("connection1");// Associate the database
QSqlQuery query(db);// Specify the database
query("SELECT id,name,score FROM stundet");// Query the database
int queryRow = 0;// Count the number of rows in the query
while(query.next()){
	queryRow++;
}
query.seek(- 1);// Resets the position of the query to one bit before the first data
if(queryRow > 0) {// When the result is queried, it will be populated
	// Set the number of rows and columns in the database
	theModel->setRowCount(queryRow);
	theModel->setColumnCount(8);
// Set the table header
	thetModel->setHeaderData(0, Qt::Horizontal, QStringLiteral("id"));	// Set the table header. If not, use the default table header in the database
	theModel->setHeaderData(1, Qt::Horizontal, QStringLiteral("Name"));
	theModel->setHeaderData(2, Qt::Horizontal, QStringLiteral("Business score"));
	queryRow = 0;// resets the number of rows to fill
	while(query.next()) {// Get the index of the model
		QModelIndex index = theModel->index(queryRow, 0);
		theModel->setData(index, query.value(0).toInt(), Qt::DisplayRole);
		
		index = theModel->index(row, 1);
        theModel->setData(index, query.value(1).toString(), Qt::DisplayRole);
		
		index = theModel->index(row, 1);
        theModel->setData(index, query.value(1).toDouble(), Qt::DisplayRole);
        queryRow++;/ / line number + 1}}Copy the code

2.1.2 Using the QSqlQueryModel

  • 1. Define the model
    QSqlQueryModel *sqlQueryModel;// Data model
    QItemSelectionModel *theSelection;// Select the model
	
Copy the code
  • 2. Initialize the model to create a database connection and open the database
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"."connection1");
 db.setDatabaseName("/Users/mac/Qt/test.db");
 db.open(a);Copy the code

Initialize the

    QSqlDatabase db = QSqlDatabase::database("connection1");
    sqlQueryModel = new QSqlQueryModel(this);
    theSelection = new QItemSelectionModel(sqlQueryModel);// Initialize the selection model
	 sqlQueryModel->setQuery("SELECT id,name,score FROM stundet");// Initialize the data model
	 // Set the table header
	    sqlQueryModel->setHeaderData(0, Qt::Horizontal, tr("id"));
    sqlQueryModel->setHeaderData(1, Qt::Horizontal, tr("Name"));
    sqlQueryModel->setHeaderData(2, Qt::Horizontal, tr("Performance"));	
    // Set the model
    ui->TableView->setModel(sqlQueryModel);
    ui->TableView->setSelectionModel(theSelection); 
Copy the code

2.2 QTableView style design

Hide the leftmost column sort:

ui->TableView->verticalHeader() - >hide(a); ! [Insert picture description here](HTTPS://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8ba2dcbed4af4879ad235513919e46d9~tplv-k3u1fbpfcp-zoom-1.image)
Copy the code

Setting uneditable:

ui->TableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
Copy the code

Interline discoloration:

ui->TableView->setAlternatingRowColors(true);
Copy the code

Radio mode:

ui->TableView->setSelectionMode ( QAbstractItemView::SingleSelection);
Copy the code

Adjust table column width according to control length:

ui->TableView->horizontalHeader() - >setSectionResizeMode(QHeaderView::Stretch);
Copy the code

Adjust the column width adaptively to the content

    ui->theTableView->horizontalHeader() - >setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->theTableView->verticalHeader() - >setSectionResizeMode(QHeaderView::Fixed);
    ui->theTableView->horizontalHeader() - >setMinimumSectionSize(102); / Minimum widthCopy the code

Settings highlighted when selected

    ui->TableView->horizontalHeader() - >setHighlightSections(true);
Copy the code

Set the proxy to a control, such as a QComboBox control:

QComboBox *tempComboBox = new QComboBox(this);
tempComboBox->addItem("good");
tempComboBox->addItem("bad");
ui->TableView->setIndexWidget(theModel->index(row, 3),  tempComboBox);
Copy the code

To get a value from a QComBox, use:

static_cast<QComboBox *>(ui->TableView->indexWidget(theModel->index(i, 3))) - >currentText(a)Copy the code

2.3 QTableView event

2.3.1 Select events triggered by the model

    // Select the item
    connect(theSelection, &QItemSelectionModel::currentChanged,
            this, &MainWindow::onCurrentChanged);
    // Select the index
    connect(theSelection, &QItemSelectionModel::selectionChanged,
            this, &MainWindow::updateSelection);
Copy the code
void MainWindow::onCurrentChanged(const QModelIndex &current, const QModelIndex &previous){
//....} ` ` `cpp
void MainWindow::updateSelection(const QItemSelection &selected, const QItemSelection &deselected){
/ /...
}
Copy the code

2.3.2 Events triggered by clicking the model

Double click on the

    connect(ui->TableView, &QTableView::doubleClicked,
            this, &QueryDialog::chooseQuery, Qt::UniqueConnection);// &queryDialog ::chooseQuery is a custom slot function
Copy the code

Click:

        connect(ui->newOrderTableView, &QTableView::clicked,
                [=](){
			/ / slot function
        });
Copy the code

2.3.3 Events triggered by the agent

2.3.3.1 use setIndexWidget

The unit is the effect of Method 1, delete to the effect of Method 2:

Method 1: used for multiple controls to repeat the same function, transfer parameters

QComboBox *tempComboBox = new QComboBox(this);
tempComboBox->addItem("good");// Personalize the wear parameters
tempComboBox->addItem("bad");
// Associated events
  connect(tempComboBox, &QComboBox::currentTextChanged,
                  this, &MainWindow::changeQComboBoxData);
ui->TableView->setIndexWidget(theModel->index(row, 3),  tempComboBox);
Copy the code

Method two: used for multiple controls to repeat the same function, without passing parameters inherited rewrite button

class DeleteToolButton : public QToolButton{
     Q_OBJECT
public:
    DeleteToolButton(QObject *parent = nullptr);
};
Copy the code
DeleteToolButton::DeleteToolButton(QObject *parent)
{
    this->setIcon(QIcon(":/Image/sc.png"));
    this->setStyleSheet("background: transparent");
}
Copy the code

Add and associate events

    ui->TableView->setIndexWidget(goodsListModel->index(row, 7), new DeleteToolButton(this));
	//
    QList<QToolButton*> deleteToolButtonList =
            this->ui->goodsListTableView->findChildren<QToolButton*>();
    for(auto it = deleteToolButtonList.begin(a); it ! = deleteToolButtonList.end(a); it++){connect((*it), &QAbstractButton::clicked, this, &MainWindow::deleteRowData, Qt::UniqueConnection);
    }
Copy the code
2.3.3.1 use QStyledItemDelegate

Price as effect

use

QDoubleSpinDelegate     SpinDelegate;
ui->TableView->setItemDelegateForColumn(5, &SpinDelegate);
Copy the code

create

class QDoubleSpinDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    QDoubleSpinDelegate(QObject *parent=0);

A custom proxy component must inherit the following four functions

// Create the edit component
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const Q_DECL_OVERRIDE;

// Get the data from the data model and display it in the proxy component
    void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;

// Save the proxy component's data to the data model
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const Q_DECL_OVERRIDE;

// Update the size of the agent editing component
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
                              const QModelIndex &index) const Q_DECL_OVERRIDE;
};
Copy the code

QWidget *QDoubleSpinDelegate::createEditor(QWidget *parent,
   const QStyleOptionViewItem &option, const QModelIndex &index) const
{ // Create the proxy edit component
    Q_UNUSED(option);
    Q_UNUSED(index);

    QDoubleSpinBox *editor = new QDoubleSpinBox(parent);
    editor->setFrame(false);
    editor->setMinimum(0);
    editor->setDecimals(2);
    editor->setMaximum(10000);

    return editor;  // Return to the editor
}

void QDoubleSpinDelegate::setEditorData(QWidget *editor,
                      const QModelIndex &index) const
{// Get the data from the data model and display it in the proxy component
// Get the data of the unit pointed to by the model index of the data model
    int value = index.model() - >data(index, Qt::EditRole).toInt(a); QSpinBox *spinBox =static_cast<QSpinBox*>(editor);  // Cast
    spinBox->setValue(value); // Set the value of the editor
}

void QDoubleSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{ // Save the proxy component's data to the data model
    QSpinBox *spinBox = static_cast<QSpinBox*>(editor); // Cast
    spinBox->interpretText(a);// Interpret the data and trigger the signal if the data is modified
    int value = spinBox->value(a);// Get the value of spinBox

    model->setData(index, value, Qt::EditRole); // Update to the data model
}

void QDoubleSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{ // Set the component size
    Q_UNUSED(index);
    editor->setGeometry(option.rect);
}
Copy the code

Read-only proxy:

class ReadOnlyDelegate: public QItemDelegate
{

public:
    ReadOnlyDelegate(QWidget *parent = NULL) :QItemDelegate(parent)
    {}

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override //final
    {
        Q_UNUSED(parent)
        Q_UNUSED(option)
        Q_UNUSED(index)
        return NULL; }};Copy the code