问题描述
首先,我将描述并展示我的小程序是如何工作的,以便我的问题易于理解
First, I will describe and show how my mini program works visually so my problem is easy to understand
以下是我用于该程序的 2 个寡妇:
Below are the 2 widows that I use for the program:
主窗口
输入窗口
主窗口显示在程序开始处.我将 QListWidget 用于宏"列表,该列表显示从 Sqlite 数据库 (DB) 读取的每个条目的标题.当按下主窗口中的新建"按钮时,会显示一个新的输入窗口.输入窗口中的保存"按钮将输入的标题和描述保存到数据库并更新主窗口中的宏"列表.这看起来像这样:
The Main Window is shown at the start of the program. I used QListWidget for the 'Macros' list, which shows titles of each entry read from a Sqlite database(DB). A new Input Window is shown when the 'New' button in Main Window is pressed. The 'Save' button in Input Window saves the title and description input to DB and updates the 'Macros' list in Main Window. This will look something like this:
在输入窗口输入信息
更新主窗口
我的Sqlite表
我希望能够在宏"列表中选择一个条目,按编辑";按钮,并显示填充了来自 DB 的数据的输入窗口.但是,因为 QListWidget 只允许输入字符串,所以我无法使用它的 PK ('id') 进行搜索.
I would like to be able to select an entry in 'Macros' list, press "Edit" button, and show Input Window filled with data from DB. However, because QListWidget allows only string input, I can't search using it's PK ('id').
我正在考虑使用 QTableWidget 而不是 QListWidget.我将加载整个表格但隐藏除标题列之外的所有列,以便只有标题将显示在主窗口的宏"列表中.对于查询,我将通过访问所选条目的第 0 个索引来使用条目的 PK.
I'm thinking of using QTableWidget instead of QListWidget. I will load the entire table but hide all the columns except the title column, so that only the titles will be displayed in 'Macros' list in Main Window. For querying, I will use the entry's PK by accessing the selected entry's 0'th index.
请告诉我这是否是正确的步骤.如果不是,请描述您将使用什么来实现仅显示标题但允许查询其数据的列表.我是 PyQt/PySide 的初学者,非常感谢您的指导.
Please let me know if this is the correct step. If not, please describe what you would use to implement a list that only shows the title, but allows querying of its data. I am a beginner at PyQt/PySide and I would really appreciate any guidance.
以下是按下保存"按钮时执行的代码(及其辅助函数)
Below are the code executed when 'Save' button is pressed (plus its helper functions)
def save_macro(self):
title = self.lineedit.text()
description = self.textedit.toPlainText()
add_sql_query = ''' INSERT INTO Macros (title,description)
VALUES(?,?) '''
# Helper func that creates connection to db
sqlhelper = SqliteHelper("entry name")
if sqlhelper is not None: # If db is connected:
macro_data = (title, description)
sqlhelper.insert(add_sql_query, macro_data)
self.close()
class SqliteHelper:
def __init__(self, name=None):
self.conn = None
self.cursor = None
if name:
self._create_connection(name)
def _create_connection(self, name):
try:
self.conn = sqlite3.connect(name)
self.cursor = self.conn.cursor()
print(sqlite3.version)
except sqlite3.Error as e:
print(e)
def insert(self, query, inserts): # Insert
c = self.cursor
c.execute(query, inserts)
self.conn.commit()
推荐答案
不要重复造轮子,Qt 提供了与数据库交互的类,例如处理表上的信息可以使用 QSqlQueryModel、QSqlTableModel 等来添加一行你必须创建一个 QSqlRecord 并将其添加到模型中,对于版本,你可以使用一个 QDataWidgetMapper 来映射和编辑一行的信息,要删除你必须删除该行并重新加载整个表.要指示应该在 QListView 中显示哪个字段,请使用 setModelColumn() 方法,该方法应该是标题"字段的列.
Do not reinvent the wheel, Qt provides classes to interact with the database, for example to handle information on tables you can use QSqlQueryModel, QSqlTableModel, etc. To add a row you must create a QSqlRecord and add it to the model, for the edition you can use a QDataWidgetMapper that maps and edits the information of a row, and to delete you must remove the row and reload the entire table. To indicate which field should be displayed in the QListView, use the setModelColumn() method, which should be the column of the "title" field.
from PyQt5 import QtCore, QtGui, QtWidgets, QtSql
def create_connection(database):
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName(database)
if not db.open():
print("Cannot open database")
print(
"Unable to establish a database connection.\n"
"This example needs SQLite support. Please read "
"the Qt SQL driver documentation for information "
"how to build it.\n\n"
"Click Cancel to exit."
)
return False
query = QtSql.QSqlQuery()
if not query.exec_(
"""CREATE TABLE IF NOT EXISTS Macros (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"title" TEXT,
"description" TEXT)"""
):
print(query.lastError().text())
return False
return True
class AddMacroDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.title_le = QtWidgets.QLineEdit()
self.description_te = QtWidgets.QPlainTextEdit()
button_box = QtWidgets.QDialogButtonBox(self)
button_box.setOrientation(QtCore.Qt.Horizontal)
button_box.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.title_le)
lay.addWidget(self.description_te)
lay.addWidget(button_box)
@property
def title(self):
return self.title_le.text()
@property
def description(self):
return self.description_te.toPlainText()
class EditMacroDialog(QtWidgets.QDialog):
def __init__(self, model, index, parent=None):
super().__init__(parent)
self.title_le = QtWidgets.QLineEdit()
self.description_te = QtWidgets.QPlainTextEdit()
mapper = QtWidgets.QDataWidgetMapper(
self, submitPolicy=QtWidgets.QDataWidgetMapper.ManualSubmit
)
mapper.setModel(model)
mapper.addMapping(self.title_le, model.record().indexOf("title"))
mapper.addMapping(self.description_te, model.record().indexOf("description"))
mapper.setCurrentIndex(index)
button_box = QtWidgets.QDialogButtonBox(self)
button_box.setOrientation(QtCore.Qt.Horizontal)
button_box.setStandardButtons(
QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
button_box.accepted.connect(mapper.submit)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(self.title_le)
lay.addWidget(self.description_te)
lay.addWidget(button_box)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QtSql.QSqlTableModel(self)
self.model.setTable("Macros")
self.model.select()
self.sql_list_view = QtWidgets.QListView()
self.sql_list_view.setModel(self.model)
self.sql_list_view.setModelColumn(self.model.record().indexOf("title"))
self.new_button = QtWidgets.QPushButton(self.tr("New"))
self.edit_button = QtWidgets.QPushButton(self.tr("Edit"))
self.remove_button = QtWidgets.QPushButton(self.tr("Remove"))
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
grid_layout = QtWidgets.QGridLayout(central_widget)
grid_layout.addWidget(
QtWidgets.QLabel(self.tr("Macros"), alignment=QtCore.Qt.AlignCenter)
)
grid_layout.addWidget(self.sql_list_view, 1, 0)
vlay = QtWidgets.QVBoxLayout()
vlay.addWidget(self.new_button)
vlay.addWidget(self.edit_button)
vlay.addWidget(self.remove_button)
grid_layout.addLayout(vlay, 1, 1)
self.resize(640, 480)
self.new_button.clicked.connect(self.new)
self.edit_button.clicked.connect(self.edit)
self.remove_button.clicked.connect(self.remove)
self.sql_list_view.selectionModel().selectionChanged.connect(
self.onSelectionChanged
)
self.onSelectionChanged()
@property
def model(self):
return self._model
@QtCore.pyqtSlot()
def new(self):
d = AddMacroDialog()
if d.exec_() == QtWidgets.QDialog.Accepted:
r = self.model.record()
r.setValue("title", d.title)
r.setValue("description", d.description)
if self.model.insertRecord(self.model.rowCount(), r):
self.model.select()
@QtCore.pyqtSlot()
def edit(self):
ixs = self.sql_list_view.selectionModel().selectedIndexes()
if ixs:
d = EditMacroDialog(self.model, ixs[0].row())
d.exec_()
@QtCore.pyqtSlot()
def remove(self):
ixs = self.sql_list_view.selectionModel().selectedIndexes()
if ixs:
self.model.removeRow(ixs[0].row())
self.model.select()
@QtCore.pyqtSlot()
def onSelectionChanged(self):
state = bool(self.sql_list_view.selectionModel().selectedIndexes())
self.edit_button.setEnabled(state)
self.remove_button.setEnabled(state)
if __name__ == "__main__":
import sys
database = "entry name" # ":memory:"
app = QtWidgets.QApplication(sys.argv)
if not create_connection(database):
sys.exit(app.exec_())
w = MainWindow()
w.show()
sys.exit(app.exec_())
这篇关于从列表条目访问 SQL 数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!