我使用的是QSqlTableModel和QTableView查看SQLite数据库表.
我想让表每隔一秒自动刷新一次(它不会是一个非常大的表 - 几百行).我可以这样做 - 就像这样:
QTimer *updateInterval = new QTimer(this);
updateInterval->setInterval(1000);
updateInterval->start();
connect(updateInterval, SIGNAL(timeout()),this, SLOT(update_table()));
...
void MainWindow::update_table()
{
model->select(); //QSqlTableModel*
sqlTable->reset(); //QTableView*
}
Run Code Online (Sandbox Code Playgroud)
但是这会删除我的任何选择,因此选择只持续一秒钟.这很烦人,因为GUI中的另一个窗格取决于所选择的内容.如果未选择任何内容,则会重置为解释启动页面.
然后我尝试了一种有点hacky的方法,它获取所选的行号,重置表,然后选择该行.但这也不起作用,因为所选行可以根据对表的添加来上移或下移.
我知道其他班级都有dataChanged()信号,这是理想的.
你们中的任何人都知道如何刷新表以反映数据库的更改(从命令行使用或程序的其他实例)并保持当前选择?
我知道我可以从当前选择中获取数据,然后在重置后搜索同一行然后重新选择它,但这似乎是一个适得其反的问题.
编辑:当前尝试解决方案:
void MainWindow::update_table()
{
QList<QModelIndex> selection = sqlTable->selectionModel()->selection().indexes();
QList<int> selectedIDs;
bool somethingSelected = true;
for(QList<QModelIndex>::iterator i = selection.begin(); i != selection.end(); ++i){
int col = i->column();
QVariant data = i->data(Qt::DisplayRole);
if(col == 0) {
selectedIDs.append(data.toInt());
}
}
if(selectedIDs.empty()) somethingSelected = false; …Run Code Online (Sandbox Code Playgroud) void MyWindow::initializeModelBySQL(QSqlQueryModel *model,QTableView *table,QString sql){
model = new QSqlQueryModel(this);
model->setQuery(sql);
}
Run Code Online (Sandbox Code Playgroud)
使用此方法,我可以将QSQlQueryModels设置为我的QTableviews.
但是如何根据单元格值将颜色设置为一行?
我正在使用Qt的MySQL驱动程序和32位MinGW Qt.这是有效的:
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setDatabaseName("MyDatabase");
//SETUP
if (db.open) {
QSqlQuery q;
if (q.prepare("SELECT id FROM Things WHERE parent_id = :pid")) {
q.bindValue(":pid", 1);
qDebug() << boundValues();
if (q.exec) {
//DO STUFF
} } }
Run Code Online (Sandbox Code Playgroud)
但是现在我正在使用64位MSVS Qt,我需要使用MySQL ODBC Connector.我已经设置并更改了代码以反映:
QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
db.setDatabaseName("Driver={MySQL ODBC 8.0 Unicode Driver};DATABASE=MyDatabase;");
Run Code Online (Sandbox Code Playgroud)
这就是我所做的一切.没有WHERE子句的SELECT语句按预期工作,我可以像以前一样通过QSqlTableModel操作数据库.
这只是绑定停止工作......我的意思是绑定值在那里,qDebug返回:
QMap((":pid",QVariant(int,1)))
但是现在查询在exec之后没有返回任何行; 但也没有错误...这也有效:
q.prepare(QString("SELECT id FROM Things WHERE parent_id = '%1'").arg(1))
Run Code Online (Sandbox Code Playgroud)
有帮助吗?
我想知道在使用QSqlTableModel :: setFilter时是否有办法防止SQL注入,并且没有对WHERE子句条件进行验证.
我不想使用QSqlQueryModel,因为我需要编辑功能.
这是这个问题的后续行动.在那里,我们创建了一个可编辑的QSqlQueryModel子类,用于复杂查询.现在我需要添加像QTableModel的setEditStrategy这样的功能,这样我就可以缓存所有更改并使用按钮接受或还原它们.PyQt显然不允许多重继承,我找不到足够的文档来在我的自定义模型中重新实现这个方法,因此这里有一个问题:
如何在可编辑的QSqlQueryModel中重新实现QSqlTableModel.setEditStragety(或类似的东西),包括RevertAll()和SubmitAll()?
这是一个CVME :(我已经评论了我希望工作的Example类的部分内容)
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtSql import QSqlDatabase, QSqlQuery, QSqlQueryModel, QSqlTableModel
from PyQt5.QtWidgets import QApplication, QTableView, QWidget, QGridLayout
from PyQt5.Qt import QPushButton
db_file = "test.db"
def create_connection(file_path):
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(file_path)
if not db.open():
print("Cannot establish a database connection to {}!".format(file_path))
return False
return True
def fill_tables():
q = QSqlQuery()
q.exec_("DROP TABLE IF EXISTS Manufacturers;")
q.exec_("CREATE TABLE Manufacturers (Company TEXT, Country TEXT);")
q.exec_("INSERT INTO Manufacturers VALUES ('VW', 'Germany');")
q.exec_("INSERT INTO Manufacturers VALUES …Run Code Online (Sandbox Code Playgroud) 我有一个QTableView由QSqlRelationalTableModel.
有一个列引用另一个表,因此当我编辑/创建一行时,该列的编辑器将从QCombobox相关表中获取其数据。问题是我想使用相关表上的一些预定义WHERE来过滤数据。
例子:
表格:
Person:
id, name, job_id;
Job:
id, title, salary
Run Code Online (Sandbox Code Playgroud)
我想要的是类似的东西
model.setRelation(3,QSqlRelation("Job", "id", "title", "WHERE salary > 50000"))
Run Code Online (Sandbox Code Playgroud)
这样 QCombobox 将只包含薪资 > 5000 的职位。
我无法按照SO 问题QSqlQueryModel中的建议使用- 我仍然需要用户能够添加新数据或编辑现有数据。
似乎10 年前就有人通过调整 QT 源代码成功实现了这一点,但我的 C++ 很糟糕,所以我无法很好地理解它。
可能的解决方案:
我想到的第一件事是实现我自己的QSqlRelationalDelagate并填充QCombobox并createEditor在 中设置适当的值setModelData。我会尝试自己做并在这里报告结果。但对我来说似乎不太干净。
最好的方法是扩展QSqlRelation或 的功能QSqlRelationalTableModel,但其文档似乎不是很清楚。因此,对于经验丰富的 QT/PyQT 开发人员来说,真正的问题是:如何以这种方式解决问题?
更新
QCombobox因此,过滤掉委托中的内容是可行的createEditor,但每次创建编辑器时都需要进行数据库查询,这似乎有点不对劲。而且过滤后处理新索引也很混乱。但我仍然想知道解决问题的第二种方法。
我的类DataTable派生自QAbstractTableModel.它在内部使用QSqlTableModel对象从db表中获取数据.它表示db中每一行的记录(它执行的操作更多,但记录计数始终是db表中的行数).
使用MySql,我的DataTable :: rowCount()实现只调用QSqlTableModel上的rowCount(),这很好用.
现在使用SQLite,如果db表中有超过256行,Qt的SQLite驱动程序返回的行数为256,因此我的DataTable类也返回256 - 这是错误的.该文件告诉我打电话while (sql_model->canFetchMore()) sql_model->fetchMore();.在创建内部QSqlTableModel之后立即调用fetchMore()实际上会导致以下rowCount()调用返回正确的值.但是一旦数据库中的某些内容发生了变化(我的类将在QSqlTableModel上调用insertRow()或setData()),下一个QSqlTableModel :: rowCount()调用将再次返回256.
数据库仅由我的类修改,而我的类又使用该特定的QSqlTableModel对象(或使用我的DataTable作为模型的视图可以更新某些内容).因此,没有其他进程可以将行插入数据库.
那么我的DataTable类何时应该为rowCount()调用fetchMore()以始终返回实际的行数?
我认为我的类应该将QSqlTableModel发出的一些信号连接到一个调用fetchMore()的插槽,虽然我不确定这是否是正确/可靠的方法呢?
更新:
这里有一些代码来演示基本问题.
QSqlTableModel *model = new QSqlTableModel(0, database); //QSqlDatabase
model->setTable("tablename");
qDebug() << "0 row count" << model->rowCount(); //0 row count 0
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
qDebug() << "1 row count" << model->rowCount(); //1 row count 256
while (model->canFetchMore()) model->fetchMore();
qDebug() << "2 row count" << model->rowCount(); //2 row count 1520
//... other methods ...
model->setData(model->index(0, 0), "TEST");
model->submitAll();
qDebug() << "3 row …Run Code Online (Sandbox Code Playgroud) 您好,我正在使用 QTableView 使用 qsqltablemodel 显示 sql 表中的数据,如下所示:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
model = new QSqlTableModel(this);
model->setTable("staging");
model->select();
model->setHeaderData(0, Qt::Vertical, tr("ID"));
model->setHeaderData(1, Qt::Vertical, tr("Region"));
model->setHeaderData(2, Qt::Vertical, tr("T1"));
model->setHeaderData(3, Qt::Vertical, tr("N1"));
model->setHeaderData(4, Qt::Vertical, tr("M1"));
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableView->setModel(model);
ui->tableView->showRow(1);
ui->tableView->resizeColumnsToContents();
}
Run Code Online (Sandbox Code Playgroud)
我只想以这样的视图显示表格,即列显示为行,行显示为列。我搜索过谷歌等,但找不到任何简单的解决方案。提到了代理模型,但我不确定如何使用 QSqltablemodel 来实现它,在本例中它不使用数据方法,而是使用 model->select() 语句来立即填充整个模型。任何指导将不胜感激。
我的数据库:

我的代码:
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("sqlite.db");
db.open();
QSqlQuery query;
query.exec("SELECT * from Expenses");
QSqlTableModel *model = new QSqlTableModel(0, db);
model->setTable("Expenses");
model->select();
Run Code Online (Sandbox Code Playgroud)
如何获得“ 2014年1月”的TOTAL值?即“ 1”。
当要编辑一行时,索引会传递到编辑对话框中。
编辑工作正常。
当我想添加一行时,我不会将索引传递给对话构造函数,因此它知道应该添加新行。
这是对对话框按钮做出反应的函数代码
void DialogAddCl::on_buttonBox_clicked(QAbstractButton *button)
{
// prepare
m->database().transaction();
QString debugstr;
auto chi4 = ui->buttonBox->buttonRole(button);
int rowCount = m->rowCount();
switch (chi4) {
case QDialogButtonBox::AcceptRole:
if (!ind->isValid())
// insert
if (!m->insertRow(rowCount, *ind))
{
QMessageBox::critical (this, "Error inserting into model", m->lastError().text(), QMessageBox::Cancel);
break;
}
else
{
m->setData(m->index(rowCount, 0), rowCount+1);
}
else
{
// update
rowCount = ind->row();
}
m->setData(m->index(rowCount, 1), ui->name->text());
m->setData(m->index(rowCount, 2), ui->addr->text());
// 12 other setData() calls
if (m->submitAll())
{
m->database().commit();
}
else
{
// rollback if error …Run Code Online (Sandbox Code Playgroud) 我正在学习 PyQt5 框架并尝试构建一个 QListView 项目,每个项目前面都有一个复选框。我读过的大多数示例都没有展示如何使用 QSqlTableModel 来实现这一点。有人可以指出我正确的方向吗?
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("./Data/mydbase.db")
db.open()
model = QSqlTableModel()
model.setTable("labdata")
model.setSort(1,0)
model.select()
while model.canFetchMore():
model.fetchMore()
self.ui.lst_LabData.setModel(model)
self.ui.lst_LabData.setModelColumn(1)
self.ui.lst_LabData.show()
Run Code Online (Sandbox Code Playgroud) 我需要交换 QSqlRelationalTableModel 的行和列。经过大量搜索后,我编写了一个小代理模型来翻转行和列。
它正在部分发挥作用。表中的关系已解决并显示,但选择它们的保管箱丢失了。另外,我如何让他们更新?
这是一个重现该行为的独立脚本。
我的错误在哪里?我强烈怀疑它与模型的信号和插槽有关,但我没有找到任何暗示哪些信号和插槽以及如何重新实现它们。
还有另一种更简单的方法来交换行和列吗?
编辑:澄清委托模型并不完全不起作用,它只是部分起作用。
from PySide import QtCore, QtGui, QtSql
from PySide.QtCore import Qt, QModelIndex
from PySide.QtGui import QAbstractProxyModel, QWidget, QHBoxLayout, QTableView
from PySide.QtSql import QSqlRelationalDelegate
class FlipProxyModel(QAbstractProxyModel):
def __init__(self, parent=None):
super(FlipProxyModel, self).__init__(parent)
def mapFromSource(self, index):
return self.createIndex(index.column(), index.row())
def mapToSource(self, index):
return self.sourceModel().index(index.column(), index.row(), QModelIndex())
def columnCount(self, parent):
return self.sourceModel().rowCount(QModelIndex())
def rowCount(self, parent):
return self.sourceModel().columnCount(QModelIndex())
def index(self, row, column, parent):
return self.createIndex(row, column)
def parent(self, index):
# tables have no parent object so return empty …Run Code Online (Sandbox Code Playgroud) 我需要通过从 QSqlTableModel 对象检索数据来填充 QTableView。我使用以下命令来连接到 sql server 数据库:
\n\nQSqlDatabase db = QSqlDatabase::addDatabase("QODBC");\nQString connectionTemplate = "DRIVER={SQL Native Client};SERVER=%1;DATABASE=%2;Uid=username;Pwd=password;Trusted_Connection=Yes;";\nQString connectionString = connectionTemplate.arg("localhost").arg("mydb");\ndb.setDatabaseName(connectionString);\nRun Code Online (Sandbox Code Playgroud)\n\n我通过 QSqlDatabase 类中的 isValid() 和 open() 方法验证数据库连接。我还可以正确地从数据库表中查询。\xd9\x8d 到目前为止一切都很好。但是当我使用以下命令时出现问题:
\n\nQSqlTableModel* model = new QSqlTableModel(parent,db);\nmodel->setTable("mytable");\nqDebug() << model->lastError().text(); // the error message is printed on consul.\nRun Code Online (Sandbox Code Playgroud)\n\nsetTable 方法不起作用并导致错误:无法找到表 \\"mytable\\"。
\nqsqltablemodel ×13
qt ×9
c++ ×4
pyqt ×4
pyqt5 ×3
python ×3
qsqldatabase ×3
qtableview ×2
sqlite ×2
database ×1
model-view ×1
mysql ×1
odbc ×1
pyside ×1
qsqlquery ×1
qt4 ×1
qt5 ×1
qtsql ×1