主頁 > .NET開發 > 如何添加小部件以顯示資料庫中的SQLite資料?

如何添加小部件以顯示資料庫中的SQLite資料?

2021-12-27 10:21:57 .NET開發

很抱歉這篇文章的長度。我嘗試了大約 10 種不同的方法來解決我的問題,但沒有運氣。我想給出最可能的背景關系。

我是 Pyqt5 的新手。我正在制作一個聯系人應用程式,我能夠使用 pyqt5 GUI 應用程式將資料輸入到 sqlite3 'contacts.db' 檔案中。我在應用程式的左側有 GUI 輸入欄位。我一直卡住的地方是如何在 GUI 應用程式右側的顯示框中顯示“contacts.db”檔案的內容?

這是一個螢屏截圖: 如何添加小部件以顯示資料庫中的 SQLite 資料?

到目前為止,這是我的代碼:

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()

非常感謝您的幫助!

uj5u.com熱心網友回復:

Qt 已經通過QtSql模塊提供了對 SQL 的支持,因此您通常不需要使用單獨的 sql 模塊進行通用使用。

資料使用模型加載,并最終使用視圖顯示(閱讀更多關于Qt模型/視圖編程范例。

您基本上執行以下操作:

  1. 加載資料庫引擎;
  2. 選擇一個資料庫;
  3. 創建一個模型(通常是一個QSqlTableModel);
  4. 創建一個視圖(通常是一個QTableView);
  5. 為該視圖設定模型,使用setModel();

在下面的示例中,您可以看到模型已連接到資料庫,并且由于修改是直接對模型進行的,因此表會隨之自動更新。

請注意,我重新撰寫了您的代碼,因為它有很多問題:首先,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 提供了一個非常方便的類QDataWidgetMapper,它允許將單個小部件與模型的欄位連接起來通過這種方式,您可以在用戶選擇索引時自動更新欄位,或使用所有欄位更新資料庫。

這是上面代碼的一個稍微修改的版本,實作了映射器(為簡單起見,我再次發布整個代碼,因為修改太復雜了):

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()))

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/394255.html

標籤:Python 蟒蛇-3.x sqlite pyqt5

上一篇:SQLite3JSON1按數字索引排序

下一篇:RoomAndroid忽略Dao類中的@Query條件(奇怪)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more