在一个应用程序设计中,为了实现一些特定的功能,必领设计自定义对话框。
自定义对话框的设计一般从 QDialog 继承,并且可以采用UI设计器可视化地设计对话框。对话框的调用一般包括创建对话框、传递数据给对话框、显示对话框获取输入、判断对话框单击按钮的返回类型、获取对话框输入数据等过程。
本节将通过实例 samp6_2 来详细介绍这些原理。图 1 是实例 samp6_2 的主窗口,及其设置表格行列数的对话框。
图 1 实例 samp6_2 主窗口及其设置表格行列数的对话框
主窗口采用 QTableView 和 QStandardltemModel、QltemSelectionModel 构成一个通用的数据表格编辑器,设计了 3 个对话框,分别具有不同的功能,并且展示对话框不同调用方式的特点:
?设置表格行列数对话框 QWDialogSize
该对话框每次动态创建,以模态方式显示(必须关闭此对话框才可以返回主窗口操作),对话框关闭后获取返回值,用于设置主窗口的表格行数和列数,并且删除对话框对象,释放内存。
这种对话框创建和调用方式适用于比较简单,不需要从主窗口传递大量数据做初始化的对话框,调用后删除对话框对象可以节约内存。
?设置表头标题对话框 QWDialogHeaders
图 2 是设置表格表头标题的对话框,该对话框在父窗口(本例中就是主窗口)存续期间只创建一次,创建时传递表格表头字符串列表给对话框,在对话框里编辑表头标题后,主窗口获取编辑之后的表头标题。
图 2 设置表格表头标题对话框
注意,对话框以模态方式显示,关闭后只是隐藏,并不删除对象,下次再调用时只是打开己创建的对话框对象。
这种创建和调用方式适用于比较复杂的对话框,需要从父窗口传递大量数据做对话框初始化。下次调用时不需要重复初始化,能提高对话框调用速度,但是会一直占用内存,直到父窗口删除时,对话框才从内存中删除。
?单元格定位与文字设置对话框QWDialogLocate
图 3 是单元格定位和文字设置对话框,该对话框以非模态方式调用,显示对话框时还可以对主窗口进行操作,对话框只是浮动在窗口上方。在对话框里可以定位主窗口表格的某个单元格并设置其文字内容,在主窗口上的表格中单击鼠标时,单元格的行号、列号也会更新在对话框中。对话框关闭后将自动删除,释放内存。
图 3 浮动于主窗口上方的对话框,可交互操作
这种对话框适用于主窗口与对话框需要交互操作的情况,例如用于查找和替换
操作的对话框。
对话框 QWDialogSize 的创建和使用
创建对话框QWDialogSize
实例主窗口从 QMainWindow 继承,主窗口用一个 QTableView 组件作为界面中心组件,设计几个 Action 用于创建主工具栏按钮。主窗口采用QStandardItemModel 作为数据模型,QItemSelectionModel 作为选择模型,界面和主窗口 Model/View 结构的设计前面已经讲过,本节不再详述。
在项目主窗口建立后,要创建如图 1 所示的设置表格行列数的对话框,单
击Qt Creator 的菜单项 File->New File or Project,选择 Qt 类别下的“Qt Designer Form Class”,创建可视化设计的对话框类。在随后出现的向
导里,选择窗口模板为 Dialog without Buttons,并设置自定义对话框的类名。
设置创建的对话框类名称为 QWDialogSize,系统自动生成 qwdialogsize.h、qwdialogsize.cpp 和 qwdialogsize.ui 3 个文件。
QWDialogSize 对话框的界面设计在 UI 设计器里进行,放置界面组件并设置好布局。
对话框的调用和返回值
设计 QWDialogSize 对话框的界面时,在上面放置了两个 QPushButton 按钮,并分别命名为 btnOK 和 btnCancel,分别是“确定”和“取消”按钮,用于获取对话框运行时用户的选择。那么,如何获得用户操作的返回值呢?
在信号与槽编辑器里,将 btnOK 的 clicked() 信号与对话框的 accept() 槽
关联,将 btnCancel 的 clicked() 信号与对话框的reject()槽关联即可,如图 4 所示。
图 4 对话框设计时“确定”和“取消”按钮的信号与槽关联
单击“确定”按钮会执行 accept() 槽(或在代码里调用 accept() 槽函数也是一样的),这会关闭对话框(默认情况下,对话框只是被隐藏,并不被删除),并返回 QDialog::Accepted 作为 exec() 函数的返回值。
单击“取消”按钮会执行 reject() 槽函数,也会关闭对话框,并返回
QDialog::Rejected 作为 exec() 函数的返回值。
完成后的 QWDialogSize 的类完整定义如下:
1.class QWDialogSize : public QDialog
2.{
3. Q_OBJECT
4.public:
5.explicit QWDialogSize(QWidget *parent = 0);
6. ~QWDialogSize();
7. int rowCount();//获取对话框输入的行数
8. int columnCount();//获取对话框输入的列数
9. void setRowColumn(int row, int column); //初始对话框上两个
SpinBox的值
10.private slots:
11.private:
12. Ui::QWDialogSize *ui;
13.};
在 QWDialogSize 的类定义中定义 3 个 public 函数,用于与对话框调用者的数据交互。因为窗体上的组件都是私有成员,外界不能直接访问界面组件,只能通过接口函数访问。
下面是类的接口函数实现代码。在析构函数中弹出一个消息提示对话框,以便观察对话框是何时被删除的。
1.QWDialogSize::~QWDialogSize、
2.{
3. QMessageBox::information (this,"提示","设置表格行列数对话框被删
除"); delete ui;
4.}
5.
6.int QWDialogSize::rowCount()
7.{ //用于主窗口调用获得行数的输入值
8.return ui->spinBoxRow->value();
9.}
10.
11.int QWDialogSize::columnCount()
12.{//用于主窗口调用获得列数的输入值
13. return ui->spinBoxColumn->value();
14.}
15.
16.void QWDialogSize::setRowColumn(int row, int column)
17.{ //初始化数据显示
18. ui->spinBoxRow->setValue(row);
19. ui->spinBoxColumn->setValue(column);
20.}
下面是主窗口中的“设置行数列数”工具栏按钮的响应代码,用于创建、显示对话框,并读取对话框上设置的行数、列数。
1.void MainWindow::on_actTab_SetSize_triggered()
2.{ //模态对话框,动态创建,用过后删除
3. QWDialogSize *dlgTableSize=new QWDialogSize(this);
4. Qt::WindowFlags flags=dlgTableSize->windowFlags();
5. dlgTableSize->setWindowFlags(flags |
Qt::MSWindowsFixedSizeDialogHint);
6. dlgTableSize->setRowColumn(theModel->rowCount(),theModel-
>columnCount ());
7. int ret=dlgTableSize->exec () ;// 以模态方式显示对话框
8.if (ret==QDialog::Accepted)
9. { //OK按钮被按下,获取对话框上的输入,设置行数和列数
10. int cols=dlgTableSize->columnCount();
11. theModel->setColumnCount(cols);
12. int rows=dlgTableSize->rowCount();
13. theModel->setRowCount(rows);
14. }
15. delete dlgTableSize;
16.}
从代码中可以看到,每次单击此工具栏按钮时,对话框都被重新创建。创建后用 QDialog 的 setWindowFlags() 函数将对话框设置为固定大小,然后调用对话框的自定义函数 setRowColumn(),将主窗口数据模型 theModd 的现有的行数和列数显示到对话框上的两个 SpinBox 组件里。
调用对话框的 exec() 函数,以模态显示的方式显示对话框。模态显示方式下,用户只能在对话框上操作,不能操作主窗口,主程序也在此处等待 exec() 函数的返回结果。
当用户单击“确定”按钮关闭对话框后,exec() 返回结果为
QDialogxAccepted,主程序获得此返回结果后,通过对话框的自定义函数
columnCount() 和 rowCount() 获得对话框上新输入的列数和行数,然后设置为数据模型的列数和行数。
最后使用 delete 删除创建的对话框对象,释放内存。所以,关闭对话框时,会出现 QWDialogSize 析构函数里的消息提示对话框。
对话框QWDialogHeaders的创建和使用
对话框的生存期
对话框的生存期是指它从创建到删除的存续区间。前面介绍的设置表格行数和列数的对话框的生存期只在调用它的按钮的槽函数里,因为对话框是动态创建的,调用结束后就会被删除。
而对于图 2 所示的设置表头标题对话框,我们希望在主窗口里首次调用时创建它,对话框关闭时并不删除,只是隐藏,下次调用时再次显示此对话框。只有
在主窗口释放时该对话框才释放,所以这个对话框的生存期在主窗口存续期间。
QWDialogHeaders的定义和实现
设置表头标题的对话框类是 QWDialogHeaders,它也是从 QDialog 继承的可视对话框类。其界面显示使用 QListView 组件,用 QStringListModel 变量管理字符串列表数据,构成 Model/View 结构。对话框上同样有“确定”和“取消”
两个按钮,设置与对话框的 accept() 和 reject() 槽关联。
QWDialogHeaders 类的定义如下:
1.class QWDialogHeaders : public QDialog
2.{
3. Q_OBJECT
4.private:
5. QStringListModel *model;
6.
7.public:
8.explicit QWDialogHeaders(QWidget *parent = 0);
9. ~QWDialogHeaders();
10. void setHeaderList(QStringList& headers);
11. QStringList headerList();
12.private:
13. Ui::QWDialogHeaders *ui;
14.};
QWDialogSize 类接口函数实现的代码如下:
1.QWDialogHeaders::QWDialogHeaders(QWidget *parent) :
2. QDialog(parent),
3. ui(new Ui::QWDialogHeaders)
4.{
5. ui->setupUi(this);
6. model= new QStringListModel;
7. ui->listView->setModel(model);
8.}
9.
10.QWDialogHeaders::~QWDialogHeaders()
11.{
12. QMessageBox::information(this,"提示","设置表头标题对话框被删除");
13. delete ui;
14.}
15.
16.void QWDialogHeaders::setHeaderList(QStringList &headers)
17.{
18. model->setStringList(headers);
19.}
20.
21.QStringList QWDialogHeaders::headerList()
22.{
23. return model->stringList();
24.}
QWDialogHeaders对话框的使用
因为要在主窗口中重复调用此对话框,所以在 MainWindow 的 private 部分定义一个 QWDialogHeaders 类型的指针变量,并且将此指针初始化设置为 NULL,用于判断对话框是否已经被创建。
在 MainWindow 中的定义如下:
下面是主窗口工具栏上的“设置表头标题”按钮的响应代码:
1.void MainWindow::on_actTab_SetHeader_triggered()
2.{//一次创建,多次调用,对话框关闭时只是隐藏
3.if (dlgSetHeaders==NULL) //如果对象没有被创建过,就创建对象
4. dlgSetHeaders = new QWDialogHeaders(this);
5.
6.if (dlgSetHeaders->headerList().count()!=theModel->columnCount())
7. {//如果表头列数变化,重新初始化
8. QStringList strList;
9.for (int i=0;i
题
10. strList.append(theModel-
>headerData(i,Qt::Horizontal,Qt::DisplayRole).toString());
11. dlgSetHeaders->setHeaderList(strList);//用于对话框初始化显示
12. }
13.
14. int ret=dlgSetHeaders->exec();// 以模态方式显示对话框
15. if (ret==QDialog::Accepted) //OK键被按下
16. {
17. QStringList strList=dlgSetHeaders->headerList();//获取对话框
上修改后的StringList
18. theModel->setHorizontalHeaderLabels(strList);// 设置模型的表
头标题
19. }
20.}
在这段代码中,首先判断主窗口的成员变量 dlgSetHeaders 是否为 NULL,如果为 NULL (初始化为 NULL),说明对话框还没有被创建,就创建对话框。
初始化的工作是获取主窗口数据模型现有的表头标题,然后调用对话框的自定义函数 setHeaderList(),设置其为对话框的数据源。
使用 exec() 函数模态显示对话框,然后在“确定”按钮被单击时获取对话框上输入的字符串列表,设置为主窗口数据模型的表头标题。
注意,这里在结束对话框操作后,并没有使用 delete 操作删除对话框对象,这样对话框就只是隐藏,它还在内存中。关闭对话框时不会出现析构函数里的消息提示对话框。
对话框创建时,传递主窗口的指针作为对话框的父对象,即:
所以,主窗口释放时才会自动删除此对话框对象,也就是程序退出时才删除此对话框,才会出现 QWDialogHeaders 析构函数里的消息提示对话框。
对话框QWDialogLocate的创建与使用
非模态对话框
前面设计的两个对话框是以模态(Modal)方式显示的,即用 QDialog::exec() 函数显示。模态显示的对话框不允许鼠标再去单击其他窗口,直到对话框退出。
若使用 QDialog::show(),则能以非模态(Modeless)方式显不对话框。非模
态显示的对话框在显示后继续运行主程序,还可以在主窗口上操作,主窗口和非模态对话框之间可以交互控制,典型的例子是文字编辑软件里的“查找/替换”
对话框。
图 3 中的单元格定位与文字设置对话框以非模态方式显示,对话框类是
QWDialogLocate,它有如下的一些功能:
?主窗口每次调用此对话框时,就会创建此对话框对象,并以 StayOnTop 的方式显示,对话框关闭时自动删除。
?在对话框中可以定位主窗口上 Table View 组件的单元格,并设置单元格的文字。
?在主窗口的 TableView 组件中单击鼠标时,如果对话框己创建,则自动更新对话框上单元格的行号和列号 SpinBox 组件的值。
?主窗口上的 actTab_Locate 用于调用对话框,调用时 actTab_Locate 设置为禁用,当对话框关闭时自动使能 actTab_Locate。这样避免对话框显示时,在主窗口上再次单击“定位单元格”按钮,而在对话框关闭和释放后,按钮又恢复为可用。
对话框 QWDialogLocate 的类定义代码如下(各接口函数的意义和实现在后面介绍):
1.class QWDialogLocate : public QDialog
2.{
3. Q_OBJECT
4.private:
5. void closeEvent(QCloseEvent *event);
6. void showEvent(QShowEvent *event);
7.public:
8.explicit QWDialogLocate(QWidget *parent = 0);
9. ~QWDialogLocate();
10. void setSpinRange(int rowCount, int colCount); //设置最大值
11. void setSpinValue(int rowNo, int colNo);//设置初始值
12.private slots:
13. void on_btnSetText_clicked();
14.private:
15. Ui::QWDialogLocate *ui;
16.};
对话框的创建与调用
对话框 QWDialogLocate 是从 QDialog 继承而来的可视化设计的对话框类,其界面设计不再详述。为了在主窗口中也能操作对话框,需要保留对话框实例对象名,所以在 MainWindow 定义对话框 QWDialogLocate 的一个指针
dlgLocate,并初始化为 NULL。
主窗口上的 actTab_Locate 用于调用此对话框,其 triggered() 信号槽函数代码如下:
1.void MainWindow::on_actTab_Locate_triggered()
2.{//创建 StayOnTop的对话框,对话框关闭时自动删除
3. //通过控制actTab_Locate的enable属性避免重复点击
4. ui->actTab_Locate->setEnabled(false);
5. dlgLocate = new QWDialogLocate(this); //创建对话框,传递指针
6. dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //对话框关闭时自动
删除对话框对象,用于不需要读取返回值的对话框
7. Qt::WindowFlags flags=dlgLocate->windowFlags(); //获取已有flags
8. dlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint); //设
置对话框固定大小,StayOnTop
9. //对话框初始化设置
10. dlgLocate->setSpinRange(theModel->rowCount(),theModel-
>columnCount());
11. QModelIndex curIndex=theSelection->currentIndex();
12. if (curIndex.isValid())
13. dlgLocate->setSpinValue(curIndex.row(),curIndex.column());
14. dlgLocate->show(); //非模态显示对话框
15.}
在这段代码中,使用 QWidget::setAttribute() 函数将对话框设置为关闭时自动删除:
setAttribute() 用于对窗体的一些属性进行设置,当设置为
Qt::WA_DeleteOnClose时,窗口关闭时会自动删除,以释放内存。这与前面两个对话框是不同的,前面两个对话框在关闭时缺省是隐藏自己,除非显式地使用 delete 进行删除。
程序还调用 QWidget::setWindowFlags() 将对话框设置为 StayOnTop 显示:
对话框窗口效果设置后,再设置其初始数据,然后调用 show() 显示对话框。
显示对话框后,主程序继续运行,不会等待对话框的返回结果。鼠标可以操作主窗口上的界面,但是因为 actTab_Locate 被禁用了,不能再重复单击“定位单元格”按钮。
对话框中操作主窗口
在对话框上单击“设定文字”按钮,会在主窗口中定位到指定的单元格,并设定为输入的文字,按钮的代码如下:
1.void QWDialogLocate::on_btnSetText_clicked()
2.{//定位到单元格,并设置字符串
3. int row=ui->spinBoxRow->value(); //行号
4. int col=ui->spinBoxColumn->value();//列号
5.
6. MainWindow *parWind = (MainWindow*)parentWidget(); //获取主窗口
7. parWind->setACellText(row,col,ui->edtCaption->text()); //设置单元
格文字
8.if (ui->chkBoxRow->isChecked()) //行增
9. ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());
10.
11. if (ui->chkBoxColumn->isChecked()) //列增
12. ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
13.}
想要在对话框中操作主窗口,就需要获取主窗口对象,调用主窗口的函数并传递参数。在上面的代码中,通过下面一行语句获得主窗口对象:
parentWidget() 是 QWidget 类的一个函数,指向父窗口。在创建此对话框时,将主窗口的指针传递给对话框的构造函数,即:
所以,对话框的 parentWidget 指向主窗口。然后调用主窗口的一个自定义的public 函数 setACellText(),传递行号、列号和字符串,由主窗口更新指定单元格的文字。
下面是主窗口的 setACellText() 函数的代码:
1.void MainWindow::setACellText(int row, int column, QString text)
2.{//定位到单元格,并设置字符串
3. QModelIndex index=theModel->index(row,column);//获取模型索引
4. theSelection->clearSelection(); //清除现有选择
5. theSelection->setCurrentIndex(index,QItemSelectionModel::Select);
//定位到单元格
6. theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
7.}
这样就实现了在对话框里对主窗口进行的操作,主要是获取主窗口对象,然后调用相应的函数。
主窗口中操作对话框
在主窗口上用鼠标单击 TableView 组件的某个单元格时,如果单元格定位对话框 dlgLocate 己经存在,就将单元格的行号、列号更新到对话框上,实现代码如下:
1.void MainWindow::on_tableView_clicked(const QModelIndex &index)
2.{//单击单元格时,将单元格的行号、列号设置到对话框上
3.if (dlgLocate!=NULL) //对话框存在
4. dlgLocate->setSpinValue(index.row(),index.column());
5.}
因为主窗口中定义了对话框的指针,只要它不为 NULL,就说明对话框存在,调用对话框的一个自定义函数 setSpinValue(),刷新对话框显示界面。
QWDialogLocate 的 setSpinValue() 函数实现如下:
1.void QWDialogLocate::setSpinValue(int rowNo, int colNo)
2.{//设置SpinBox数值
3. ui->spinBoxRow->setValue(rowNo);
4. ui->spinBoxColumn->setValue(colNo);
5.}
窗口的 CloseEvent 事件
对话框和主窗口之间互相操作的关键是要有对方对象的指针,然后才能传递参数并调用对方的函数。在对话框关闭时,还需要做一些处理:将主窗口的
actTab_Locate 重新设置为使能,将主窗口的指向对话框的指针 dlgLocate 重新设置为 NULL。
由于对话框 dlgLocate 是以非模态方式运行的,程序无法等待对话框结束后作出响应,但是可以利用窗口的 CloseEvent 事件。
事件(event)是由窗口系统产生的由某些操作触发的特殊函数,例如鼠标操作、键盘操作的一些事件,还有窗口显示、关闭、绘制等相关的事件。从 QWidget 继承的窗口部件常用的事件函数有如下几种:
?closeEvent():窗口关闭时触发的事件,通常在此事件做窗口关闭时的一些处理,例如显示一个对话框询问是否关闭窗口。
?showEvent():窗口显示时触发的事件。
?paintEvent():窗口绘制事件,第8章介绍绘图时会用到。?mouseMoveEvent():鼠标移动事件。
?mousePressEvent():鼠标键按下事件。
?mouseReleaseEvent():鼠标键释放事件。
?keyPressEvent():键盘按键按下事件。
?keyReleaseEvent():键盘按键释放事件。
要利用某个事件进行一些处理,需要在窗口类里重定义事件函数并编写响应代码。在后面的例子中,将逐渐演示一些事件的用法。
在本例中,要利用对话框的 closeEvent() 事件,在类定义中声明了此事件的函数,其实现代码如下:
1.void QWDialogLocate::closeEvent(QCloseEvent *event)
2.{ //窗口关闭事件,关闭时释放本窗口
3. MainWindow *parWind = (MainWindow*)parentWidget(); //获取父窗口指
针
4. parWind->setActLocateEnable(true);//使能 actTab_Locate
5. parWind->setDlgLocateNull(); //将窗口指针设置为NULL
6.}
在 closeEvent() 事件里,调用主窗口的两个函数,将 actTab_Locate 重新使能,将主窗口内指向对话框的指针设置为 NULL。主窗口中这两个函数的实现代码如下:
1.void MainWindow::setActLocateEnable(bool enable)
2.{
3. ui->actTab_Locate->setEnabled(enable);
4.}
5.void MainWindow::setDlgLocateNull()
6.{
7. dlgLocate=NULL;
8.}
利用 closeEvent() 事件,可以询问窗口是否退出,例如为主窗口添加
closeEvent() 事件的处理,代码如下:
1.void MainWindow::closeEvent(QCloseEvent *event)
2.{ //窗口关闭时询问是否退出
3. QMessageBox::StandardButton result=QMessageBox::question(this, "确
认", "确定要退出本程序吗?
",QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,QMessageBox::N o);
4.if (result==QMessageBox::Yes)
5. event->accept();
6.else
7. event->ignore();
8.}
这样,主窗口关闭时就会出现一个询问对话框,如果不单击“Yes”按钮,程序就不关闭;否则应用程序结束。
利用信号与槽实现交互操作
前面设计的 QWDialogLocate 对话框与主窗口之间的交互釆用互相引用的方式,实现起来比较复杂。另外一种实现方式就是利用 Qt 的信号与槽机制,设计相应的信号和槽,将信号与槽关联起来,在进行某个操作时发射信号,槽函数自动响应。
对 MainWindow 和 QWDialogLocate 稍作修改,采用信号与槽机制实现交互操作。
下面是 MainWindow 类定义中与此相关的定义,包括两个槽函数和一个信号:
1.class MainWindow : public QMainWindow
2.{
3.public slots:
4. void setACellText (int row, int column, QString &text) ;//设
置单元格内容
5. void setActLocateEnable (bool enable) ; //设置 actTab_Locate
的 enabled 属性
6. signals:
7. void celllndexChanged(int rowNo, int colNo) ;//当前单元格发生
变化
8.};
在主窗口上,“定位单元格”按钮的响应代码与前面有较大的差别。
两个槽函数是对话框操作主窗口时,主窗口作出的响应。信号是主窗口上
tableView 的当前单元格发生变化时发射的一个信号,以便对话框作出响应。
下面是两个槽函数的实现,以及 tableView 的 clicked() 信号的槽函数里发射自定义信号的代码,代码中都无须引用对话框对象:
1.void MainWindow::setACellText(int row, int column, QString text)
2.{//定位到单元格,并设置字符串
3. QModelIndex index=theModel->index(row,column);//获取模型索引
4. theSelection->clearSelection(); //清除现有选择
5. theSelection->setCurrentIndex(index,QItemSelectionModel::Select);
//定位到单元格
6. theModel->setData(index,text,Qt::DisplayRole);//设置单元格字符串
7.}
8.void MainWindow::setActLocateEnable(bool enable)
9.{
10. ui->actTab_Locate->setEnabled(enable);
11.}
12.void MainWindow::on_tableView_clicked(const QModelIndex &index)
13.{//单击单元格时发射信号,传递单元格的行号、列号
14. emit cellIndexChanged(index.row(),index.column());
15.}
在主窗口上,“定位单元格”按钮的响应代码与前面有较大的差别:
1.void MainWindow::on_actTab_Locate_triggered()
2.{//创建StayOnTop的对话框,对话框关闭时自动删除
3. QWDialogLocate *dlgLocate = new QWDialogLocate(this);
4. dlgLocate->setAttribute(Qt::WA_DeleteOnClose);
5. Qt::WindowFlags flags=dlgLocate->windowFlags();
6. dlgLocate->setWindowFlags(flags 丨 Qt::WindowStaysOnTopHint);
7. dlgLocate->setSpinRange(theModel->rcwCoimt(),theModel-
>columnCount());
8. QModelIndex curIndex=theSelection->currentIndex();
9.if (curIndex.isValid())
10. dlgLocate->setSpinValue(curIndex.row(),curIndex.column());
11. //对话框发射信号,设置单元格文字
12. connect(dlgLocate,SIGNAL(changeCellText(int, int, QString&)),
this,SLOT(setACellText(int,int,QString&)));
13. //对话框发射信号,设置actTab_Locate的属性
14. connect(dlgLocate,SIGNAL(changeActionEnable(bool)), this,
SLOT(setActLocateEnable(bool)));
15. //主窗口发射信号,修改对话框上的spinBox的值
16. connect(this,SIGNAL(celllndexChanged(int, int)),
17. dlgLocate,SLOT(setSpinValue(int, int)));
18. dlgLocate->show () ; //非模态显示对话框
19.}
在这里,对话框变量声明为了局部变量,不再需要在主窗口类里保存对话框的指针。这段代码的关键是设置了 3 对信号与槽的关联:
在 QWDialogLocate 类定义中,与信号和槽相关的定义如下:
1.class QWDialogLocate : public QDialog
2.{
3.private:
4. void closeEvent(QCloseEvent *event);
5. void showEvent(QShowEvent *event);
6.private slots:
7. void on_btnSetText_clicked();
8.public slots:
9. void setSpinValue(int rowNo, int colNo);
10.signals:
11. void changeCellText(int row, int column, QString &text);
12. void changeActionEnable(bool en);
13.};
QWDialogLocate 自定义了一个槽函数和两个信号,还增加了 showEvent() 事件的处理,用于对话框显不时发射信号使主窗口的 actTab_Locate 失效。
这些槽函数,以及发射信号的实现代码如下,代码中没有出现对主窗口的引用:
1.void QWDialogLocate::closeEvent(QCloseEvent *event)
2.{//窗口关闭事件,发射信号使actTab_Locate能用
3. emit changeActionEnable(true);
4.}
5.void QWDialogLocate::showEvent(QShowEvent *event)
6.{//窗口显示事件,发射信号使actTab_Locate不能用
7. emit changeActionEnable(false);
8.}
9.void QWDialogLocate::setSpinValue(int rowNo, int colNo)
10.{//响应主窗口信号,更新spinBox的值
11. ui->spinBoxRow->setValue(rowNo);
12. ui->spinBoxColumn->setValue(colNo);
13.}
14.void QWDialogLocate::on_btnSetText_clicked(〉
15.{//发射信号,定位到单元格并运置字符串
16. int row=ui->spinBoxRow->value () ; //行号
17. int col=ui->spinBoxColumn->value () ;//列号
18. QString text=ui->edtCaption->text () ;//文字
19. emit changeCellText (row, col, text) ; //发射信号
20. if (ui->chkBoxRow->isChecked () ) //行增
21. ui->spinBoxRow->setValue(1+ui->spinBoxRow->value());
22. if (ui->chkBoxColumn->isChecked () ) //列增
23. ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value());
24.}
经过这样修改后的程序,能实现与前面的实例完全相同的主窗口与对话框交互的功能,但是与前面互相引用的方式不同,这里使用Qt的信号与槽的机制,无须获取对方的指针,程序结构上更简单一些。
1.以下关于QT的描述正确的是: a.是一个不跨平台的C++图形用户界面 b.由挪威TrollTech公司出品 c.只支持Unix、Linux d.QT API和开发工具对所支持的平台是不一致的2.以下关于QT的描述不正确的是: a.QT支持2D图形渲染 b.QT支持3D图形渲染 c.QT支持OpenGL d.QT不支持XML 3.下关于不正确的是: a.是面向嵌入式系统的Qt版本 b.是Qt的嵌入式窗口 c.基于Windows平台的开发工具 d.是完整的自包含C++ GUI的开发工具 4.内部对字符集的处理采用以下哪个标准: a.UNICODE b.ASCII c.GB2312 d.ISO 8859-1 5.以下关于Qt描述不正确的是 a.是基于面向对象的C++语言 b.提供了signal和slot的对象通信机制 c.有可查询和可设计属性 d.没有字符国际化 6.以下描述正确的是: a.标准的C++对象模型可有效的支持运行时参数 b.标准的C++对象模型的静态特性十分灵活 c.图形用户界面编程无需运行得高效 d.图形用户界面编程无需运行得高灵活性 7.以下不是QT增加的特性: a.有效的对象通信signal和slot b.可查询和可设计的对象 c.事件及事件过滤器 d.不使用指针 8.以下描述正确的是: a.元对象系统可以对信号使用模板 b.元对象系统可以对槽使用模板 c.Qt可在多个平台的应用程序中完全应用模板 d.Qt不能在多个平台的应用程序中完全应用模板9.以下关于moc叙述正确的是:
a.moc即Mult Object Compiler b.可产生能被任何标准C++编译访问的附加C++代码 c.moc必须手动调用 d.类声明中有无Q_OBJECT无所谓 10.以下关于信号和槽的描述正确的是: a.用于SOCKET网络通信 b.用于UDP网络通信 c.用于对象间通信 d.用于串口通信 11.以下关于信号/槽的叙述不正确的是: a.信号与槽通过connected函数任意相连 b.信号/槽机制在QObject类中实现 c.从QWidget类继承的所有类可以包含信号和槽 d.当对象状态变化时信号被发送,对象不关心是否有其他对象接收到该信 号 12.以下类声明中有几处错误? class M : public Qobject { public : M ( ) ; int value ( ) const { return va ; } public slot : void setValue ( int ) ; signals : void valueChanged ( int ) ; private: int va ; }; a. 5 b. 4 c. 3 d. 2 13.设有如下声明 void M : : setValue ( int v ) { if ( v != va ) { va = v ; emit valueChanged ( v ) ; } }
QtE开发基础
?嵌入式GUI特点及种类 ?安装与建立QtE桌面运行环境?QtE Hello程序
?嵌入式GUI特点及种类 ?嵌入式系统对GUI的基本要求包括轻型、占用资源少、高性能、高可 靠性及可配置。 ?尽管实时嵌入式系统对GUI的需求越来越明显,但目前GUI的实现方法 各有不同,主要有以下几点: ?某些大型厂商有能力自己开发满足自身需要的GUI系统。 ?某些厂商没有将GUI作为一个软件层从应用程序中剥离,GUI的支 持逻辑由应用程序自己来负责。 ?采用某些比较成熟的GUI系统,比如MiniGUI,MicroWindows 或其他GUI系统。
?MiniGUI ?MiniGUI由原清华大学教师魏永明先生开发,是一种面向嵌入式系 统或实时系统的图形用户界面支持系统。它主要运行于Linux控制台,实际可以运行在任何一种具有POSIX线程支持的POSIX兼容系 统上。
?MicroWindows ?MicroWindows是一个著名的开放源码的嵌入式GUI软件。它提供了 现代图形窗口系统的一些特性。MicroWindows API接口支持类 Win32API,接口试图和Win32完全兼容,而且还实现了一些Win32用户模块功能。
?Qt/Embedded ?Qt/Embedded(简称QtE)是一个专门为嵌入式系统设计图形用户界 面的工具包。Qt是挪威Trolltech软件公司的产品,它为各种系统提供图形用户界面的工具包,QtE就是Qt的嵌入式版本。 ?使用QtE,开发者可以: ?用QtE开发的应用程序要移植到不同平台时,只需要重新编译代 码,而不需要对代码进行修改。 ?可以随意设置程序界面的外观。 ?可以方便地为程序连接数据库。 ?可以使程序本地化。 ?可以将程序与Java集成。
Qt复习提纲 Qt基础 1、以下关于QT的描述正确的是____B_____ A是一个不跨平台的C++图形用户界面 B由挪威TrollTech公司出品 C只支持Unix、Linux D QT API和开发工具对所支持的平台是不一致的 2、以下关于Qt描述不正确的是_____D__ A是基于面向对象的C++语言 B提供了signal和slot的对象通信机制 C有可查询和可设计属性 D没有字符国际化 3、以下不是QT增加的特性_____D___ A有效的对象通信signal和slot B可查询和可设计的对象 C事件及事件过滤器 D不使用指针 4、以下关于信号和槽的描述正确的是__C_____ A用于SOCKET网络通信 B用于UDP网络通信 C用于对象间通信 D用于串口通信 5、以下关于信号/槽的叙述不正确的是__B?______ A信号与槽通过connected函数任意相连 B信号/槽机制在QObject类中实现 C从QWidget类继承的所有类可以包含信号和槽 D当对象状态变化时信号被发送,对象不关心是否有其他对象接收到该信号 6、关于布局功能的叙述,以下正确的是____D____ A在布局空间中布置子窗口部件 B设置子窗口部件间的空隙 C管理在布局空间中布置子窗口部件 D以上都对 7、布局管理器包括____D____ A QHBox B QVBox C QGrid D 以上全有 8、以下叙述正确的是__D_______ A QHBox允许子窗口部件按水平、垂直和网格排列 B QVBox允许子窗口部件按水平、垂直和网格排列 C QGrid允许子窗口部件按水平、垂直和网格排列 D 以上全不对 9、创建一个窗体对象后,要想显示该窗体,需要调用对象的___show_______方法,要想隐藏该窗体需要调用对象的____hide______方法。
Qt-4.6新增了Animation Framework(动画框架),让我们能够方便的写一些生动的程序。不必像以前的版本一样,所有的控件都枯燥的呆在伟大光荣的QLayout里,也许它们可以唱个歌,跳个舞。 前面写过一篇文章Qt动画效果的幕后英雄:QTimeLine,介绍了怎么利用QTimeLine写一动画程序。今天又再重申前文里的一句话,所谓动画就是在一个时间段内的不同时间点有不同的状态,只要定义好这样状态,实现动画就是水到渠成的事情。当然做这件事情,最好用的就是状态机,没错Qt-4.6.0提供了QStateMachine类,不过今天我要讲的三字决要简单一些。 第一决:QPropertyAnimation QPropertyAnimation用于和QObject中的属性properties进行通信,比如QWidget的大小,坐标等。来看代码 QPropertyAnimation *animation = new QPropertyAnimation(myWidget, "geometry"); animation->setDuration(10000); animation->setStartValue(QRect(0, 0, 100, 30)); animation->setEndValue(QRect(250, 250, 100, 30)); animation->start(); 第一行创建的QPropertyAnimation对象关联了myWidget这个窗体的几何属性。后面的几句分别设置了这个动画的时长,起始坐标和结束坐标。剩下的事情就交改QProperAnimation 去做就行了。然后调用start()启动它。没错,五行代码就完成了一个完成了一个自动从一个坐标点移动到另一个坐标点的窗体。下面我给出一个可以运行的代码,是一只小鸟从下角移到中间的一个小动画,当然你得自己准备这个同名的图片:) #include
《Qt Creator快速入门》第2版 实验讲义 2014年6月
目录 实验1 Qt开发环境的搭建......................................................- 2 - 目的与要求..................................................................................................................- 2 - 实验准备......................................................................................................................- 2 - 实验内容......................................................................................................................- 2 - 实验2 编译和发布Qt程序...................................................- 16 - 目的与要求................................................................................................................- 16 - 实验准备....................................................................................................................- 16 - 实验内容....................................................................................................................- 16 - 实验3 使用Qt资源文件.......................................................- 25 - 目的与要求................................................................................................................- 25 - 实验准备....................................................................................................................- 25 - 实验内容....................................................................................................................- 25 - 实验4 创建登陆对话框..........................................................- 30 - 目的与要求................................................................................................................- 30 - 实验准备....................................................................................................................- 30 - 实验内容....................................................................................................................- 30 - 实验5 定时器和随机数..........................................................- 35 - 目的与要求................................................................................................................- 35 - 实验准备....................................................................................................................- 35 - 实验内容....................................................................................................................- 35 - 实验6 编译MySQL数据库驱动............................................- 38 - 目的与要求................................................................................................................- 38 - 实验准备....................................................................................................................- 38 - 实验内容....................................................................................................................- 38 - 实验7 数据库基本操作............................................................- 49 - 目的与要求................................................................................................................- 49 - 实验准备....................................................................................................................- 49 - 实验内容....................................................................................................................- 49 - 实验8 Qt数据库应用编程(综合设计)................................- 55 - 目的与要求................................................................................................................- 55 - 实验准备....................................................................................................................- 55 - 实验内容....................................................................................................................- 55 -
第01章Qt Creator的安装和hello world程序 第1章主要讲述windows下的Qt Creator下载、安装和最简单程序的编写,然后在附录里又讲解了两种其他的编写程序的方法。在linux下Qt Creator下载、安装及程序的编写基本与此相同。 1.1 Qt 简介 Qt 是一个跨平台的C++ 图形用户界面库,由挪威TrollTech 公司出品,目前包括Qt,基于Framebuffer 的Qt Embedded,快速开发工具Qt Designer,国际化工具Qt Linguist 等部分Qt 支持所有Unix 系统,当然也包括Linux,还支持WinNT/Win2k,Win95/98 平台。 Qt 具有下列优点: 1.优良的跨平台特性: Qt支持下列操作系统: Microsoft Windows 95/98, Microsoft Windows NT, Linux,Solaris, SunOS, HP-UX, Digital UNIX (OSF/1, Tru64), Irix, FreeBSD,BSD/OS, SCO, AIX, OS390,QNX 等等。 2.面向对象 Qt 的良好封装机制使得 Qt 的模块化程度非常高,可重用性较好,对于用户开发来说是非常方便的。 Qt 提供了一种称为 signals/slots 的安全类型来替代 callback,这使得各个元件之间的协同工作变得十分简单。 3.丰富的 API Qt 包括多达 250 个以上的 C++ 类,还替供基于模板的 collections, serialization, file, I/O device, directory management, date/time 类。 甚至还包括正则表达式的处理功能。 4.支持 2D/3D 图形渲染,支持 OpenGL 5.大量的开发文档 6.XML 支持 1.2 Qt Creator的下载和安装 1. 下载 首先到Qt的官方网站上下载Qt Creator,这里我们下载windows版的。 Qt SDK: 完整的开发环境 Qt SDK 在一个单独的安装程序内包括了使用 Qt 构建跨平 台应用程序所需的工具。 ?Qt 库 4.7.0
一、选择题(每题2分,共15题,30分) 1.以下关于QT的描述正确的是:B a.是一个不跨平台的C++图形用户界面 b.由挪威TrollTech公司出品 c.只支持Unix、Linux d.QT API和开发工具对所支持的平台是不一致的 1.内部对字符集的处理采用以下哪个标准:A a.UNICODE b.ASCII c.GB2312 d.ISO 8859-1 2.以下描述正确的是:A a.标准的C++对象模型可有效的支持运行时参数 b.标准的C++对象模型的静态特性十分灵活 c.图形用户界面编程无需运行得高效 d.图形用户界面编程无需运行得高灵活性 3.以下不是QT增加的特性:D a.有效的对象通信signal和slot b.可查询和可设计的对象 c.事件及事件过滤器 d.不使用指针 4.以下描述正确的是:C a.元对象系统可以对信号使用模板 b.元对象系统可以对槽使用模板 c.Qt可在多个平台的应用程序中完全应用模板 d.Qt不能在多个平台的应用程序中完全应用模板 5.以下关于moc叙述正确的是:B a.moc即Mult Object Compiler b.可产生能被任何标准C++编译访问的附加C++代码 c.moc必须手动调用 d.类声明中有无Q_OBJECT无所谓 6.以下关于信号/槽的叙述不正确的是:D a.信号与槽通过connected函数任意相连 b.信号/槽机制在QObject类中实现 c.从QWidget类继承的所有类可以包含信号和槽 d.当对象状态变化时信号被发送,对象不关心是否有其他对象接收到该信 号 7.设有如下声明B void M : : setValue ( int v ) { if ( v != va ) { va = v ;
几行代码轻松做上位机界面Qt Designer快速入门小教程 By Exilefox 2012年3月28日 做嵌入式的各位想必或多或少都听说过Qt,各种优点不细数了,简单的说这就是个做界面的IDE。 我发现很多Qt的教程都是用代码来编写界面程序,有没有图形化的方法呢!答案就是Qt Designer 打个比方,用代码写界面就像是你用记事本一行行的敲HTML代码,用Qt Designer 写界面就很类似用FrontPage或者DreamWeaver,拖些控件,调整一下位置、属性,补些css 效果,一个轻松的页面就出来了 此文意在引导初学者使用Qt Designer快速的入门编写界面,不关心底层的c++实现,总共只用敲几行代码 新建工程开始,如图选择,然后一路next。我就不多说了
工程建立好后来看看工程的结构 点击ui文件就可以切换到设计窗口,我们的ui设计主要就是在这里完成的,让我们看看结构 在左边的是控件栏,里面的控件(如我们将用到的按钮、框架等)可以直接拖拽到中间的窗口编辑区。各位有兴趣可以自己把他们一一拖出来,然后按shift+alt+R预览,看看是做什么功能的,我就不一一详述了(其实有些我也没用过,呵呵)。因为我们再之前建立工程时候默认的是Mainwindow类型,所以这个窗口一开始就自带了顶部菜单,顶部图标栏,底部状态栏等,各位想要干净点的可以在创建时试试其他类型。右上的显示的是从属结构,右下显示的是某个部件的属性。底部的是信号与槽编辑窗口,信号与槽的编辑方式有4种:拖拽、在编辑窗口添加,右键“转到槽”,在C++代码中用connect函数,在此只演示右键“转到槽”