خانه برنامه نویسی پروژه برنامه نویسی Qt و کار با دیتابیس Sqlite – قسمت دوم
پروژه برنامه نویسی کار با دیتا بیس در محیط Qt

پروژه برنامه نویسی Qt و کار با دیتابیس Sqlite – قسمت دوم


۲۰ فروردین ۱۳۹۸
رضا احمدی
869 بازدید
دسته بندی : c++ , Qt creator , برنامه نویسی

در قسمت قبل ما با دیتابیس ها کلاس های موجود در Qt آشنا شدیم و یک دیتابیس را باز کردیم حال نیاز است با دستورات خاصی جدول ها و داده ها را مدیریت کنیم . این دسورات را زبان SQL می گویند که برای کار با پایگاه های داده است.

دستورات SQL

” در کیوت برای اجرای دستورات sql  کلاس خاصی به نام QSqlQuery وجود دارد.در دیتا بیس ها ارسال دستور و دریافت پاسخ را اصطلاحا یک کوئری می گویند.”

همانطور که در بالا گفته شد در این برنامه ما به یک جدول به نام Users نیاز داریم. پس وقتی به دیتا بیس وصل شدین نیاز است ابتدا یک شی از کلاس QSqlQuery اسجاد کنیم:

در کانستراکتور کلاس داریم:

  1. if(createConnection())
  2.     {
  3.         qDebug()<<"connect ok;";
  4.         m_qu=new QSqlQuery(m_db);
  5.         createTable();
  6.     }
  7.     else
  8.     {
  9.         qDebug()<<"Error: can't open database.";
  10.         exit(0);
  11.     }

اگر ایجاد کانشکن موفقیت آمیز بود شی m_qu را ایجاد کن و متد createTable را صدا بزن پیاده سازی این متد به شرح زیر است :

  1. void zxMain::createTable()
  2. {
  3.     if(!m_db.isOpen())
  4.         return;
  5.     if(!m_qu->exec("CREATE TABLE IF NOT EXISTS Users"
  6.               "(id integer PRIMARY KEY AUTOINCREMENT,"
  7.               "fname varchar(32),lname varchar(32),age int,"
  8.               "phone varchar(12),address varchar(128) );"))
  9.        qDebug()<<"createTable:error :"<<m_qu->lastError();  
  10. }

در کلاس QSqlQuery برای اجرای دستورات متد exec(const QString &queru) وجود دارد دستورات sql را به این متد پاس می دهیم و آن را اجرا می کنیم.

نکته در Sql تفاوتی ندارد که کلمات کلیدی آن را با حروف بزگ یا کوچک بنویسم یعنی دستور CREATE با create تفاوتی ندارد.”

در sql  دستور ایجاد یک جدول مانند زیر است :

  1. CREATE TABLE TABLE_NAME (
  2.     column1 datatype,
  3.     column2 datatype,
  4.     column3 datatype,
  5.    ....
  6. );

اما چون ما هر بار که این برنامه را باز میکنیم این دستور صدا زده می شود لذا نیاز است بگویم که اگر این جدول وجود نداشت آن را ایجاد کن :

CREATE TABLE IF NOT EXISTS Users

اگر جدول Users وجود نداشت ایجاد کن آن را.

در این پروژه به دو تابع دیگر برای حذف کاربر و افزودن کاربر نیاز داربم پیاده سازی این متد ها به شرح زیر است :

  1. bool zxMain::addUser(QString fname, QString lname, int age, QString phone, QString address)
  2. {
  3.  
  4.  if(!m_qu->exec("insert into Users(fname,lname,age,phone,address) "
  5.                 "values('"+fname+"', '"+lname+"', "+QString::number(age)+", '"+phone+"', '"+address+"')"))
  6.     {
  7.      qDebug()<<"userAdded:error :"<<m_qu->lastError();
  8.      return false;}
  9.  return true;
  10. }

