Survey
(一)Skins technique survey
I: Mplayer
II: Qt support change the backend or background image
① Introduction of resource mechanism
② methods of setting and changeing background image
(二) QSqlite usage & presentation
① General Information about QSQLITE
② From the SQLite project description
③ advantages of SQLite
④ basic knowledge of QtSql model of Qt
(一)Skins technique survey
I: Mplayer
Skin technique of Mplayer is implemented by resource file and configuration file that are usually compressed. Resource file include images that is need for changing of skin.Generally,each skin interface own its folder that contain corresponding images and configuration file.Configuration file is usually stored by XML form or JaveSripe.Skin application get informations from configuration by reading and parsing it.The information contains some useful message,such as the size of image,station,color.transparence.
II: Qt support change the backend or background image
① Introduction of resource mechanism
GUI applications generally use many images. There are several methods for providing images to the application.
The most common are the following:
1: Storing images in files and loading them at run-time.
2: Including XPM files in the source code. (This works because XPM files are also valid C++ files.)
3: Using Qt's resource mechanism.
Here we use Qt's resource mechanism because it is more convenient than loading files at run-time,and it works with any supported file format. We have chosen to store the images in the source tree in a subdirectory called images.To make use of Qt's resource system, we must create a resource file and add a line to the .pro file that identifies the resource file.For example, we have called the resource file spreadsheet.qrc, so we put the following line in the .pro file:
RESOURCES = spreadsheet.qrc
The resource file itself uses a simple XML format. Here's an extract from :
<RCC>
<qresource>
<file>images/icon.png</file>
...
<file>images/girl.png</file>
</qresource>
</RCC>
② methods of setting and changeing background image
There are two ways to set the background image in Qt as following
A:The first one: the code can be described
QPalette pallete;
pallete.setBrush(QPalette::Base, QBrush(QPixmap("./image/1.bmp")));
skin.setPalette(pallete) note: skin is a object
B:The second method
skin.setStyleSheet("background-image: url(:/image/1.bmp);");
In the end,we give a simple example to reinforce the understanding.The source code for this application is spread across shin.h and skin.cpp.Let’s start with the header file:
#define SKIN_H
#include<QtGui>
#include<QWidget>
#include<iostream>
class Skin:public QDialog
{
Q_OBJECT
public:
Skin(QWidget *parent=0);
~Skin();
protected:
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
public slots:
void changeImage();
private:
int chose ;
QPushButton *button;
QPoint last,pos0;
};
#endif
The resource code of skin.cpp is as following
#include"skin.h"
#include<QHBoxLayout>
#include<QPoint>
using namespace std;
Skin::Skin(QWidget *parent):QDialog(parent)
{
setFixedSize(250,250);
setWindowFlags(Qt::CustomizeWindowHint);
chose=0;
if(0==chose)
{ setStyleSheet(QString::fromUtf8("background-image: url(:/image/0.bmp);"));}
/*QPalette pallete;
pallete.setBrush(QPalette::Base, QBrush(QPixmap("./image/0.bmp")));
setPalette(pallete);
*/
button=new QPushButton(tr("chageskin"));
button->setFixedSize(100,30);
QFont font("Helvetica", 12, QFont::Bold);
button->setFont(font);
button->setStyleSheet(QString::fromUtf8("background-color: RGBA(255,255,255,0);"));
QHBoxLayout *layout = new QHBoxLayout;
layout->setContentsMargins(10,10,145,200);
layout->addWidget(button);
this->setLayout(layout);
QObject::connect(button,SIGNAL(clicked()),this,SLOT(changeImage()));
}
Skin::~Skin()
{ }
void Skin::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton)
last=e->globalPos();
pos0=e->globalPos()-e->pos();
}
void Skin::mouseMoveEvent(QMouseEvent *e)
{
if(!(e->buttons()&Qt::LeftButton)) //note: buttons()button()
return;
QPoint newpos = e->globalPos();
QPoint upleft = pos0+newpos-last;
move(upleft);
}
void Skin::changeImage()
{
cout<<"chose="<<chose<<endl;
chose++;
if(4==chose)
chose=0;
switch(chose)
{
case 0:
this->setStyleSheet(QString::fromUtf8("background-image: url(:/image/1.bmp);"));
break;
case 1:
this->setStyleSheet(QString::fromUtf8("background-image: url(:/image/2.bmp);"));
break;
case 2:
this->setStyleSheet(QString::fromUtf8("background-image: url(:/image/3.bmp);"));
break;
case 3:
this->setStyleSheet(QString::fromUtf8("background-image: url(:/image/4.bmp);"));
break;
}
}
There is outcome of this application when it is executed.you can change the background image by chicking the “changeskin” button.
It is simple for us to code the *.qrc and main.cpp ,so they are omitted here
(二) QSqlite usage & presentation
① General Information about QSQLITE
QSQLite will be a Qt database driver for the SQLite Database. Using this driver all Qt applications can easily access the SQLite database through Qt's common SQL interface.The Qt SQLite plugin makes it possible to access SQLite databases. SQLite is an in-process database, which means that it is not necessary to have a database server. SQLite operates on a single file, which must be set as the database name when opening a connection. If the file does not exist, SQLite will try to create it. SQLite also supports in-memory databases, simply pass ":memory:" as the database name.
There is a need for this driver, because many projects need a SQL database, but only a few users want to run a big database like MySQL or Oracle. As a result a small file based database like SQLite are needed.
SQLite has some restrictions regarding multiple users and multiple transactions. If you try to read/write on a resource from different transactions, your application might freeze until one transaction commits or rolls back. The Qt SQLite driver will retry to write to a locked resource until it runs into a timeout (see QSQLITE_BUSY_TIMEOUT at QSqlDatabase::setConnectOptions()).
In SQLite any column, with the exception of an INTEGER PRIMARY KEY column, may be used to store any type of value. For instance, a column declared as INTEGER may contain an integer value in one row and a text value in the next. This is due to SQLite associating the type of a value with the value itself rather than with the column it is stored in. A consequence of this is that the type returned by QSqlField::type() only indicates the field's recommended type. No assumption of the actual type should be made from this and the type of the individual values should be checked.
The driver is locked for updates while a select is executed. This may cause problems when using QSqlTableModel because Qt's item views fetch data as needed (with QSqlQuery::fetchMore() in the case of QSqlTableModel).
You can find information about SQLite on http://www.sqlite.org.
② From the SQLite project description:
SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine. -- quoted from www.sqlite.org.
According to the comments in the source files, the code is in the public domain. See the SQLite Copyright page on the SQLite web site for further information. The SQLite library reads and writes directly to and from the database files on disk
SQLite is the most widely deployed SQL database engine in the world. It is used in countless desktop computer applications as well as consumer electronic devices including cellphones, PDAs, and MP3 players. The source code for SQLite is in the public domain.
③ advantages of SQLite
1: Wider application,the sqlite is based on C code
2: read and write directly to and from the database files on disk when you need permanent storage,the database file can be stored in memory for temporary storage .Both don’t need extra server side process.
3:open code and is less than 30000 lines with good comments
4: self-contained, embeddable, zero-configuration and doesn’t need administrator
5:faster than c/s model database in term of speed
6:using API is easy and etc.
④ basic knowledge of QtSql mode of Qt
QtSql Module Hierarchy
Layer | Description |
Driver Layer | This comprises the classes QSqlDriver, QSqlDriverCreator<T>, QSqlDriverCreatorBase, QSqlDriverPlugin, and QSqlResult. This layer provides the low-level bridge between the specific databases and the SQL API layer. See SQL Database Drivers for more information. |
SQL API Layer | These classes provide access to databases. Connections are made using the QSqlDatabase class. Database interaction is achieved by using the QSqlQuery class. In addition to QSqlDatabase and QSqlQuery, the SQL API layer is supported by QSqlError, QSqlField, QSqlIndex, and QSqlRecord. |
User Interface Layer | These classes link the data from a database to data-aware widgets. They include QSqlQueryModel, QSqlTableModel, and QSqlRelationalTableModel. These classes are designed to work with Qt's model/view framework. |
Connecting to Databases
Note that to use any of these classes, a QCoreApplication object must have been instantiated first. To include the definitions of the module's classes, use the following directive:
#include <QtSql>
To link against the module, add this line to your qmake .pro file:
QT += sql
Before you can use QSqlQuery or QSqlQueryModel to access a database, you must create at least one database connection.QtSql model use driver plugins to communicate with different database interface
Driver name | DBMS |
IBM DB2 (version 7.1 and above) | |
Borland InterBase | |
MySQL | |
Oracle Call Interface Driver | |
Open Database Connectivity (ODBC) - Microsoft SQL Server and other ODBC-compliant databases | |
PostgreSQL (versions 7.3 and above) | |
SQLite version 2 | |
SQLite version 3 | |
Sybase Adaptive Server |
QSqlDatabase db = QSqlDatebase::addDatabase(“QSQLITE”);
Db.setDatabasename(“:memory”);
Note:the “:memory”is the only name to use for that sqlite create memory database.
Executing SQL Statements
The QSqlQuery class provides an interface for executing SQL statements and navigating through the result set of a query.
Executing a Query
To execute an SQL statement, simply create a QSqlQuery object and call QSqlQuery::exec() like this:
QSqlQuery query;
query.exec("SELECT name, salary FROM employee WHERE salary > 50000");
The QSqlQuery constructor accepts an optional QSqlDatabase object that specifies which database connection to use. In the example above, we don't specify any connection, so the default connection is used.
If an error occurs, exec() returns false. The error is then available as QSqlQuery::lastError().
Navigating the Result Set
QSqlQuery provides access to the result set one record at a time. After the call to exec(), QSqlQuery's internal pointer is located one position before the first record. We must call QSqlQuery::next() once to advance to the first record, then next() again repeatedly to access the other records, until it returns false. Here's a typical loop that iterates over all the records in order:
while (query.next()) {
QString name = query.value(0).toString();
int salary = query.value(1).toInt();
qDebug() << name << salary;
}
Inserting, Updating, and Deleting Records
QSqlQuery can execute arbitrary SQL statements, not just SELECTs. The following example inserts a record into a table using INSERT:
QSqlQuery query;
query.exec("INSERT INTO employee (id, name, salary) "
"VALUES (1001, 'Thad Beaumont', 65000)");
If you want to insert many records at the same time, it is often more efficient to separate the query from the actual values being inserted. This can be done using placeholders. Qt supports two placeholder syntaxes: named binding and positional binding. Here's an example of named binding:
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
"VALUES (:id, :name, :salary)");
query.bindValue(":id", 1001);
query.bindValue(":name", "Thad Beaumont");
query.bindValue(":salary", 65000);
query.exec();
Here's an example of positional binding:
QSqlQuery query;
query.prepare("INSERT INTO employee (id, name, salary) "
"VALUES (?, ?, ?)");
query.addBindValue(1001);
query.addBindValue("Thad Beaumont");
query.addBindValue(65000);
query.exec();
Updating a record is similar to inserting it into a table:
QSqlQuery query;
query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003");
You can also use named or positional binding to associate parameters to actual values.Finally, here's an example of a DELETE statement:
QSqlQuery query;
query.exec("DELETE FROM employee WHERE id = 1007");
There is a example for strengthen comprehend of QSqlite useage
#ifndef CONNECTION_H
#define CONNECTION_H
#include <QtCore>
#include <QMessageBox>
#include <QtSql>
#include <QStringList>
#include <iostream>
#include <QApplication>
#include <QTime>
#include <QVariant>
#include <QDebug>
#include <stdlib.h>
using namespace std;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");
if (!db.open()) {
QMessageBox::critical(0, QObject::tr("can't open the datebase please read SQL driver document/n"),
QObject::tr("exit by tabbing the Cancel button"),
QMessageBox::Cancel, QMessageBox::NoButton);
return false;
}
QSqlQuery query;
bool bSuccess = query.exec("CREATE TABLE test (id INT PRIMARY KEY,"
"name VARCHAR,"
"nation VARCHAR,"
"telephone VARCHAR)");
if(bSuccess)
qDebug() << QObject::tr("create database sucessfully/n");
else
qDebug() << QObject::tr("fault to create datebase/n");
query.exec("SELECT * FROM test");
QSqlRecord rec = query.record();
qDebug() << QObject::tr("each item's record numbers" )<< rec.count();
query.prepare("INSERT INTO test (id,name,nation,telephone)""VALUES (:id, :name,:nation,:telephone)");
int records = 10;
for(int i=0;i<records;i++) {
query.bindValue(":id", i);
query.bindValue(":name", "Yang");
query.bindValue(":nation", "china");
query.bindValue(":telephone", "028-25639874");
bSuccess = query.exec();
if(!bSuccess) {
QSqlError lastError = query.lastError();
qDebug() << lastError.driverText()<<QString(QObject::tr("insert unsucessfully"));
}
}
//select the id>5
query.exec("SELECT id,name,telephone FROM test WHERE id>5 ");
while(query.next())
{
int id = query.value(0).toInt();
QString name = query.value(1).toString();
QString telephone = query.value(2).toString();
qDebug()<<"id="<<id<<" "<<"name="<<name<<"telephone="<<telephone<<endl;
}
//update
query.exec("UPDATE test SET telephone='13541193799' WHERE id=7");
query.exec("SELECT id,name,telephone FROM test WHERE id=7 ");
cout<<"update telephone=135*****of id=7"<<endl;
while(query.next())
{
int id = query.value(0).toInt();
QString name = query.value(1).toString();
QString telephone = query.value(2).toString();
qDebug()<<"id="<<id<<" "<<"name="<<name<<"telephone="<<telephone<<endl;
}
//delete id=6
query.exec("DELETE FROM test WHERE id=6");
cout<<"delete id=6 later the detail is "<<endl;
query.exec("SELECT id,name,telephone FROM test WHERE id>5 ");
while(query.next())
{
int id = query.value(0).toInt();
QString name = query.value(1).toString();
QString telephone = query.value(2).toString();
qDebug()<<"id="<<id<<" "<<"name="<<name<<"telephone="<<telephone<<endl;
}
return 0;
}
#endif
The result of this application
and