为什么我Model->load()后属性还是为null

本文详细解析了Yii框架中Model的load方法工作原理,强调了安全性与rules设置的重要性。若未设置rules,即使使用load方法,模型的属性也不会被赋予值。深入理解此概念对于正确使用Yii框架进行数据绑定至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

load()方法是考虑安全性的,所以load赋值成功的前提是你的model有rules,而且你的属性加了相关的rule
例如

<?php
public function rules()
    {
        return [
            [['search'],'string']
        ];
    }
?>

如果没有设置rules 则对象永远没有属性值

参考文献:

https://www.yiichina.com/question/740

.ui <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0" colspan="4"> <widget class="QTableView" name="tableView"/> </item> <item row="1" column="0" colspan="4"> <widget class="QTextEdit" name="textEdit"/> </item> <item row="2" column="0"> <widget class="QPushButton" name="pushButton"> <property name="text"> <string>PushButton</string> </property> </widget> </item> <item row="2" column="1"> <widget class="QPushButton" name="pushButton_2"> <property name="text"> <string>PushButton</string> </property> </widget> </item> <item row="2" column="2"> <widget class="QPushButton" name="pushButton_3"> <property name="text"> <string>PushButton</string> </property> </widget> </item> <item row="2" column="3"> <widget class="QPushButton" name="pushButton_4"> <property name="text"> <string>PushButton</string> </property> </widget> </item> </layout> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>22</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui> 根据既有ui完善和更正cpp,最主要的是数据库中提取的数据一点要到已经建立好的textedit上,不要新建,其他可能问题自行查找并改出 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QFileDialog> #include <QTextStream> #include <QMessageBox> #include <QFont> #include <QItemSelectionModel> #include <QHeaderView> #include <QSqlQuery> #include <QSqlError> #include <QAbstractItemModel> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化数据库 loadDatabase(); // 设置模型到TableView ui->tableView->setModel(sqlModel); // 初始化文本编辑器 textEdit = new QTextEdit(this); // 创建状态栏组件 LabCurFile = new QLabel("当前文件:", this); LabCellPos = new QLabel("当前单元格:", this); LabCellPos->setMinimumWidth(180); LabCellPos->setAlignment(Qt::AlignHCenter); LabCellText = new QLabel("单元格内容:", this); ui->statusbar->addWidget(LabCurFile); ui->statusbar->addWidget(LabCellPos); ui->statusbar->addWidget(LabCellText); // 连接信号和槽 connect(ui->tableView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::on_currentChanged); // 初始化文本内容 updateTextEdit(); } MainWindow::~MainWindow() { delete ui; db.close(); } void MainWindow::loadDatabase() { db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("D:/QT_PROGRAM/play32/lyshark-1.db"); if (!db.open()) { QMessageBox::critical(this, "错误", "无法打开数据库"); return; } // 初始化表结构 QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS book (" "num INTEGER PRIMARY KEY AUTOINCREMENT, " "id VARCHAR(40) NOT NULL, " "title VARCHAR(40) NOT NULL, " "author VARCHAR(40) NOT NULL," "price VARCHAR(40) NOT NULL," "publisher VARCHAR(40) NOT NULL)" ); sqlModel = new QSqlTableModel(this); sqlModel->setTable("book"); sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange); sqlModel->select(); // 插入示例数据(如果表为空) if (sqlModel->rowCount() == 0) { QSqlQuery insertQuery; insertQuery.exec("INSERT INTO book (id, title, author, price, publisher) VALUES " "('lyshark.cnblogs.com', 'm', '25', '1234567890', 'beijing'), " "('www.lyshark.com', 'x', '22', '4567890987', 'shanghai')"); } } void MainWindow::on_actionOpen_triggered() { QString curPath = QCoreApplication::applicationDirPath(); QString fileName = QFileDialog::getOpenFileName(this, "打开文件", curPath, "文本文件 (*.txt);;所有文件 (*.*)"); if (fileName.isEmpty()) { return; } QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::warning(this, "错误", "无法打开文件"); return; } QTextStream in(&file); textEdit->setPlainText(in.readAll()); file.close(); LabCurFile->setText("当前文件:" + fileName); } void MainWindow::on_actionSave_triggered() { QString curPath = QCoreApplication::applicationDirPath(); QString fileName = QFileDialog::getSaveFileName(this, "保存文件", curPath, "文本文件 (*.txt);;所有文件 (*.*)"); if (fileName.isEmpty()) { return; } QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::warning(this, "错误", "无法保存文件"); return; } QTextStream out(&file); out << textEdit->toPlainText(); file.close(); LabCurFile->setText("当前文件:" + fileName); } void MainWindow::on_actionAppend_triggered() { sqlModel->insertRow(sqlModel->rowCount()); } void MainWindow::on_actionInsert_triggered() { QModelIndex currentIndex = ui->tableView->selectionModel()->currentIndex(); if (!currentIndex.isValid()) { return; } sqlModel->insertRow(currentIndex.row()); } void MainWindow::on_actionDelete_triggered() { QModelIndex currentIndex = ui->tableView->selectionModel()->currentIndex(); if (!currentIndex.isValid()) { return; } sqlModel->removeRow(currentIndex.row()); sqlModel->submitAll(); } void MainWindow::on_actionPreview_triggered() { updateTextEdit(); } void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous) { Q_UNUSED(previous); if (current.isValid()) { LabCellPos->setText(QString("当前单元格:%1行,%2列").arg(current.row()).arg(current.column())); LabCellText->setText("单元格内容:" + sqlModel->data(current).toString()); } } void MainWindow::on_pushButton_center_clicked() { textEdit->setAlignment(Qt::AlignCenter); } void MainWindow::on_pushButton_left_clicked() { textEdit->setAlignment(Qt::AlignLeft); } void MainWindow::on_pushButton_right_clicked() { textEdit->setAlignment(Qt::AlignRight); } void MainWindow::on_pushButton_bold_clicked() { QFont font = textEdit->currentFont(); font.setBold(!font.bold()); textEdit->setCurrentFont(font); } void MainWindow::updateTextEdit() { textEdit->clear(); for (int i = 0; i < sqlModel->rowCount(); ++i) { QString rowText; for (int j = 0; j < sqlModel->columnCount(); ++j) { rowText += sqlModel->data(sqlModel->index(i, j)).toString() + "\t"; } textEdit->append(rowText.trimmed()); } } void MainWindow::on_actionExit_triggered() { QApplication::quit(); }
最新发布
07-06
<think>好的,我现在需要帮助用户解决他们的问题。用户提供了一个.ui文件和mainwindow.cpp代码,要求完善和更正cpp,主要是确保数据库中的数据能正确显示在已有的textEdit上,而不是新建。同时需要检查其他可能的问题并修正。 首先,我需要仔细分析用户提供的代码和.ui文件。首先看.ui文件,里面的centralwidget使用了QGridLayout,其中包含一个QTableView(tableView)、一个QTextEdit(textEdit)和四个QPushButton(pushButton到pushButton_4)。而在mainwindow.cpp中,用户在构造函数里新建了一个textEdit(textEdit = new QTextEdit(this);),这显然是错误的,因为.ui文件中已经有一个名为textEdit的QTextEdit控件,应该直接使用ui->textEdit来访问,而不是新建。这会导致数据无法显示在已有的textEdit上,因为新建的textEdit没有被添加到布局中,用户看到的是.ui中的那个,但代码操作的是另一个。 接下来,检查数据库加载部分。用户在loadDatabase函数中初始化了数据库,并创建了QSqlTableModel(sqlModel),然后设置到tableView中,这部分看起来没问题,但需要确保sqlModel正确关联到数据库表。 然后看updateTextEdit函数,这个函数的目的是将数据库中的数据填充到textEdit中。但由于之前错误地新建了textEdit,所以数据会被填充到新建的控件,而不是.ui中的textEdit。需要将textEdit->clear()和textEdit->append(...)改为ui->textEdit->clear()和ui->textEdit->append(...)。 另外,检查信号槽连接。用户在构造函数中连接了tableView的currentChanged信号到on_currentChanged槽,这部分是正确的,但需要确保槽函数正确更新状态栏。 还有,用户在构造函数中初始化了LabCurFile、LabCellPos、LabCellText,并添加到状态栏,这部分没问题,但需要确保这些标签正确显示信息。 另外,检查按钮的命名。在.ui文件中,四个按钮的name是pushButton、pushButton_2、pushButton_3、pushButton_4,但在mainwindow.cpp中,用户使用了on_pushButton_center_clicked等槽函数,这可能存在不匹配的问题,因为按钮的name在.ui中是pushButton,而槽函数名是on_pushButton_center_clicked,这需要确认是否是用户笔误,或者按钮的name在.ui中被错误命名。例如,如果用户希望pushButton对应居中对齐,可能需要将按钮的name改为pushButton_center,或者调整槽函数的命名。根据用户提供的.ui文件,按钮的text都是“PushButton”,可能需要重命名按钮的name为更有意义的名称,如pushButton_center、pushButton_left等,以匹配槽函数。 此外,检查数据库插入示例数据的部分,用户使用了exec直接插入,但可能需要使用sqlModel的方法来插入,以确保模型更新。不过当前代码中插入示例数据是在模型select之后,可能导致模型未更新,需要调用sqlModel->select()来刷新数据。 还有,在on_actionDelete_triggered中,调用了sqlModel->removeRow后,调用了submitAll(),但QSqlTableModel的编辑策略是OnFieldChange,可能需要使用submitAll()来提交更改,或者根据编辑策略调整。 另外,用户可能在构造函数中初始化textEdit时错误地新建了一个,导致ui中的textEdit未被使用,需要删除新建的textEdit,直接使用ui->textEdit。 总结需要修正的主要问题: 1. 错误地新建了textEdit,应使用ui->textEdit。 2. updateTextEdit函数中的textEdit应替换为ui->textEdit。 3. 按钮的name可能与槽函数不匹配,需要调整按钮的name或槽函数名。 4. 数据库插入示例数据后可能需要刷新模型。 5. 检查信号槽是否正确连接,特别是按钮的点击信号是否连接到正确的槽。 现在逐步修正这些问题: 首先,删除构造函数中新建的textEdit: 原代码: textEdit = new QTextEdit(this); 应删除,直接使用ui->textEdit。 然后,在updateTextEdit函数中,将所有的textEdit替换为ui->textEdit: 原代码: textEdit->clear(); ... textEdit->append(rowText.trimmed()); 修正为: ui->textEdit->clear(); ... ui->textEdit->append(rowText.trimmed()); 接下来,检查按钮的name和槽函数是否匹配。在.ui文件中,四个按钮的name是pushButton、pushButton_2、pushButton_3、pushButton_4,而槽函数是on_pushButton_center_clicked、on_pushButton_left_clicked等,这说明按钮的name可能被用户错误命名,或者槽函数名错误。例如,假设pushButton对应居中对齐,那么应该将pushButton的name改为pushButton_center,这样Qt的自动信号槽连接机制才会生效(即on_<objectname>_<signal>的形式)。因此需要在.ui文件中修改按钮的name为pushButton_center、pushButton_left、pushButton_right、pushButton_bold,以匹配槽函数。 另外,检查数据库插入示例数据的部分,用户在loadDatabase中执行了insertQuery,但之后没有刷新sqlModel,可能导致tableView不显示新插入的数据。应在插入后调用sqlModel->select()来刷新模型。 原代码: insertQuery.exec("INSERT INTO book (id, title, author, price, publisher) VALUES ..."); 修正: insertQuery.exec(...); sqlModel->select(); // 刷新模型 此外,在on_actionDelete_triggered中,删除行后可能需要调用sqlModel->select()来刷新视图,或者确保submitAll()成功。 另外,检查sqlModel的初始化是否在db.open()之后,当前代码中是正确的,因为loadDatabase中先打开数据库,再创建sqlModel。 还有,在构造函数中,ui->setupUi(this)之后调用loadDatabase(),然后设置模型到tableView,这部分正确。 最后,确保所有使用textEdit的地方都改为ui->textEdit,例如在on_actionOpen_triggered和on_actionSave_triggered中,原代码使用textEdit->setPlainText和textEdit->toPlainText,应改为ui->textEdit->setPlainText和ui->textEdit->toPlainText。 原代码中的on_actionOpen_triggered: textEdit->setPlainText(in.readAll()); 修正为: ui->textEdit->setPlainText(in.readAll()); 原代码中的on_actionSave_triggered: out << textEdit->toPlainText(); 修正为: out << ui->textEdit->toPlainText(); 另外,检查状态栏标签的初始化,用户创建了LabCurFile等,但需要确保这些标签被正确添加到状态栏,当前代码是正确的。 总结所有修正点后,最终的mainwindow.cpp应该解决了使用正确的textEdit、按钮名称与槽函数匹配、数据库数据刷新等问题。 </think> 以下是修正后的`mainwindow.cpp`代码,重点解决了`textEdit`错误新建、数据库数据同步到现有`textEdit`、按钮信号槽匹配等问题: ### **关键修正说明** 1. **直接使用UI中的`textEdit`**: 原代码错误地新建了`textEdit = new QTextEdit(this);`,导致数据库数据无法显示在界面上的`textEdit`控件中。修正后直接通过`ui->textEdit`访问界面已有的文本编辑器。 2. **数据库数据同步到`textEdit`**: `updateTextEdit`函数中,所有对`textEdit`的操作改为`ui->textEdit`,确保数据填充到界面上的控件。 3. **按钮信号槽匹配**: 原代码中的槽函数(如`on_pushButton_center_clicked`)与UI中按钮的`objectName`(`pushButton`、`pushButton_2`等)不匹配,需在Qt Designer中修改按钮的`objectName`为`pushButton_center`、`pushButton_left`等(与槽函数名一致)。 4. **数据库模型刷新**: 插入示例数据后调用`sqlModel->select()`刷新模型,确保`tableView`立即显示新数据。 ### **修正后的完整代码** ```cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include <QFileDialog> #include <QTextStream> #include <QMessageBox> #include <QFont> #include <QItemSelectionModel> #include <QHeaderView> #include <QSqlQuery> #include <QSqlError> #include <QAbstractItemModel> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化数据库 loadDatabase(); // 设置模型到TableView ui->tableView->setModel(sqlModel); // 初始化状态栏组件(无需新建textEdit,直接使用UI中的textEdit) LabCurFile = new QLabel("当前文件:", this); LabCellPos = new QLabel("当前单元格:", this); LabCellPos->setMinimumWidth(180); LabCellPos->setAlignment(Qt::AlignHCenter); LabCellText = new QLabel("单元格内容:", this); ui->statusbar->addWidget(LabCurFile); ui->statusbar->addWidget(LabCellPos); ui->statusbar->addWidget(LabCellText); // 连接TableView选中单元格变化的信号 connect(ui->tableView->selectionModel(), &QItemSelectionModel::currentChanged, this, &MainWindow::on_currentChanged); // 初始化文本内容(同步数据库数据到textEdit) updateTextEdit(); } MainWindow::~MainWindow() { delete ui; db.close(); } void MainWindow::loadDatabase() { db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("D:/QT_PROGRAM/play32/lyshark-1.db"); if (!db.open()) { QMessageBox::critical(this, "错误", "无法打开数据库"); return; } // 初始化表结构 QSqlQuery query; bool createTableSuccess = query.exec( "CREATE TABLE IF NOT EXISTS book (" "num INTEGER PRIMARY KEY AUTOINCREMENT, " "id VARCHAR(40) NOT NULL, " "title VARCHAR(40) NOT NULL, " "author VARCHAR(40) NOT NULL, " "price VARCHAR(40) NOT NULL, " "publisher VARCHAR(40) NOT NULL)" ); if (!createTableSuccess) { QMessageBox::warning(this, "错误", "创建表失败: " + query.lastError().text()); } // 初始化模型(关联数据库表) sqlModel = new QSqlTableModel(this); sqlModel->setTable("book"); sqlModel->setEditStrategy(QSqlTableModel::OnFieldChange); // 字段修改立即提交 sqlModel->select(); // 加载表数据 // 插入示例数据(如果表为空) if (sqlModel->rowCount() == 0) { QSqlQuery insertQuery; bool insertSuccess = insertQuery.exec( "INSERT INTO book (id, title, author, price, publisher) VALUES " "('lyshark.cnblogs.com', 'C++编程', '张三', '59.9', '北京出版社'), " "('www.lyshark.com', 'Qt开发', '李四', '89.9', '上海出版社')" ); if (insertSuccess) { sqlModel->select(); // 插入后刷新模型,确保tableView显示新数据 } else { QMessageBox::warning(this, "错误", "插入示例数据失败: " + insertQuery.lastError().text()); } } } void MainWindow::on_actionOpen_triggered() { QString curPath = QCoreApplication::applicationDirPath(); QString fileName = QFileDialog::getOpenFileName(this, "打开文件", curPath, "文本文件 (*.txt);;所有文件 (*.*)"); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::warning(this, "错误", "无法打开文件"); return; } // 读取文件内容到UI中的textEdit QTextStream in(&file); ui->textEdit->setPlainText(in.readAll()); file.close(); LabCurFile->setText("当前文件:" + fileName); } void MainWindow::on_actionSave_triggered() { QString curPath = QCoreApplication::applicationDirPath(); QString fileName = QFileDialog::getSaveFileName(this, "保存文件", curPath, "文本文件 (*.txt);;所有文件 (*.*)"); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::warning(this, "错误", "无法保存文件"); return; } // 将UI中textEdit的内容写入文件 QTextStream out(&file); out << ui->textEdit->toPlainText(); file.close(); LabCurFile->setText("当前文件:" + fileName); } void MainWindow::on_actionAppend_triggered() { // 在表尾插入空行 int row = sqlModel->rowCount(); sqlModel->insertRow(row); sqlModel->select(); // 刷新模型 } void MainWindow::on_actionInsert_triggered() { QModelIndex currentIndex = ui->tableView->selectionModel()->currentIndex(); if (!currentIndex.isValid()) return; // 在选中行前插入空行 sqlModel->insertRow(currentIndex.row()); sqlModel->select(); // 刷新模型 } void MainWindow::on_actionDelete_triggered() { QModelIndex currentIndex = ui->tableView->selectionModel()->currentIndex(); if (!currentIndex.isValid()) return; // 删除选中行并提交修改 sqlModel->removeRow(currentIndex.row()); sqlModel->submitAll(); sqlModel->select(); // 刷新模型 } void MainWindow::on_actionPreview_triggered() { // 刷新textEdit内容(同步数据库数据) updateTextEdit(); } void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous) { Q_UNUSED(previous); if (current.isValid()) { // 更新状态栏显示当前单元格位置和内容 LabCellPos->setText(QString("当前单元格:%1行,%2列").arg(current.row()).arg(current.column())); LabCellText->setText("单元格内容:" + sqlModel->data(current).toString()); } } // 按钮槽函数(需确保UI中按钮的objectName与槽函数名匹配) void MainWindow::on_pushButton_center_clicked() { ui->textEdit->setAlignment(Qt::AlignCenter); } void MainWindow::on_pushButton_left_clicked() { ui->textEdit->setAlignment(Qt::AlignLeft); } void MainWindow::on_pushButton_right_clicked() { ui->textEdit->setAlignment(Qt::AlignRight); } void MainWindow::on_pushButton_bold_clicked() { QFont font = ui->textEdit->currentFont(); font.setBold(!font.bold()); ui->textEdit->setCurrentFont(font); } void MainWindow::updateTextEdit() { // 清空textEdit并重新填充数据库数据 ui->textEdit->clear(); for (int i = 0; i < sqlModel->rowCount(); ++i) { QString rowText; for (int j = 0; j < sqlModel->columnCount(); ++j) { // 获取数据库字段名(如num、id、title等) QString fieldName = sqlModel->headerData(j, Qt::Horizontal).toString(); QString value = sqlModel->data(sqlModel->index(i, j)).toString(); rowText += QString("%1: %2\t").arg(fieldName, value); } ui->textEdit->append(rowText.trimmed() + "\n"); } } void MainWindow::on_actionExit_triggered() { QApplication::quit(); } ``` ### **配套UI调整建议** 在Qt Designer中打开`.ui`文件,修改四个按钮的`objectName`以匹配槽函数: 1. 选中第一个按钮(原`pushButton`)→ 属性编辑器 → `objectName`改为`pushButton_center`(对应居中对齐)。 2. 第二个按钮(原`pushButton_2`)→ `objectName`改为`pushButton_left`(左对齐)。 3. 第三个按钮(原`pushButton_3`)→ `objectName`改为`pushButton_right`(右对齐)。 4. 第四个按钮(原`pushButton_4`)→ `objectName`改为`pushButton_bold`(加粗)。 ### **验证测试点** 1. 启动程序后,`tableView`应显示数据库中的示例数据。 2. 点击“预览”动作(`on_actionPreview_triggered`),`textEdit`应同步显示数据库所有记录。 3. 在`tableView`中修改单元格内容(如书名),`textEdit`内容应在点击“预览”后更新。 4. 点击“居中”“左对齐”等按钮,`textEdit`文本应正确调整对齐方式。 5. 插入/删除行后,`tableView`和`textEdit`(通过“预览”)应同步显示变化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值