در sql  برای افزودن یک مقدار جدید به دستور insert into  نیاز شرح کلی کار با این دستور برابر است با :

  1. INSERT INTO TABLE_NAME (column1, column2, column3, ...)
  2. VALUES (value1, value2, value3, ...);

یا بصورت زیر:

  1. INSERT INTO TABLE_NAME
  2. VALUES (value1, value2, value3, ...);

همانطور که می بینید زبان sql یک زبان سطح بالا می باشد و درک کلمات و روند برنامه برای انسان بسیار راحت است. پیاده سازی متد حذف کاربر:

  1. bool zxMain::deleteUser(int id)
  2. {
  3.     if(!m_qu->exec("DELETE FROM Users "
  4.                    "WHERE id = "+QString::number(id)+";"))
  5.        {
  6.         qDebug()<<"deleteUser: error:"<<m_qu->lastError();
  7.         return false;
  8.     }
  9.     return true;
  10. }

با استفاده از دستور delete می توان مقداری را حذف کرد .در خطوط بالا گفته شده از جدول کاربران هرچه را که هست پاک کن به شرطی که فیلد id برابر با مقدار فلان باشد.

بصورت کلی:

DELETE FROM table_name WHERE condition;

متد بروزرسانی مشخصات کاربر را نیز پیاده سازی کردیم که در این برنامه از آن استفاده نکردیم زیرا در کیوت میتوان بصورت خودکار تغییرات ذخیره شده در Qtableview را در جدول متناسبش ذخیره کرد.

  1. bool zxMain::updateUser(int id, QString fname, QString lname, int age, QString phone,QString address)
  2. {
  3.     if(!m_qu->exec("update Users "
  4.                "set fname= '"+fname+"', lname ='"+lname+"', age="+QString::number(age)+", phone='"+phone+"'"+", address='"+address+"' "
  5.                "where id="+QString::number(id)))
  6.     {
  7.         qDebug()<<"updateUser: error :"<<m_qu->lastError();
  8.         return false;
  9.     }
  10.     return true;
  11. }

پیاده سازی متدهای مربوط به فرم طراحی:

ابتدا برای اینکه جدولی را از دیتا بیس به یک شی از کلاس QTabelView پاس بدهیم نیاز به یک شی از کلاس QSqlTableModel  داریم اگر نام این شی را m_tbModel بگذاریم پس از ایجاد کانشکن و ایجاد تیبل می بایست این شی ارتباط بین جدولUsers و ویدجت tb_Users را برقرار کند.

