步骤
第一步:绘制连接数据库的ui
第二步:创建数据库,往数据表中写数据
第三步:解析xml文件,匹配汽车类型
绘制如下
点击连接跳转到主页面
在.pro文件中添加sql和xml
代码实现
connectdlg.h
#ifndef CONNECTDLG_H
#define CONNECTDLG_H
#include <QDialog>
#include<QMessageBox>
#include"ui_connectlg.h"
class QSqlError;
namespace Ui {
class ConnDlg;
}
class ConnDlg : public QDialog
{
Q_OBJECT
public:
explicit ConnDlg(QWidget *parent = 0);
QString driverName() const;//确保该函数再任何对象都可以使用,需要使用const,const代表常量成员函数
QString databaseName() const;
QString userName() const;
QString password() const;
QString hostName() const;
int port() const;
QSqlError addConnection(const QString &driver,const QString &dbName,const QString &host,const
QString &user,const QString &passwd,int port=-1);//数据库连接
void creatDB();
void addSqliteConnection();
~ConnDlg();
private:
Ui::QSqlConnectionDialogUi ui;
private slots:
void on_okButton_clicked();
void on_cancelButton_clicked() { reject(); }//调用了reject函数
void driverChanged(const QString &);//&表示引用,你可以修改这个传递进来的变量
};
#endif // CONNECTDLG_H
connectdlg.cpp
#include "connectdlg.h"
#include "ui_connectlg.h"
#include <QSqlDatabase>
#include <QtSql>
ConnDlg::ConnDlg(QWidget *parent) :
QDialog(parent)
//ui(new Ui::ConnDlg)
{
ui.setupUi(this);
QStringList drivers=QSqlDatabase::drivers();//查找数据库驱动
ui.comboDriver->addItems(drivers);//将这些驱动加入ui界面的组合框中
connect(ui.comboDriver,SIGNAL(currentIndexChanged(const QString &)),this,SLOT(driverChanged(const QString &)));
ui.status_label->setText(tr("准备连接数据库!"));
}
QString ConnDlg::driverName() const
{
return ui.comboDriver->currentText();
}
QString ConnDlg::databaseName() const
{
return ui.editDatabase->text();
}
QString ConnDlg::userName() const
{
return ui.editUsername->text();
}
QString ConnDlg::password() const
{
return ui.editPassword->text();
}
QString ConnDlg::hostName() const
{
return ui.editHostname->text();
}
int ConnDlg::port() const
{
return ui.portSpinBox->value();
}
QSqlError ConnDlg::addConnection(const QString &driver, const QString &dbName, const QString &host,
const QString &user, const QString &passwd, int port)
{
QSqlError err;
QSqlDatabase db=QSqlDatabase::addDatabase(driver);
db.setDatabaseName(dbName);
db.setHostName(host);
db.setPort(port);
if(!db.open(user,passwd))//当数据库打开失败,记录最后错误,然后引用默认数据库连接,并删除刚才打开的失败连接
{
err=db.lastError();
}
return err;
}
void ConnDlg::creatDB()
{
//创建QSqlQuery对象,支持sql语句
QSqlQuery query;
query.exec("create table factory(id int primary key,manufactory varchar(40),address varchar(40))");
query.exec(QObject::tr("insert into factory values(1,'一汽大众','长春')"));
query.exec(QObject::tr("insert into factory values(2,'二汽神龙','武汉')"));
query.exec(QObject::tr("insert into factory values(3,'上海大众','上海')"));
query.exec("create table cars (carid int primary key,name varchar(50),factoryid int,year int,foreign key(factoryid) references factory)");
query.exec(QObject::tr("insert into cars values(1,'奥迪A6',1,2005)"));
query.exec(QObject::tr("insert into cars values(2,'捷达',1,1993)"));
query.exec(QObject::tr("insert into cars values(3,'宝来',1,2000)"));
query.exec(QObject::tr("insert into cars values(4,'毕加索',2,1999)"));
query.exec(QObject::tr("insert into cars values(5,'富康',2,2004)"));
query.exec(QObject::tr("insert into cars values(6,'标志',2,2001)"));
query.exec(QObject::tr("insert into cars values(7,'桑塔纳',3,1995)"));
query.exec(QObject::tr("insert into cars values(8,'帕萨特',3,2000)"));
}
void ConnDlg::addSqliteConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("databasefile");
if(!db.open())
{
ui.status_label->setText(db.lastError().text());
return;
}
ui.status_label->setText(tr("创建sqlite数据库成功"));
}
ConnDlg::~ConnDlg()
{
//delete ui;
}
void ConnDlg::on_okButton_clicked()
{
if(ui.comboDriver->currentText().isEmpty())//检查用户是否选择了一个数据库驱动
{
ui.status_label->setText(tr("请选择一个数据库驱动!"));
ui.comboDriver->setFocus();
}
else if(ui.comboDriver->currentText()=="QSQLITE")//如果是QSQLITE驱动,则调用函数创建一个内存数据库
{
addSqliteConnection();
//创建数据库表,如已经存在则无需执行
creatDB();
accept();
}
else
{
//如果是其他驱动,则调用函数创建一个其他所选类型的数据库连接
QSqlError err=addConnection(driverName(),databaseName(),hostName(),userName(),password(),port());
if(err.type()!=QSqlError::NoError)//在连接出错时显示错误信息
ui.status_label->setText(err.text());
else
ui.status_label->setText(tr("连接数据库成功"));
accept();
}
}
void ConnDlg::driverChanged(const QString &text)
{
if(text == "QSQLITE")
{
ui.editDatabase->setEnabled(false);
ui.editUsername->setEnabled(false);
ui.editPassword->setEnabled(false);
ui.editHostname->setEnabled(false);
ui.portSpinBox->setEnabled(false);
}
else
{
ui.editDatabase->setEnabled(true);
ui.editUsername->setEnabled(true);
ui.editPassword->setEnabled(true);
ui.editHostname->setEnabled(true);
ui.portSpinBox->setEnabled(true);
}
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QGroupBox>
#include<QTableView>
#include<QListWidget>
#include<QLabel>
#include<QFile>
#include<QSqlRelationalTableModel>
#include<QSqlTableModel>
#include<QModelIndex>
#include<QDomNode>
#include<QDomDocument>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//构造函数,factoryTable是需要传入汽车制造商表名
MainWindow(const QString &factoryTable,const QString &carTable,QFile *carDetails,QWidget *parent = 0);
~MainWindow();
private:
QGroupBox *createCarGroupBox();
QGroupBox *createFactorGroupBox();
QGroupBox *createDetailsGroupBox();
void createMenuBar();
QTableView *carView;
QTableView *factoryView;
QListWidget *attribList;
QLabel *profileLabel;
QLabel *titleLabel;
void decreaseCarCount(QModelIndex index);
void getAttribList(QDomNode car);
QModelIndex indexOfFactory(const QString &factory);
void readCarData();
void removeCarFromDatabase(QModelIndex index);
void removeCarFromFile(int id);
QDomDocument carData;
QFile *file;
QSqlRelationalTableModel *carModel;
QSqlTableModel *factoryModel;
private slots:
void addCar();
void changeFactory(QModelIndex index);
void delCar();
void showCarDetails(QModelIndex index);
void showFactorytProfile(QModelIndex index);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include<QGridLayout>
#include<QAbstractItemView>
#include<QHeaderView>
#include<QAction>
#include<QMenu>
#include<QMenuBar>
#include<QMessageBox>
#include<QSqlRecord>
MainWindow::MainWindow(const QString &factoryTable,const QString &carTable,QFile *carDetails,QWidget *parent)
: QMainWindow(parent)
{
file = carDetails;
readCarData();//将xml文件里的车型信息读入QDomDocument类实例carData中
carModel=new QSqlRelationalTableModel(this);
carModel->setTable(carTable);
carModel->setRelation(2,QSqlRelation(factoryTable,"id","manufactory"));
carModel->select();
factoryModel=new QSqlTableModel(this);
factoryModel->setTable(factoryTable);
factoryModel->select();
QGroupBox *factory=createFactorGroupBox();
QGroupBox *cars=createCarGroupBox();
QGroupBox *details=createDetailsGroupBox();
//布局
QGridLayout *layout=new QGridLayout;
layout->addWidget(factory,0,0);
layout->addWidget(cars,1,0);
layout->addWidget(details,0,1,2,1);
layout->setColumnStretch(1,1);
layout->setColumnMinimumWidth(0,500);
QWidget *widget=new QWidget;
widget->setLayout(layout);
setCentralWidget(widget);
createMenuBar();
resize(850,400);
setWindowTitle(tr("主从视图"));
}
MainWindow::~MainWindow()
{
}
QGroupBox *MainWindow::createCarGroupBox()
{
QGroupBox *box=new QGroupBox(tr("汽车"));
carView=new QTableView;
carView->setEditTriggers(QAbstractItemView::NoEditTriggers);
carView->setSortingEnabled(true);
carView->setSelectionBehavior(QAbstractItemView::SelectRows);
carView->setSelectionMode(QAbstractItemView::SingleSelection);
carView->setShowGrid(false);
carView->verticalHeader()->hide();
carView->setAlternatingRowColors(true);
carView->setModel(carModel);
connect(carView,SIGNAL(clicked(QModelIndex)),this,SLOT(showCarDetails(QModelIndex)));
connect(carView,SIGNAL(activated(QModelIndex)),this,SLOT(showCarDetails(QModelIndex)));
QVBoxLayout *layout=new QVBoxLayout;
layout->addWidget(carView,0,0);
box->setLayout(layout);
return box;
}
QGroupBox *MainWindow::createFactorGroupBox()
{
factoryView=new QTableView;
factoryView->setEditTriggers(QAbstractItemView::NoEditTriggers);
factoryView->setSortingEnabled(true);
factoryView->setSelectionBehavior(QAbstractItemView::SelectRows);
factoryView->setShowGrid(false);
factoryView->setAlternatingRowColors(true);
factoryView->setModel(factoryModel);
connect(factoryView,SIGNAL(clicked(QModelIndex)),this,SLOT(changeFactory(QModelIndex)));
QGroupBox *box=new QGroupBox(tr("汽车制造商"));
QGridLayout *layout=new QGridLayout;
layout->addWidget(factoryView,0,0);
box->setLayout(layout);
return box;
}
QGroupBox *MainWindow::createDetailsGroupBox()
{
QGroupBox *box=new QGroupBox(tr("详细信息"));
profileLabel=new QLabel;
profileLabel->setWordWrap(true);
profileLabel->setAlignment(Qt::AlignBottom);
titleLabel=new QLabel;
titleLabel->setWordWrap(true);
titleLabel->setAlignment(Qt::AlignBottom);
attribList=new QListWidget;
QGridLayout *layout=new QGridLayout;
layout->addWidget(profileLabel,0,0,1,2);
layout->addWidget(titleLabel,1,0,1,2);
layout->addWidget(attribList,2,0,1,2);
layout->setRowStretch(2,1);
box->setLayout(layout);
return box;
}
void MainWindow::createMenuBar()
{
QAction *addAction=new QAction(tr("添加"),this);
QAction *deleteAction=new QAction(tr("删除"),this);
QAction *quitAction=new QAction(tr("退出"),this);
addAction->setShortcut(tr("Ctrl+A"));
deleteAction->setShortcut(tr("Ctrl+D"));
quitAction->setShortcut(tr("Ctrl+Q"));
QMenu *fileMenu=menuBar()->addMenu(tr("操作菜单"));
fileMenu->addAction(addAction);
fileMenu->addAction(deleteAction);
fileMenu->addSeparator();
fileMenu->addAction(quitAction);
connect(addAction,SIGNAL(triggered(bool)),this,SLOT(addCar()));
connect(deleteAction,SIGNAL(triggered(bool)),this,SLOT(delCar()));
connect(quitAction,SIGNAL(triggered(bool)),this,SLOT(close()));
}
void MainWindow::decreaseCarCount(QModelIndex index)
{
int row = index.row();
int count=carModel->rowCount();
if(count==0)
factoryModel->removeRow(row);
}
void MainWindow::showCarDetails(QModelIndex index)
{
QSqlRecord record=carModel->record(index.row());
QString factory=record.value("manufactory").toString();
QString name=record.value("name").toString();
QString year = record.value("year").toString();
QString carId=record.value("carid").toString();
showFactorytProfile(indexOfFactory(factory));
titleLabel->setText(tr("品牌:%1 (%2)").arg(name).arg(year));
titleLabel->show();
QDomNodeList cars=carData.elementsByTagName("car");
for(int i=0;i<cars.count();i++)
{
QDomNode car=cars.item(i);
if(car.toElement().attribute("id") == carId)
{
getAttribList(car.toElement());
break;
}
}
if(!attribList->count() == 0)
attribList->show();
}
void MainWindow::getAttribList(QDomNode car)
{
attribList->clear();
QDomNodeList attribs=car.childNodes();
QDomNode node;
QString attribNumber;
for(int j=0;j<attribs.count();j++)
{
node=attribs.item(j);
attribNumber=node.toElement().attribute("number");
QListWidgetItem *item=new QListWidgetItem(attribList);
QString showText(attribNumber + ": " + node.toElement().text());
item->setText(tr("%1").arg(showText));
}
}
QModelIndex MainWindow::indexOfFactory(const QString &factory)
{
for(int i=0;i<factoryModel->rowCount();i++)
{
QSqlRecord record=factoryModel->record(i);
if(record.value("manufactory")==factory)
return factoryModel->index(i,1);
}
return QModelIndex();
}
void MainWindow::readCarData()
{
if(!file->open(QIODevice::ReadOnly))
return;
if(!carData.setContent(file))
{
file->close();
return;
}
file->close();
}
void MainWindow::removeCarFromDatabase(QModelIndex index)
{
carModel->removeRow(index.row());
}
void MainWindow::removeCarFromFile(int id)
{
QDomNodeList cars=carData.elementsByTagName("car");
for(int i=0;i<cars.count();i++)
{
QDomNode node=cars.item(i);
if(node.toElement().attribute("id").toInt() == id)
{
carData.elementsByTagName("archive").item(0).removeChild(node);
break;
}
}
}
void MainWindow::addCar()
{
}
void MainWindow::changeFactory(QModelIndex index)
{
QSqlRecord record=factoryModel->record(index.row());//取出用户选择的这条制造商记录
QString factoryId=record.value("id").toString();//获取以上选择汽车制造商的主键
carModel->setFilter("id='"+ factoryId +"'");
showFactorytProfile(index);
}
void MainWindow::delCar()
{
QModelIndexList selection=carView->selectionModel()->selectedRows(0);
if(!selection.empty())
{
QModelIndex idIndex=selection.at(0);
int id=idIndex.data().toInt();
QString name=idIndex.sibling(idIndex.row(),1).data().toString();
QString factory=idIndex.sibling(idIndex.row(),2).data().toString();
QMessageBox::StandardButton button;
button=QMessageBox::question(this,tr("删除汽车记录"),
QString(tr("确认删除由'%1'生产的'%2'吗?").arg(factory).arg(name)),QMessageBox::Yes | QMessageBox::No);
if(button == QMessageBox::Yes)
{
removeCarFromFile(id);
removeCarFromDatabase(idIndex);
decreaseCarCount(indexOfFactory(factory));
}
else
{
QMessageBox::information(this,tr("删除汽车记录"),tr("请选择要删除的记录。"));
}
}
}
void MainWindow::showFactorytProfile(QModelIndex index)
{
QSqlRecord record=factoryModel->record(index.row());
QString name=record.value("manufactory").toString();
int count=carModel->rowCount();
profileLabel->setText(tr("汽车制造商:%1\n产品数量:%2").arg(name).arg(count));
profileLabel->show();
titleLabel->hide();
attribList->hide();
}
创建xml文件,右键创建resourse文件夹,将xml文件放在res文件下
将xml文件命名为attribs.xml
<?xml version="1.0" encoding="UTF-8"?>
<archive>
<car id="1" >
<attrib number="01">排量:2393ml</attrib>
<attrib number="02">价格:8.98万元</attrib>
<attrib number="03">排放:欧4</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:130/6000</attrib>
</car>
<car id="2" >
<attrib number="01">排量:1600ml</attrib>
<attrib number="02">价格:43.26万元</attrib>
<attrib number="03">排放:欧3</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:68/5800</attrib>
</car>
<car id="3" >
<attrib number="01">排量:2393ml</attrib>
<attrib number="02">价格:11.25万元</attrib>
<attrib number="03">排放:欧3带</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:74/6000</attrib>
</car>
<car id="4" >
<attrib number="01">排量:1997ml</attrib>
<attrib number="02">价格:15.38万元</attrib>
<attrib number="03">排放:欧3带</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:99/6000</attrib>
</car>
<car id="5" >
<attrib number="01">排量:1600ml</attrib>
<attrib number="02">价格:6.58万元</attrib>
<attrib number="03">排放:欧3</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:65/5600</attrib>
</car>
<car id="6" >
<attrib number="01">排量:1997ml</attrib>
<attrib number="02">价格:16.08万元</attrib>
<attrib number="03">排放:欧4</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:108/6000</attrib>
</car>
<car id="7" >
<attrib number="01">排量:1781ml</attrib>
<attrib number="02">价格:7.98万元</attrib>
<attrib number="03">排放:国3</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:70/5200</attrib>
</car>
<car id="8" >
<attrib number="01">排量:1984ml</attrib>
<attrib number="02">价格:19.58万元</attrib>
<attrib number="03">排放:欧4</attrib>
<attrib number="04">油耗:7.01(90km/h) 8.31(120km/h)</attrib>
<attrib number="05">功率:85/5400</attrib>
</car>
</archive>
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include<QDialog>
#include<QFile>
#include "connectdlg.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ConnDlg dialog;
if(dialog.exec() != QDialog::Accepted)
return -1;
QFile *carDetails=new QFile(":/attribs.xml");
MainWindow window("factory","cars",carDetails);
window.show();
//dialog.show();
//MainWindow w;
//w.show();
return a.exec();
}