繁体   English   中英

如何添加小部件以显示来自数据库的 SQLite 数据?

[英]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 的模型/视图编程范例的更多信息。

您基本上执行以下操作:

  1. 加载数据库引擎;
  2. select 一个数据库;
  3. 创建一个 model (通常是QSqlTableModel );
  4. 创建一个视图(通常是QTableView );
  5. 使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM