I made PyQt5 APP which create SQlite3 DB and show data from it in QTableView widget. I have a problem with editing rows in a widget. There are 3 buttons "Add", "Change" and "Delete" that should delete, modify and add new rows to the widget, as well as edit the database itself, but the buttons do not work properly.
"Add" button - after clicking add button, when all new data inputted and Enter clicked, all values is gone and "!" symbol is showing. I need press Add button, input new data in cells, click Enter and all data must save in SQL DB and displayed in QTableView widget in live time.
"Change" button - when change clicked and Enter pressed after cell editing, all data gone. All data must be save in real time is SQL DB after change button press.
3)"Delete" button - this button don't delete row. There is no error, no any answer from app.
How to program the buttons correctly ? Do I need to use a delegate? Which programming approach is more preferable when working with a graphical interface and SQL database?
I made a reproducible example. At startup, a database with 1 table and 2 rows will be created.
import sys, os, sqlite3
from datetime import datetime
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtSql import *
from PyQt5.QtCore import *
CONFIG_NAME = 'config.ini'
DB_NAME = 'nsi.db'
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__()
self.window_pref()
self.show_widgets()
def window_pref(self):
self.setWindowTitle('PyQt5 APP')
self.def_width = 800
self.def_height = 400
self.def_size = self.setMinimumSize(self.def_width, self.def_height)
def show_widgets(self):
self.createConnection()
self.fillDB()
self.setupMainWidgets()
def createConnection(self):
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(DB_NAME)
if not db.open():
QMessageBox.warning(self, 'PyQt5 APP',
'Error:{}'.format(db.lastError().text()))
sys.exit(1)
def fillDB(self):
query = QSqlQuery()
query.exec_("""\
CREATE TABLE sprav (
id_nsi INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
nsi_name TEXT UNIQUE NOT NULL,
file_date TEXT NOT NULL,
file_name TEXT NOT NULL)
""")
query.prepare("""\
INSERT INTO sprav (nsi_name, file_date, file_name)VALUES (?, ?, ?)
""")
sample_list = (('nsi1', 'january', 'file1'), ('nsi2', 'may', 'file2'))
for i in sample_list:
query.addBindValue(i[0])
query.addBindValue(i[1])
query.addBindValue(i[2])
query.exec_()
def setupMainWidgets(self):
mw_widget = QWidget()
main_panel = QHBoxLayout(mw_widget)
# SQL Table
self.modelSql = QSqlTableModel()
self.modelSql.setTable('sprav')
self.modelSql.setQuery(QSqlQuery(
'SELECT nsi_name, file_date, file_name FROM sprav'))
self.modelSql.setHeaderData(self.modelSql.fieldIndex('nsi_name'),
Qt.Horizontal, 'Name')
self.modelSql.setHeaderData(self.modelSql.fieldIndex('file_date'),
Qt.Horizontal, 'Date')
self.modelSql.setHeaderData(self.modelSql.fieldIndex('file_name'),
Qt.Horizontal, 'File')
self.modelSql.setEditStrategy(QSqlTableModel.OnFieldChange)
self.modelSql.select()
# QTableView()
self.table_view = QTableView()
self.table_view.setSelectionBehavior(1)
self.table_view.setAlternatingRowColors(True)
self.table_view.setModel(self.modelSql)
self.table_view.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
main_panel.addWidget(self.table_view)
# QVBoxLayout()
right_panel = QVBoxLayout()
line = QFrame()
line.setFrameShape(QFrame.HLine)
self.add_record = QPushButton('Add', self)
self.add_record.clicked.connect(self.addRecord)
self.change_record = QPushButton('Change', self)
self.change_record.clicked.connect(self.changeRecord)
self.delete_record = QPushButton('Delete', self)
self.delete_record.clicked.connect(self.delRecord)
right_panel.addSpacing(20)
right_panel.addWidget(line)
right_panel.addWidget(self.add_record)
right_panel.addWidget(self.change_record)
right_panel.addWidget(self.delete_record)
right_panel.addStretch()
main_panel.addLayout(right_panel)
self.setCentralWidget(mw_widget)
def addRecord(self):
row = self.modelSql.rowCount()
self.modelSql.insertRow(row)
index = self.modelSql.index(row, 0)
self.table_view.setCurrentIndex(index)
self.table_view.edit(index)
def delRecord(self):
cur_item = self.table_view.selectedIndexes()
for index in cur_item:
self.modelSql.removeRow(index.row())
self.modelSql.select()
def changeRecord(self):
self.table_view.edit(self.table_view.currentIndex())
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())