Qt学习笔记
前段时间在学习Qt,边学边做了个小的程序“河南师范大学宿舍报修系统”,现在终于有空总结一下。其中部分代码源自网络,因已忘记出处,在此一并指出,尊重原作者的相关权益。 开发环境采用Qt Creator 1.2.1,基于Qt 4.5.3。操作系统为Windows XP sp3。
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组件了:
设置Qt应用程序的图标:1)在工程目录下创建RC文件,例如reportSystem.rc。内容是: IDI_ICON1 ICON DISCARDABLE "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_OBJECTQt应用程序中的所有用户自定义UI类都需要继承自某一Qt预定义的UI类,同时需要在类声明中加上Q_OBJECT,占据一行,并且使用qmake,这样才能完整地拥有Qt的强大功能(元对象),如信号和槽机制,运行时类型信息和动态属性系统。 QSettingQSetting用于在系统中保存配置信息。不同的系统有不同的保存位置,如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与QSqlTableModelQTableView是表格视图类,可以通过为其指定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(); foreachforeach关键字是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应用程序的发布
源代码可以从这里下载。 22.为什么将开发的使用数据库的程序发布到其它机器就连接不上数据库? 答:这是由于程序找不到数据库插件而致,可照如下解决方法: 在main函数中加入下面语句: Quote: QApplication::addLibraryPath(strPluginsPath"); strPluginsPath是插件所在目录,比如此目录为/myapplication/plugins 则将需要的sql驱动,比如qsqlmysql.dll, qsqlodbc.dll或对应的.so文件放到 /myapplication/plugins/sqldrivers/ 目录下面就行了 这是一种解决方法,还有一种通用的解决方法,即在可执行文件目录下写qt.conf文件,把系统相关的一些目录配置写到qt.conf文件里,详细情况情参考Qt Document Reference里的qt.conf部分 |