پس کانستراکتور کلاس به شرح زیر می باشد :

  1. ...
  2. if(createConnection())
  3.     {
  4.         qDebug()<<"connect ok;";
  5.         m_qu=new QSqlQuery(m_db);
  6.         createTable();
  7.         m_tbModel=new QSqlTableModel(this,m_db);
  8.         m_tbModel->setTable("Users"); //نام جدول مورد نظر
  9.         m_tbModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//در این خط گفته شده وقتی فیلدی در جدول تغییر کرد آن را دریتا بیس لحاظ نکن و منتظر بمان تا دستور ذخیره بصورت دستی وارد شود.
  10.         m_tbModel->select();
  11.         ui->tb_Users->setModel(m_tbModel);
  12.         ui->tb_Users->setColumnWidth(0,20);
  13.         ui->tb_Users->setColumnWidth(1,100);
  14.         ui->tb_Users->setColumnWidth(2,100);
  15.         ui->tb_Users->setColumnWidth(3,20);
  16.         ui->tb_Users->setColumnWidth(4,100);
  17.         ui->tb_Users->setColumnWidth(5,180);
  18.     }
  19.     else
  20.     {
  21. ...

در دستور : m_tbModel=new QSqlTableModel(this,m_db); ارتباط این شی با دیتابیس m_db برقرار شده و برای اینکه این model  را درون فرم طراحی و جدول مورد نظر قرار دهیم کافی است:

ui->tb_Users->setModel(m_tbModel);

در پروژه ما سه کلید داریم به نام btn_addUser,btn_deleteUser,btn_updateUser متناسب با نام آنها سه اسلات جدید به پروژه در فایل zxMain.h ایجاد شده و پیاده سازی آن ها به شرح زیر است :

پیاده سازی متد افزودن کاربر :

  1. void zxMain::btn_addUser()
  2. {
  3.     if(ui->le_firstName->text().isEmpty() || ui->le_lastName->text().isEmpty())
  4.     {
  5.         QMessageBox::warning(this,"خطا","پر کردن فیلدهای نام و نام خانوادگی الزامی است. ");
  6.         return;
  7.     }
  8.     if(addUser(ui->le_firstName->text(),
  9.             ui->le_lastName->text(),
  10.             ui->sb_age->value(),
  11.             ui->le_phone->text(),
  12.             ui->le_address->text()))
  13.     {
  14.         qDebug()<<"added!";
  15.         m_tbModel->select();
  16.         ui->tb_Users->selectRow(m_tbModel->rowCount()-1);
  17.         clearForm();
  18.     }
  19. }

شرط افزودن کاربر جدید این است که فیلد های نام و نام خانوادگی خالی نباشند اگر خالی بودند با دستور return از ادامه روند تابع جلو گیری می شود.

اگر  افزودن کاربر جدید با موفقیت انجام شد با استفاده از دستور زیر تغییرات ایجاد شده در دیتابیس در شی m_tbModel لحاظ می گردد:

m_tbModel->select();

دستور زیر ردیف جدیدی که ایجاد شده در فرم انتخاب میکند:

ui->tb_Users->selectRow(m_tbModel->rowCount()-1);

clearForm()یک متد ساده است تمامی فیلدهای وردوی کاربر را پاک میکند :

  1. void zxMain::clearForm()
  2. {
  3.     ui->le_firstName->clear();
  4.     ui->le_lastName->clear();
  5.     ui->le_phone->clear();
  6.     ui->le_address->clear();
  7. }

پیاده سازی متد ذخیره تغییرات:

  1. void zxMain::btn_updateUsers()
  2. {
  3.     m_tbModel->submitAll();
  4. }

این همان متدی است که مقادیری اگر در جدول تغییر کرده باشند آن ها را در جدول اصلی دیتابیس لحاط میکند.

پیاده سازی متد حذف کاربر:

  1. void zxMain::btn_deleteUser()
  2. {
  3.     int id=m_tbModel->index(ui->tb_Users->currentIndex().row(),0).data().toInt();
  4.     QMessageBox::StandardButton answer=QMessageBox::question(this,"هشدار",
  5.                                                              " آیا میخواهید مشخصات کاربر  ID: "+QString::number(id)+" حذف کنید؟ ");
  6.     if(answer==QMessageBox::Yes)
  7.     {
  8.  
  9.         if(deleteUser(id))
  10.         {
  11.             m_tbModel->select();
  12.             qDebug()<<"remove id: "<<id <<" successfully.";
  13.         }
  14.     }
  15. }

دستور زیر شامل چند قسمت می باشد تا به شماره id  مورد نظر برسیم:

int id=m_tbModel->index(ui->tb_Users->currentIndex().row(),0).data().toInt();

قسمت اول دستور m_tbModel->indec(r,c).data() این دستور مقدار فیلدی را به شماره سطر و ستونی برمی گرداند حال چون همیشه ما مقدار ستون شماره صفر یعنی همان ستون id را می خواهیم و این ستون همیشه یک عدد صحیح است خروجی دیتا را به عدد صحیح با استفاده از دستور toInt() تبدیل کردیم.در قسمت دیگر برای بدست آوردن ردیفی که کاربر آن را انتخاب کرده از فرم طراحی شی m_tb_Users متد currentInsex() را صدا می زنیم وخروجی این تابع که از جنس QModelIndex می یاشد  متد row() را ضدا زدیم تا به مورد مربوطه برسیم.

در خطوط بعدی از کاربر سوال پرسیده شده و درصورت تایید کاربر متد deleteUser() صدا زده می شود و اگر این متد بتواند عملیات مد نظر را انجام دهد نیاز است تغییرات صورت گرفته در دیتابیس به مدل انتقال یابند …

نکته :طول مقادیری که کاربر میتواند وارد کند با توجه دستورات ایجاد جدول در فرم طراحی لحاظ کند مثلا برای شی le_firstName  مقادر maximum length را برابر 32 بگذارید.

دانلود سورس کامل پروژه :

zxMain.h

  1. #ifndef ZXMAIN_H
  2. #define ZXMAIN_H
  3.  
  4. #include <QMainWindow>
  5. #include <QtSql>
  6.  
  7. namespace Ui {
  8. class zxMain;
  9. }
  10.  
  11. class zxMain : public QMainWindow
  12. {
  13.     Q_OBJECT
  14.  
  15. public:
  16.     explicit zxMain(QWidget *parent = 0);   
  17.     ~zxMain();
  18.     bool createConnection();
  19.     void createTable();
  20.     bool addUser(QString fname, QString lname, int age, QString phone,QString address);
  21.     bool updateUser(int id, QString fname, QString lname, int age, QString phone, QString address);
  22.     bool deleteUser(int id);
  23.  
  24.     void clearForm();
  25.  
  26. private:
  27.     Ui::zxMain *ui;
  28.     QSqlDatabase m_db;
  29.     QSqlQuery *m_qu;
  30.     QSqlTableModel *m_tbModel;
  31. private slots:
  32.     void btn_addUser();
  33.     void btn_updateUsers();
  34.     void btn_deleteUser();
  35. };
  36.  
  37. #endif // ZXMAIN_H

zxMain.cpp

  1. #include "zxmain.h"
  2. #include "ui_zxmain.h"
  3. #include <QDebug>
  4. #include <QMessageBox>
  5. //#include <QSqlError>
  6.  
  7. zxMain::zxMain(QWidget *parent) :
  8.     QMainWindow(parent),
  9.     ui(new Ui::zxMain)
  10. {
  11.     ui->setupUi(this);
  12.  
  13.     if(createConnection())
  14.     {
  15.         qDebug()<<"connect ok;";
  16.         m_qu=new QSqlQuery(m_db);
  17.         createTable();        
  18.         m_tbModel=new QSqlTableModel(this,m_db);
  19.         m_tbModel->setTable("Users");
  20.         m_tbModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
  21.         m_tbModel->select();
  22.         ui->tb_Users->setModel(m_tbModel);
  23.         ui->tb_Users->setColumnWidth(0,20);
  24.         ui->tb_Users->setColumnWidth(1,100);
  25.         ui->tb_Users->setColumnWidth(2,100);
  26.         ui->tb_Users->setColumnWidth(3,20);
  27.         ui->tb_Users->setColumnWidth(4,100);
  28.         ui->tb_Users->setColumnWidth(5,180);
  29.     }
  30.     else
  31.     {
  32.         qDebug()<<"Error: can't open database.";
  33.         exit(0);
  34.     }
  35.     connect(ui->btn_addUser,SIGNAL(clicked(bool)),this,SLOT(btn_addUser()));
  36.     connect(ui->btn_updateUsers,SIGNAL(clicked(bool)),this,SLOT(btn_updateUsers()));
  37.     connect(ui->btn_deleteUser,SIGNAL(clicked(bool)),this,SLOT(btn_deleteUser()));    
  38. }
  39.  
  40. zxMain::~zxMain()
  41. {
  42.     delete m_tbModel;
  43.     if(m_db.isOpen())
  44.         m_db.close();
  45.  
  46.     delete m_qu;
  47.     delete ui;
  48. }
  49.  
  50. bool zxMain::createConnection()
  51. {
  52.     m_db= QSqlDatabase::addDatabase("QSQLITE");
  53.     m_db.setDatabaseName("mydb");
  54.     //m_db.setConnectOptions();
  55.     if(!m_db.open())
  56.     {
  57.         qDebug()<<"An error on opening database : " <<m_db.lastError();
  58.         return false;
  59.     }
  60.     return true;
  61. }
  62.  
  63. void zxMain::createTable()
  64. {
  65.     if(!m_db.isOpen())
  66.         return;
  67.     if(!m_qu->exec("CREATE TABLE IF NOT EXISTS Users"
  68.               "(id integer PRIMARY KEY AUTOINCREMENT,"
  69.               "fname varchar(32),lname varchar(32),age int,"
  70.               "phone varchar(12),address varchar(128) );"))
  71.        qDebug()<<"createTable:error :"<<m_qu->lastError();  
  72. }
  73.  
  74. bool zxMain::addUser(QString fname, QString lname, int age, QString phone, QString address)
  75. {
  76.  
  77.  if(!m_qu->exec("insert into Users(fname,lname,age,phone,address) "
  78.                 "values('"+fname+"', '"+lname+"', "+QString::number(age)+", '"+phone+"', '"+address+"')"))
  79.     {
  80.      qDebug()<<"userAdded:error :"<<m_qu->lastError();
  81.      return false;}
  82.  return true;
  83. }
  84.  
  85. bool zxMain::updateUser(int id, QString fname, QString lname, int age, QString phone,QString address)
  86. {
  87.     if(!m_qu->exec("update Users "
  88.                "set fname= '"+fname+"', lname ='"+lname+"', age="+QString::number(age)+", phone='"+phone+"'"+", address='"+address+"' "
  89.                "where id="+QString::number(id)))
  90.     {
  91.         qDebug()<<"updateUser: error :"<<m_qu->lastError();
  92.         return false;
  93.     }
  94.     return true;
  95. }
  96.  
  97. bool zxMain::deleteUser(int id)
  98. {
  99.     if(!m_qu->exec("DELETE FROM Users "
  100.                    "WHERE id = "+QString::number(id)+";"))
  101.        {
  102.         qDebug()<<"deleteUser: error:"<<m_qu->lastError();
  103.         return false;
  104.     }
  105.     return true;
  106. }
  107.  
  108. void zxMain::clearForm()
  109. {
  110.     ui->le_firstName->clear();
  111.     ui->le_lastName->clear();
  112.     ui->le_phone->clear();
  113.     ui->le_address->clear();
  114. }
  115.  
  116. void zxMain::btn_addUser()
  117. {
  118.     if(ui->le_firstName->text().isEmpty() || ui->le_lastName->text().isEmpty())
  119.     {
  120.         QMessageBox::warning(this,"خطا","پر کردن فیلدهای نام و نام خانوادگی الزامی است. ");
  121.         return;
  122.     }
  123.     if(addUser(ui->le_firstName->text(),
  124.             ui->le_lastName->text(),
  125.             ui->sb_age->value(),
  126.             ui->le_phone->text(),
  127.             ui->le_address->text()))
  128.     {
  129.         qDebug()<<"added!";
  130.         m_tbModel->select();
  131.         ui->tb_Users->selectRow(m_tbModel->rowCount()-1);
  132.         clearForm();
  133.     }
  134. }
  135.  
  136. void zxMain::btn_updateUsers()
  137. {
  138.     m_tbModel->submitAll();
  139. }
  140.  
  141. void zxMain::btn_deleteUser()
  142. {
  143.     int id=m_tbModel->index(ui->tb_Users->currentIndex().row(),0).data().toInt();
  144.     QMessageBox::StandardButton answer=QMessageBox::question(this,"هشدار",
  145.                                                              " آیا میخواهید مشخصات کاربر  ID: "+QString::number(id)+" حذف کنید؟ ");
  146.     if(answer==QMessageBox::Yes)
  147.     {
  148.  
  149.         if(deleteUser(id))
  150.         {
  151.             m_tbModel->select();
  152.             qDebug()<<"remove id: "<<id <<" successfully.";
  153.         }
  154.     }
  155. }
مطالب مرتبط

 دیدگاهتان را بنویسید   

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *