前段时间在学习Qt,边学边做了个小的程序“河南师范大学宿舍报修系统”,现在终于有空总结一下。其中部分代码源自网络,因已忘记出处,在此一并指出,尊重原作者的相关权益。
-
编码支持:
QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030"));
-
Boost库里面的线程安全的模板单体类:
template struct Singleton { struct object_creator { object_creator(){ Singleton::instance(); } inline void do_nothing()const {} }; static object_creator create_object; public: typedef T object_type; static object_type& instance() { static object_type obj; create_object.do_nothing(); return obj; } }; template typename Singleton::object_creator Singleton::create_object;
使用方法:
QDevWing& devwing = Singleton::instance();
-
Qt对MD5的支持:
QObject::tr(QCryptographicHash::hash(str.toAscii(),QCryptographicHash::Md5).toHex());
-
Qt中的SQLite3数据库操作:
1)首先需要修改项目文件(pro文件),添加或者修改以下语句:
QT += sql
2)引入以下头文件:
QtSql
3)使用QSqlDatabase类和QSqlQuery进行数据库操作
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
QString appDir(QApplication::applicationDirPath());
db.setDatabaseName(appDir.append("/").append(dbName));
//qDebug()<
-
Qt Designer与ui文件的使用
利用Qt Designer设计好界面后,保存成ui文件,导入项目,编译,会自动生成“ui_文件名.h”文件。这样的界面的使用方法之一,即多重继承方式:
1)引入自动生成的这个头文件;
2)创建类,继承一个Qt的UI类以及这个生成的ui类:
class LoginDialog : public QDialog,
public Ui::Dialog
{
Q_OBJECT
public:
LoginDialog(QDialog* = 0);
public slots:
virtual void accept();
};
3)在这个子类中就可以很方便的使用ui组件了:
-
首先,需要在构造函数中安装UI:
this->setupUi(this);
-
之后,可以使用开始以下的代码来访问ui组件:
this->edit_ID->setFocus();
-
设置Qt应用程序的图标:
1)在工程目录下创建RC文件,例如reportSystem.rc。内容是:
IDI_ICON1ICONDISCARDABLE"reportSystem.ico"
其中的reportSystem.ico即为要设置的图标。
2)在pro文件中添加一行:
RC_FILE = reportSystem.rc
-
信号和槽机制:
1)自动绑定的信号和槽:
如有ui组件名为btn_finished,也即它是一个按钮,其单击信号自动绑定的槽为on_btn_finished_clicked(),即在对象名前加上on_,对象名后加上下划线和信号名。因此,如果想要为该按钮的单击事件添加处理代码,只需在该ui组件所在的类中声明并实现on_btn_finished_clicked()函数,声明需要写在private slots中。其它的组件和事件类似,如action组件actUserInfo的触发信号对应的槽为on_actUserInfo_triggered()。
2)手工绑定的信号和槽:
如果要绑定的槽的函数名不符号以上的要求,或者想自己创建槽,则需要手工绑定信号和槽。
首先,需要创建槽函数:在类的private slots声明区域中声明成员函数,如void registerUser(const QString&)。槽函数除了可以像一般的成员函数一样使用(此时返回值有用)外,还可以绑定某(些)信号,成为信号处理函数。某信号的槽必须与该信号拥有相同的参数签名。
其次,绑定信号和槽:如在类的构造函数中写上:
connect(this->l_register,SIGNAL(linkActivated(QString)),this,SLOT(registerUser(QString)));
connect函数是QObject类的成员函数,用于手工绑定信号和槽。第一个参数是触发信号的对象,第二个参数是信号类型,用宏SIGNAL()封装。第三个参数是槽对象,第四个参数是槽函数,用SLOT()宏封装。
-
Q_OBJECT
Qt应用程序中的所有用户自定义UI类都需要继承自某一Qt预定义的UI类,同时需要在类声明中加上Q_OBJECT,占据一行,并且使用qmake,这样才能完整地拥有Qt的强大功能(元对象),如信号和槽机制,运行时类型信息和动态属性系统。
-
QSetting
QSetting用于在系统中保存配置信息。不同的系统有不同的保存位置,如Windows中就保存在注册表中,Linux中则保存在配置文件中。比如:
1)创建对象,指定保存节点:QSettings settings(tr("devwing"),tr("reportSystem"));
2)设置值:settings.setValue("uID","1");
3)获取值:QString uStr = settings.value("uID","").toString();
以上的例子在windows xp中将在注册表的HKEY_CURRENT_USER/Software/下建立devwing/reportSystem项,并添加字符串项uID,值为"1"。
-
创建系统托盘图标
1)在MainWindow中加入私有成员QSystemTrayIcon* trayIcon;
2)在MainWindow的构造函数中加入以下代码以创建系统托盘:
QIcon icon(":/new/devwing/reportSystem.ico");//创建QIcon对象,参数是图标资源,值为项目的资源文件中图标的地址
trayIcon = new QSystemTrayIcon(this);
trayIcon->setIcon(icon);//将创建的QIcon对象作为系统托盘图标
trayIcon->show();//显示托盘图标
QMenu *trayMenu = new QMenu(this);//创建菜单
trayMenu->addAction(ui->actReportAdd);//为托盘菜单添加菜单项
trayMenu->addSeparator();//为托盘菜单添加分隔符
trayIcon->setContextMenu(trayMenu);//将创建菜单作为系统托盘菜单
trayIcon->setToolTip(tr("河南师范大学宿舍报修系统"));//设置系统托盘提示
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onSystemTrayIconClicked(QSystemTrayIcon::ActivationReason)));//为系统托盘绑定单击信号的槽
3)在系统托盘显示气泡消息提示:
trayIcon->showMessage(tr("河南师范大学宿舍报修系统"), tr("最小化到这里"), QSystemTrayIcon::Information, 5000);
4)隐藏系统托盘图标:
trayIcon->hide();
-
Qt中指针的自动销毁
QT扩展了C++,如果指针对象有父对象时,可以不用显式释放内存,在删除Q类(QObject继承类)指针或Q类对象在析构的时候,同时会删除或析构他的子对象。这里的父子关系不是指继承关系,而是指构造时在构造函数的参数中指定的父类,或通过setParent()函数指定的父类。我们需要显式释放的是那些没有父对象的孤立的指针。
-
MainWindow的状态栏
1)设置字体:
QFont font;
font.setPointSize(10);
ui->statusBar->setFont(font);
2)显示消息:
ui->statusBar->showMessage(tr("准备就绪"));
3)清除消息:
ui->statusBar->clearMessage();
-
退出程序
默认情况下,Qt应用程序在用户关闭最后一个窗口时就退出。这是由QApplication::quitOnLastWindowClosed属性决定的。通过QApplication::setQuitOnLastWindowClosed(false)可以阻止Qt应用程序的自动退出。这样可以配合系统托盘实现显示和隐藏程序窗口的功能。
-
MainWindow居中显示
默认情况下,MainWindow不居中显示。但它提供了move函数,可以达到相同的效果:
QDesktopWidget* desktop = QApplication::desktop();
move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);
-
QList模板类
QList模板类用于链表操作,它重载了<<等运算符,可以简化操作。QStringList继承自QList,它也继承了这些运算符。如:
QStringList head;
head<
-
QItemDelegate与重写QTableView编辑器
一般情况下,QTableView的编辑器是文本形式的,即当点击QTableView的某一单元格对数据进行修改时,都是显示一个文本框。如果用于需要改变编辑器,则需要为其指定QItemDelegate。这里以下拉框为例进行说明:
1)首先,需要创建自定义类SelectDelegate,它继承自QItemDelegate,并声明Q_OBJECT宏。
2)在该类中重载以下公有成员函数:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;//返回以parent构造的UI控件,如 new QComboBox(parent);
void setEditorData(QWidget *editor, const QModelIndex &index) const;//已知模型中的值,设置编辑器的值
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;//已知编辑器的值,设置模型中的值
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;//设置编辑器的几何尺寸,如 editor->setGeometry(option.rect);
3)这样,就可以在QTableView中设置某一列或某一行或所有单元格的编辑器:
SelectDelegate* delegate = new SelectDelegate();
ui->tableView->setItemDelegateForColumn(1,delegate);//设置第2列的编辑器的下拉框
-
QTableView与QSqlTableModel
QTableView是表格视图类,可以通过为其指定model(模型)来配置它的数据及操作。例如,如果设置其模型为QSqlTableModel的对象,它的数据将来自于数据库中查询出来的数据,对它的修改将影响数据库。
1)创建QSqlTableModel对象,并进行必要的初始化:
QSqlTableModel *model = new QSqlTableModel;
model->setTable("record");//设置数据来源于数据库中的哪张表
model->setSort(3,Qt::DescendingOrder);//设置排序规则:按第4列降序排列
model->setFilter("User='admin'");//设置过滤器:这里要求用户为admin
model->setEditStrategy(QSqlTableModel::OnManualSubmit);//设置编辑策略:手工提交数据。可能的值还有:QSqlTableModel::OnFieldChange(改变单元格时提交)、QSqlTableModel::OnRowChange(改变行时交)。
model->select();//查询数据
for(int i=0;i
2)为QTableView绑定模型:
ui->tableView->setModel(model);
3)对QTableView进行设置:
ui->tableView->setColumnHidden(0,true);//隐藏第1列
4)设置焦点到某一个单元格中以编辑:
ui->tableView->edit(model->index(0,1));//modex->(index(0,1))用于指定第1行第2列的单元格
5)设置model某一单元格中的值:
model->setData(model->index(0,6),tr("尚未处理"));
6)获取所有选择的行:
QItemSelectionModel *selectionModel = ui->tableView->selectionModel();
QModelIndexList indexes = selectionModel->selectedRows();
-
foreach
foreach关键字是Qt对标准C++的扩展,需要先用Qt自带的qmake预编译。也可以使用Q_FOREACH宏,它可以被标准C++编译器识别。foreach用于方便地遍历集合。语法是:
foreach(item, collection){
//...
}
-
MainWindow最大化时的事件处理
1)需要重载MainWindow的保护成员:虚函数virtual void changeEvent(QEvent* event);
2)在changeEvent()函数的实现中,判断事件类别,若为WindowStateChange,而且当前窗口被最大化,则执行相关操作。如:
if(event->WindowStateChange){
if(this->isMaximized()){
ui->actToolText->trigger();
return;
}
}
-
关闭MainWindow时隐藏到系统托盘
1)需要重载MainWindow的保护成员:虚函数virtual void closeEvent(QCloseEvent * event )
2)在closeEvent()函数的实现中,显示系统托盘提示,并隐藏窗口。
trayIcon->showMessage(tr("河南师范大学宿舍报修系统"), tr("最小化到这里"), QSystemTrayIcon::Information, 5000);
hide();
event->ignore();
-
Qt应用程序的发布
首先需要以release方式编译应用程序,将编译好的程序文件复制到发布文件夹。
其次将以下动态链接库复制到发布文件夹中:mingwm10.dll、QtCore4.dll、QtGui4.dll。可以从“Qt安装目录/qt/bin”下面找到它们。
如果用到了其他功能,如OpenGL,则需要将QtOpenGL4.dll也复制到发布文件夹中。
如果应用程序有访问数据库的功能,则不仅要将QtSql4.dll复制到发布文件夹,而且还需要将对应的数据库驱动程序(同样也是dll)复制过来,放到“发布文件夹/sqldrivers”目录下面。可以从可以从“Qt安装目录/qt/plugins/sqldrivers”下面找到它们,如qsqlite4.dll。
如果应用程序含有中文,还需要在发布文件夹下面建立codecs目录,并将“Qt安装目录/qt/plugins/codecs”目录下面的qcncodecs4.dll复制过来。
对于其他以插件方式提供的功能,如imageformats,也需要像上面的方式将所有需要的dll复制过来。
22.为什么将开发的使用数据库的程序发布到其它机器就连接不上数据库?
这是一种解决方法,还有一种通用的解决方法,即在可执行文件目录下写qt.conf文件,把系统相关的一些目录配置写到qt.conf文件里,详细情况情参考Qt Document Reference里的qt.conf部分