發現問題
如果是自己創建的ui文件,怎么包含進自己的窗口類并且成為ui成員?
一般來說Qt designer 會根據你.ui文件生成對應的ui_文件名這個類(文件名是ui文件名),它包含了所有 UI 組件(如按鈕、文本框、標簽等)的定義和布局代碼,以及一個setupUi
函數用于初始化 UI。
Qt 里的?
.ui
?文件本身不是編程語言編寫的,而是一種 XML 格式的文件,用于描述用戶界面的布局和屬性。生成與轉換
.ui
?文件通常是通過 Qt Designer(Qt 提供的可視化界面設計工具)創建和編輯的。在 Qt Designer 中,你可以通過拖拽、設置屬性等操作來構建界面,比如添加按鈕、文本框、布局等各種控件。當保存?
.ui
?文件后,Qt 會通過?uic
(User Interface Compiler,用戶界面編譯器 )工具將?.ui
?文件轉換為對應的 C++ 代碼,生成一個包含界面初始化和控件定義的頭文件(一般命名為?ui_<窗口名>.h
?)。
我之前抄AI給的ui文件,沒有改里面對應的窗口類名(Form),導致包含#include"ui_StatisticWindow.h",使用new StatisticWindow時報錯,顯示類不完整。
問題一?無法加載QtChart模塊
你會發現根本就沒有Qtchart這個目錄,也就是說就沒有這個模塊。
我使用Qt Maintain Tool?
哪怕后面更新組件也找不到。
但是奇怪的是,你點開Vs的項目屬性,點開Qt Project Setting
點擊選擇模塊,找到Qt Chart。
你一勾選,點擊OK,后面再應用。馬上程序就報錯。
我也不知道到哪去下載這個模塊。
問題二 Qt 本身沒有MySql驅動
需要自己去安裝,導致我一直找為什么無法打開數據庫,還是多虧AI、qDebug和調試。
后面選擇Qt自帶的SQLite數據庫。
數據庫文件概述
在使用 SQLite 數據庫時,數據庫文件是一個包含數據庫所有數據和結構的普通文件。SQLite 是一個嵌入式數據庫,它不需要單獨的服務器進程,所有的數據都存儲在一個單一的磁盤文件中。
數據庫文件的來源
1. 系統是否自帶
Qt 系統、VS 系統或者電腦系統通常不會自帶特定的 SQLite 數據庫文件。不過,操作系統可能會預裝 SQLite 庫(例如在一些 Linux 發行版中),這使得你可以在開發環境中使用 SQLite。
使用?SQLite 驅動?時,不需要額外下載獨立的 SQLite 數據庫服務器程序,也?不需要創建用戶,原因和使用方式如下:
1. 為什么不需要額外下載?
SQLite 是 “嵌入式” 數據庫:
SQLite 的核心是一個?單一的庫文件(如?sqlite3.dll
/libsqlite3.so
/libsqlite3.dylib
),Qt 已經默認集成了 SQLite 的驅動支持(QSQLITE
?驅動)。
也就是說,只要你安裝了 Qt,就已經自帶了連接 SQLite 所需的全部功能,無需額外下載數據庫程序。運行方式簡單:
SQLite 直接通過?數據庫文件(比如?todo.db
)工作,不需要像 MySQL 那樣啟動獨立的數據庫服務進程。程序運行時,Qt 會通過?QSQLite
?驅動直接讀寫數據庫文件。
2. 為什么不需要創建用戶?
SQLite 無用戶權限體系:
SQLite 的設計目標是輕量、嵌入式使用,沒有 “用戶賬戶”“密碼”“權限管理”?這些復雜概念。它的訪問權限完全依賴于?操作系統的文件權限(誰能讀寫數據庫文件,誰就能操作數據庫)。舉個例子:
如果你的程序能讀寫?todo.db
?文件,就可以直接連接、增刪改查;如果文件權限被限制(比如只讀),操作也會受限制。
3. 適合場景
- 開發 / 測試階段:無需部署數據庫服務,一個文件即可搞定。
- 輕量級應用:如工具類程序、本地數據存儲的小軟件。
- 嵌入式設備:因為 SQLite 無需獨立進程,適合資源有限的環境。
4. 注意事項
并發限制:
SQLite 是?文件級鎖,多線程 / 多進程高并發寫操作時性能會下降(但讀操作影響較小)。如果是復雜的多用戶場景,MySQL/PostgreSQL 更合適。加密需求:
默認 SQLite 不加密數據庫文件。如果需要加密,可集成?SQLCipher(需額外編譯或使用支持加密的 Qt 版本)。文件路徑問題:
如果?dbPath
?是相對路徑,數據庫文件會創建在程序運行目錄下。建議用絕對路徑或明確管理文件位置,避免找不到文件。
總結:
用 SQLite 替換 MySQL 后,代碼更簡單、無需額外部署,非常適合快速開發或本地數據存儲場景。如果你的需求是 “輕量級、無需復雜配置”,SQLite 是絕佳選擇 ?
修改后的代碼
#pragma once
#include <QtCore/QObject>
#include <QtSql/QSqlDatabase>
#include <QtCore/QString>
#include<qsqlerror.h>class DatabaseManager : public QObject { Q_OBJECT
public: static DatabaseManager& instance(); bool initDatabase(const QString& dbPath = "todo.db");QSqlDatabase database() const; // 數據庫操作方法 bool createTables(); bool backupDatabase(const QString& backupPath); private: explicit DatabaseManager(QObject* parent = nullptr); ~DatabaseManager(); Q_DISABLE_COPY(DatabaseManager) QSqlDatabase m_db;
};
#include "DatabaseManager.h"
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QDebug>DatabaseManager& DatabaseManager::instance() {static DatabaseManager instance;return instance;
}DatabaseManager::DatabaseManager(QObject* parent) : QObject(parent) {// 使用SQLite驅動(移除了所有MySQL相關配置)m_db = QSqlDatabase::addDatabase("QSQLITE");
}DatabaseManager::~DatabaseManager() {if (m_db.isOpen()) {m_db.close();}
}bool DatabaseManager::initDatabase(const QString& dbPath) {m_db.setDatabaseName(dbPath); // 設置數據庫文件名if (!m_db.open()) {qDebug() << "Failed to open SQLite database:" << m_db.lastError().text();return false;}return createTables();
}QSqlDatabase DatabaseManager::database() const
{return QSqlDatabase();
}bool DatabaseManager::createTables() {QSqlQuery query(m_db);// 修正SQL語法:// - AUTOINCREMENT (SQLite的自增關鍵字)// - INTEGER (替代BOOLEAN,SQLite用0/1表示布爾值)QString createTableQuery = "CREATE TABLE IF NOT EXISTS tasks (""id INTEGER PRIMARY KEY AUTOINCREMENT,""title TEXT NOT NULL,""description TEXT,""priority INTEGER DEFAULT 1,""due_date DATE,""completed INTEGER DEFAULT 0," // 使用INTEGER而非BOOLEAN"created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP"")";if (!query.exec(createTableQuery)) {qDebug() << "Failed to create table:" << query.lastError().text();return false;}return true;
}bool DatabaseManager::backupDatabase(const QString& backupPath) {// 實現數據庫備份邏輯return false;
}