加快用户界面响应(wonder).doc_第1页
加快用户界面响应(wonder).doc_第2页
加快用户界面响应(wonder).doc_第3页
加快用户界面响应(wonder).doc_第4页
加快用户界面响应(wonder).doc_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

加快用户界面响应在所有的QT例子在main()最后都调用了QApplication:exec()函数,它启动了Qt的事件循环。开始时Qt会发出一些事件来显示和绘制窗口部件。在这之后,事件循环就开始运行,不断地检查是否有事件发生并把这些事件交给QObject目标对象或其子对象处理。当一个事件被处理时,其他的事件也可能产生并追加到Qt的事件队列中。如果在一个特定事件的处理上消耗过多时间,用户界面就有可能冻结而无法响应。例如,当程序存在大量长时间I/O操作时,窗口系统产生的一些事件将无法得到处理直到I/O操作完成,从而导致这段时间内用户界面冻结。在Qt中解决上述问题有三种方法:第一种方法是使用线程,一个线程处理应用程序用户响应,另一个处理特定事件上的耗时操作。我们在第11章已做介绍。第二种方法是在处理耗时事件时频繁调用QApplication:processEvents()。第三种方法是推迟耗时事件处理,直到应用程序空闲下来。(一) 使用processEvents()函数QApplication:processEvents()函数告知Qt处理任何没有被处理的事件,并且将控制权返回给调用者。实际上QApplication:exec()就是一个不停调用processEvents()函数的小while循环。下面我们编写了一个复制文本文件的示例,如下图所示。当复制的文件很大时,I/O操作将持续较长时间,在此期间,程序的其他事件处理将被影响,如产生界面冻结。为了解决这个问题,在复制函数doCopy()中调用了processEvents()来保持用户界面响应,代码如下:void Dialog:doCopy()while(bytesToWrite 0)if(isStop)rFile-close();wFile-close();wFile-remove(currentFile);progressBar-setMaximum(totalBytes);progressBar-setValue(0);statusLabel-setText(tr(终止);saveButton-setEnabled(false);stopButton-setEnabled(false);qApp-processEvents();return;elsetempBuf = rFile-read(qMin(bytesToWrite, loadSize);wFile-write(tempBuf);bytesWritten += qMin(bytesToWrite, loadSize);bytesToWrite -= qMin(bytesToWrite, loadSize);progressBar-setMaximum(totalBytes);progressBar-setValue(bytesWritten);statusLabel-setText(tr(已拷贝 %1MB).arg(bytesWritten / (1024 * 1024);tempBuf.resize(0);qApp-processEvents();rFile-close();wFile-close();当还有要复制的数据(bytesToWrite变量值大于0)且用户没有单击“中断”按钮(isStop变量为false)时,在本次循环中从源文件读取4K字节内容并将它写入目标文件,然后更新进度条和状态显示,最后强制调用processEvents()函数增加一次出来其他类型事件的机会。如果用户中途中断了本次复制操作,将清理尚未复制完成的文件,更新程序显示状态。这里没有人为的对QProgressDialog调用show()函数,因为进度条对话框会自动调用,如果因为某些原因,如文件太小伙机器处理速度太快,使得操作很快就完成了,QProgressDialog会检测到这个情况并不再显示。但是上述方式存在一个潜在的威胁,那就是如果用户在文件复制过程中关闭了窗口,或者又一次选择了保存按钮,程序的执行结果将是不确定的。对于这个问题,最简单的解决方式是把:qApp-processEvents();函数调用替换为:qApp-eventLoop()-processEvents(QEventLoop:ExcludeUserInput);函数调用,它告诉Qt忽略鼠标和键盘事件。(二) 使用定时器对于处理长时间操作还有另一种完全不同的方式。这里不是在用户请求中执行处理,而是推迟处理,直到应用程序空闲下来。如果处理可以安全地打断并且随后可以继续执行,这种方法就能生效,因为无法预先直到多长时间后程序会空闲下来。在Qt中,这种方式可以通过一个特定的“0毫秒定时器”来实现。只要没有未被处理的事件,这个定时器会被触发。以下是上述文件复制示例在使用定时器方式下的实现。void Dialog:saveFile() rFile = new QFile(fileName); if (!rFile-open(QFile:ReadOnly ) QMessageBox:warning(this, tr(程序), tr(无法读取文件 %1:n%2.) .arg(fileName) .arg(rFile-errorString(); return; currentFile = fileName.right(fileName.size() - fileName.lastIndexOf(/)-1);wFile = new QFile(currentFile);if (!wFile-open(QFile:WriteOnly ) QMessageBox:warning(this, tr(程序), tr(无法写文件 %1:n%2.) .arg(currentFile) .arg(wFile-errorString(); return; totalBytes = rFile-size();bytesToWrite = totalBytes; statusLabel-setText(tr(就绪);#ifdef USET_TIME_EVENTtimeId = startTimer(0);#elsedoCopy();#endif当用户单击“保存”按钮后,saveFile()槽函数开始执行。它首先打开源文件rFile,然后以同样的文件名在当前目录下建立一个文件wFile(),以源文件大小初始化总共需复制的字节数变量totalBytes和尚未复制的字节数变量tytesToWrite,并设置当前状态为“就绪”。最后是启动一个“0毫秒的定时器”,这里使用了条件编译方法,如果定义了宏USET_TIME_EVENT则开启定时器,否则使用doCopy()函数。使用条件编译可以让用户在同一个示例程序中选择使用两种加快界面响应的处理方式,这里开启了USET_TIME_EVENT宏。void Dialog:timerEvent(QTimerEvent* event)if(event-timerId() = timeId)while(bytesToWrite 0) & (!qApp-hasPendingEvents()if(isStop)rFile-close();wFile-close();wFile-remove(currentFile);progressBar-setMaximum(totalBytes);progressBar-setValue(0);statusLabel-setText(tr(终止);saveButton-setEnabled(false);stopButton-setEnabled(false);return;elsetempBuf = rFile-read(qMin(bytesToWrite, loadSize);wFile-write(tempBuf);bytesWritten += qMin(bytesToWrite, loadSize);bytesToWrite -= qMin(bytesToWrite, loadSize);progressBar-setMaximum(totalBytes);progressBar-setValue(bytesWritten);statusLabel-setText(tr(已拷贝 %1MB).arg(bytesWritten / (1024 * 1024);tempBuf.resize(0);event-accept();elseDialog:timerEvent(event);函数timeEvent()用于处理定时器事件,如果hasPendingEvents()返回“true”,就停止处理并且把处理权交给Qt。当Qt处理完了它所有事件,定时器事件的处理将会继续进行。这个函数的其他操作与doCopy()函数几乎一模一样,所不同的仅是其中没有调用processEvent()函数。由于是在空闲的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论