[英]How do I add a widget to display SQLite data from data base?
很抱歉这篇文章的长度。 我尝试了大约 10 种不同的方法来解决我的问题,但都没有运气。 我想给出最可行的上下文。
我是 Pyqt5 的新手。 我正在制作一个联系人应用程序,我可以使用 pyqt5 GUI 应用程序将数据输入到 sqlite3 'contacts.db' 文件中。 我在应用程序的左侧有 GUI 输入字段。 我一直卡住的地方是如何在 GUI 应用程序右侧的显示框中显示“contacts.db”文件的内容?
到目前为止,这是我的代码:
import sys
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow, QLabel, QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import QSize
from sqlite3 import *
class MainWindow(QMainWindow):
# Creating Main drop window
def __init__(self):
QMainWindow.__init__(self)
# Sets dimentions for main drop window
self.setMinimumSize(QSize(1000, 425))
# Sets title for main drop window
self.setWindowTitle("Contacts")
def firstname():
# Creates a label for first field
self.nameLabel1 = QLabel(self)
# Creates label text for first label
self.nameLabel1.setText('First Name: ')
# Creates first field
self.line1 = QLineEdit(self)
# Sets placement for first field
self.line1.move(95, 50)
# Sets size for first field
self.line1.resize(200, 32)
# Sets placement for first label
self.nameLabel1.move(20, 50)
firstname()
def lastname():
self.nameLabel2 = QLabel(self)
self.nameLabel2.setText('Last Name: ')
self.line2 = QLineEdit(self)
self.line2.move(95, 100)
self.line2.resize(200, 32)
self.nameLabel2.move(20, 100)
lastname()
def email():
self.nameLabel3 = QLabel(self)
self.nameLabel3.setText('Email: ')
self.line3 = QLineEdit(self)
self.line3.move(95, 150)
self.line3.resize(200, 32)
self.nameLabel3.move(20, 150)
email()
def phone():
self.nameLabel4 = QLabel(self)
self.nameLabel4.setText('Phone: ')
self.line4 = QLineEdit(self)
self.line4.move(95, 200)
self.line4.resize(200, 32)
self.nameLabel4.move(20, 200)
phone()
def phone():
self.nameLabel5 = QLabel(self)
self.nameLabel5.setText('Location: ')
self.line5 = QLineEdit(self)
self.line5.move(95, 250)
self.line5.resize(200, 32)
self.nameLabel5.move(20, 250)
phone()
def button():
# Creates button, and button label
pybutton1 = QPushButton('Add Contact', self)
# Creates framwork for button funtion
pybutton1.clicked.connect(self.clickMethod1)
# Sets button size
pybutton1.resize(200,32)
# Sets button placement
pybutton1.move(95, 325)
button()
# Creates action that will be preformed when first button is pressed
def clickMethod1(self):
conn = connect('Contacts.db')
c = conn.cursor()
first = self.line1.text()
last = self.line2.text()
email = self.line3.text()
phone = self.line4.text()
loc = self.line5.text()
c.execute(f"""INSERT INTO contacts VALUES('{first}',
'{last}', '{email}', '{phone}', '{loc}')
""")
conn.commit()
conn.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_() )
要创建与我相同的数据库,您可以在 python 中运行它:
from sqlite3 import *
conn = connect('Contacts.db')
c = conn.cursor()
# Make table
def make():
c.execute("""CREATE TABLE IF NOT EXISTS contacts(
first TEXT,
last TEXT,
email TEXT,
phone TEXT,
location TEXT
)""")
make()
conn.commit()
conn.close()
非常感谢您的帮助!
Qt 已经通过QtSql模块提供了对 SQL 的支持,因此您通常不需要使用单独的 sql 模块进行通用使用。
使用model加载数据,并最终使用视图显示(阅读有关 Qt 的模型/视图编程范例的更多信息。
您基本上执行以下操作:
setModel()
为该视图设置 model ;在以下示例中,您可以看到 model 已连接到数据库,并且由于直接对 model 进行了修改,因此表会随之自动更新。
请注意,我重新编写了您的代码,因为它有很多问题:首先,QMainWindow 应该始终有一个中央小部件,然后您还应该始终使用布局管理器而不是任意大小和位置; 我还删除了__init__
中的函数,因为它们是不必要的,只会使代码分散注意力。
from PyQt5 import QtCore, QtWidgets, QtSql
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central = QtWidgets.QWidget()
mainLayout = QtWidgets.QGridLayout(central)
mainLayout.setColumnStretch(0, 1)
mainLayout.setColumnStretch(1, 2)
formLayout = QtWidgets.QFormLayout()
mainLayout.addLayout(formLayout, 0, 0)
self.firstNameEdit = QtWidgets.QLineEdit()
self.lastNameEdit = QtWidgets.QLineEdit()
self.emailEdit = QtWidgets.QLineEdit()
self.phoneEdit = QtWidgets.QLineEdit()
self.locEdit = QtWidgets.QLineEdit()
formLayout.addRow('First name:', self.firstNameEdit)
formLayout.addRow('Last name:', self.lastNameEdit)
formLayout.addRow('Email:', self.emailEdit)
formLayout.addRow('Phone:', self.phoneEdit)
formLayout.addRow('Location:', self.locEdit)
self.addButton = QtWidgets.QPushButton('Add contact', enabled=False)
mainLayout.addWidget(self.addButton, 1, 0)
self.table = QtWidgets.QTableView()
mainLayout.addWidget(self.table, 0, 1, 2, 1)
self.table.setEditTriggers(self.table.NoEditTriggers)
self.setCentralWidget(central)
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('Contacts.db')
self.model = QtSql.QSqlTableModel()
self.model.setTable('contacts')
self.model.select()
self.table.setModel(self.model)
self.mandatoryFields = self.firstNameEdit, self.lastNameEdit
self.otherFields = self.emailEdit, self.phoneEdit, self.locEdit
self.allFields = self.mandatoryFields + self.otherFields
for field in self.allFields:
field.textChanged.connect(self.validate)
self.addButton.clicked.connect(self.addRecord)
def addRecord(self):
record = self.model.record()
for i, field in enumerate(self.allFields):
record.setValue(i, field.text())
row = self.model.rowCount()
self.model.insertRow(row)
self.model.setRecord(row, record)
def validate(self):
for field in self.mandatoryFields:
if not field.text():
self.addButton.setEnabled(False)
return
for field in self.otherFields:
if field.text():
break
else:
self.addButton.setEnabled(False)
return
self.addButton.setEnabled(True)
另请注意,Qt 提供了一个非常方便的 class, QDataWidgetMapper ,它允许将单个小部件与 model 的字段连接起来。 通过这种方式,您可以在用户选择索引时自动更新字段,或使用所有字段更新数据库。
这是上面代码的略微修改版本,实现了映射器(为简单起见,我再次发布整个代码,因为修改太复杂了):
from PyQt5 import QtCore, QtWidgets, QtSql
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central = QtWidgets.QWidget()
mainLayout = QtWidgets.QGridLayout(central)
mainLayout.setColumnStretch(0, 1)
mainLayout.setColumnStretch(1, 2)
formLayout = QtWidgets.QFormLayout()
mainLayout.addLayout(formLayout, 0, 0)
self.firstNameEdit = QtWidgets.QLineEdit()
self.lastNameEdit = QtWidgets.QLineEdit()
self.emailEdit = QtWidgets.QLineEdit()
self.phoneEdit = QtWidgets.QLineEdit()
self.locEdit = QtWidgets.QLineEdit()
formLayout.addRow('First name:', self.firstNameEdit)
formLayout.addRow('Last name:', self.lastNameEdit)
formLayout.addRow('Email:', self.emailEdit)
formLayout.addRow('Phone:', self.phoneEdit)
formLayout.addRow('Location:', self.locEdit)
self.updateButton = QtWidgets.QPushButton('Update contact', enabled=False)
self.addButton = QtWidgets.QPushButton('Add contact', enabled=False)
buttonLayout = QtWidgets.QHBoxLayout()
buttonLayout.addWidget(self.updateButton)
buttonLayout.addWidget(self.addButton)
mainLayout.addLayout(buttonLayout, 1, 0)
self.table = QtWidgets.QTableView()
mainLayout.addWidget(self.table, 0, 1, 2, 1)
self.table.setEditTriggers(self.table.NoEditTriggers)
self.setCentralWidget(central)
db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('Contacts.db')
self.model = QtSql.QSqlTableModel()
self.model.setTable('contacts')
self.model.select()
self.table.setModel(self.model)
self.table.setSelectionMode(self.table.SingleSelection)
self.mandatoryFields = self.firstNameEdit, self.lastNameEdit
self.otherFields = self.emailEdit, self.phoneEdit, self.locEdit
self.allFields = self.mandatoryFields + self.otherFields
self.mapper = QtWidgets.QDataWidgetMapper()
self.mapper.setModel(self.model)
self.mapper.setSubmitPolicy(self.mapper.ManualSubmit)
for i, field in enumerate(self.allFields):
field.textChanged.connect(self.validate)
self.mapper.addMapping(field, i)
self.addButton.clicked.connect(self.addRecord)
self.updateButton.clicked.connect(self.updateRecord)
self.table.selectionModel().selectionChanged.connect(self.selectionChanged)
self.mapper.currentIndexChanged.connect(self.validate)
self.table.doubleClicked.connect(self.doubleClicked)
self.table.viewport().installEventFilter(self)
def eventFilter(self, obj, event):
if event.type() == event.MouseButtonPress:
# clear all fields when clicking on an empty area of the table
index = self.table.indexAt(event.pos())
if not index.isValid():
self.table.selectionModel().select(
index, QtCore.QItemSelectionModel.ClearAndSelect)
return super().eventFilter(obj, event)
def doubleClicked(self, index):
widget = self.mapper.mappedWidgetAt(index.column())
if widget:
widget.setFocus()
def selectedRow(self):
selected = self.table.selectedIndexes()
if selected:
return selected[-1].row()
return -1
def selectionChanged(self):
row = self.selectedRow()
self.mapper.setCurrentIndex(row)
if row < 0:
for field in self.allFields:
field.setText('')
self.validate()
def addRecord(self):
# we cannot use submit(), as it will use the *current* index, nor we can
# insert the new row and set the new index, as it would clear all fields
record = self.model.record()
for i, field in enumerate(self.allFields):
record.setValue(i, field.text())
row = self.model.rowCount()
self.model.insertRow(row)
self.model.setRecord(row, record)
self.table.selectionModel().select(self.model.index(row, 0),
QtCore.QItemSelectionModel.ClearAndSelect)
def updateRecord(self):
row = self.selectedRow()
if row < 0:
self.updateButton.setEnabled(False)
return
self.mapper.submit()
def validate(self):
valid = True
for field in self.mandatoryFields:
if not field.text():
valid = False
break
else:
for field in self.otherFields:
if field.text():
break
else:
valid = False
self.addButton.setEnabled(valid)
self.updateButton.setEnabled(valid and bool(self.table.selectedIndexes()))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.