热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#Winform进度条的使用

一个好的进度条能有效的改善用户体验。当然,前提是进度条做得好才行,做得差作用就正好相反了,可能造成程序假死、无法关闭等。下面是一个真实例子

一个好的进度条能有效的改善用户体验。当然,前提是进度条做得好才行,做得差作用就正好相反了,可能造成程序假死、无法关闭等。

下面是一个真实例子,我自己写代码的经验(由于我使用进度条都是自己琢磨,所以和网上的例子不太一样)。

以下是我一年前写的进度条,当时刚学C#,所以写出的进度条窗体效果非常差,正好做一个反例。

        public int current &#61; 0;//当前值public int max &#61; 100;//最大值public ProgressForm(){InitializeComponent();}//循环跑进度条public void pand(){int i, old &#61; 0;do{if (current !&#61; old){for (i &#61; 0; i < 10; i&#43;&#43;){this.progressBar1.Value &#43;&#61; 1;this.progressBar1.Update();Application.DoEvents();}old &#61; current;}this.progressBar1.Update();Application.DoEvents();if (current &#61;&#61; 0){this.label1.Text &#61; "正在写入论文信息&#xff0c;请稍等...";}else{this.label1.Text &#61; "正在写入论文正文&#xff0c;请稍等...";}}while (current !&#61; max);while (this.progressBar1.Value !&#61; this.progressBar1.Maximum){this.progressBar1.Value &#43;&#61; 1;this.progressBar1.Update();Application.DoEvents();}}//窗体显示时的事件private void ProgressForm_Shown(object sender, EventArgs e){this.progressBar1.Maximum &#61; max * 10;this.progressBar1.Value &#61; 0;pand();this.Close();}

好吧&#xff0c;代码非常繁琐&#xff0c;我稍微解释一下这段代码以及当时我的想法&#xff1a;

我定义了两个公共变量&#xff1a;max存后台需要完成任务任务数&#xff0c;current存当前完成了第几项任务。然后pand()方法负责循环检测current的值&#xff0c;然后给进度条增加值&#xff0c;当current等于max时停止循环关闭进度条窗体&#xff0c;代表任务完成。

                        while (this.progressBar1.Value !&#61; this.progressBar1.Maximum){this.progressBar1.Value &#43;&#61; 1;this.progressBar1.Update();Application.DoEvents();}

这段代码的作用是让进度条跑的时候不跳格&#xff0c;类似this.progressBar1.PerformStep();方法&#xff08;当时我并不知道进度条有这个方法&#xff09;。下面说一下这段代码存在的问题&#xff0c;首先使用无限循环会造成程序假死现象&#xff08;就是跑进度的时候无法关闭进度条窗体&#xff09;&#xff0c;这非常影响用户体验&#xff0c;其次是代码繁琐&#xff0c;明明是非常简单的事&#xff0c;写得那么繁琐&#xff0c;既影响阅读又影响性能&#xff0c;最后是进度条的画面和Value不同步&#xff08;即每次进度条的Value已经加完了&#xff0c;进度条还没跑完&#xff09;&#xff0c;导致用户看到的效果是进度还没跑完&#xff0c;进度条就关了。

下面看一下我修改后的进度条窗体代码&#xff1a;

        private int _current &#61; 0;/// 

/// 当前值/// public int Current{get { return _current; }set{_current &#61; value;AddValue();}}private int _max &#61; 100;/// /// 最大值/// public int Max{get { return _max; }set { _max &#61; value;this.progressBar1.Maximum &#61; (_max - 1) * 10;this.progressBar1.Value &#61; 0;}}MainForm father;public ProgressForm(MainForm main){father &#61; main;InitializeComponent();this.label1.Text &#61; "正在写入论文信息&#xff0c;请稍等...";}/// /// 给进度条加值的方法/// private void AddValue(){if (_current > 0){this.label1.Text &#61; "正在写入论文正文&#xff0c;请稍等...";}this.progressBar1.PerformStep();if (this._current * 10 > this.progressBar1.Maximum){this.DialogResult &#61; System.Windows.Forms.DialogResult.OK;this.Close();}}/// /// 取消按钮的方法/// private void Cancel(){father.CreateThesisIsRuning &#61; false;progressBar1.Style &#61; ProgressBarStyle.Marquee;label1.Text &#61; "取消中&#xff0c;请稍等...";while (true){if (!father.CreateThesisTh.IsAlive)break;Application.DoEvents();}}/// /// 取消按钮事件/// /// /// private void buttonX1_Click(object sender, EventArgs e){Cancel();}

同样是需要当前值和最大值变量&#xff0c;不同的是我把这两个字段封装起来了&#xff0c;AddValue()方法负责给进度条增加值&#xff0c;Cancel()方法负责执行用户点击取消按钮的操作。

在设置Current值时执行AddValue()方法&#xff0c;AddValue()方法中使用了this.progressBar1.PerformStep()&#xff0c;这个方法的作用是按照设置好的this.progressBar1.Step值给进度条增加值&#xff0c;比如Step&#61;10&#xff0c;调用这个方法就相当于给进度条添加10次值&#xff0c;每次增加1&#xff0c;就不会造成进度条跳跃格数过大&#xff0c;提升用户体验。

用户在点击取消按钮时&#xff0c;就设置后台进程CreateThesisIsRuning&#61;false&#xff0c;使进程停止&#xff0c;由于进程正常可能停止需要一定的时间&#xff0c;所以用一个循环去检测CreateThesisTh.IsAlive的值判断进程是否结束&#xff0c;此时还要修改进度条类型为ProgressBarStyle.Marquee&#xff0c;Application.DoEvents()可以避免循环卡死。

然后针对进度不同步&#xff0c;在设置Max值得时候&#xff0c;this.progressBar1.Maximum &#61; (_max - 1) * 10&#xff0c;将进度条的最大值设置成max最大值-10&#xff0c;然后最后判断进度条是否结束时使用this._current * 10 > this.progressBar1.Maximum去判断&#xff0c;这样就可以使进度条画面&#xff0c;原理是进度条画面更新比较慢&#xff0c;所以减小进度条的最大值&#xff0c;让进度条先跑完再执行完任务&#xff0c;造成进度条在等任务&#xff0c;虽然还是不同步&#xff0c;但是在用户体验上效果好多了。

下面看一下效果&#xff1a;

跑条中.png

图1 任务进行中

取消中.png

图2 任务取消中

以上是我自己想的一个进度条方案&#xff0c;如有雷同&#xff0c;纯属巧合&#xff0c;欢迎大家指正。


推荐阅读
  • WinMain 函数详解及示例
    本文详细介绍了 WinMain 函数的参数及其用途,并提供了一个具体的示例代码来解析 WinMain 函数的实现。 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 在Delphi7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本。定义如下:1234 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 使用多项式拟合分析淘宝双11销售趋势
    根据天猫官方数据,2019年双11成交额达到2684亿元,再次刷新历史记录。本文通过多项式拟合方法,分析并预测未来几年的销售趋势。 ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • 本文对比了杜甫《喜晴》的两种英文翻译版本:a. Pleased with Sunny Weather 和 b. Rejoicing in Clearing Weather。a 版由 alexcwlin 翻译并经 Adam Lam 编辑,b 版则由哈佛大学的宇文所安教授 (Prof. Stephen Owen) 翻译。 ... [详细]
  • PTArchiver工作原理详解与应用分析
    PTArchiver工作原理及其应用分析本文详细解析了PTArchiver的工作机制,探讨了其在数据归档和管理中的应用。PTArchiver通过高效的压缩算法和灵活的存储策略,实现了对大规模数据的高效管理和长期保存。文章还介绍了其在企业级数据备份、历史数据迁移等场景中的实际应用案例,为用户提供了实用的操作建议和技术支持。 ... [详细]
  • Python 序列图分割与可视化编程入门教程
    本文介绍了如何使用 Python 进行序列图的快速分割与可视化。通过一个实际案例,详细展示了从需求分析到代码实现的全过程。具体包括如何读取序列图数据、应用分割算法以及利用可视化库生成直观的图表,帮助非编程背景的用户也能轻松上手。 ... [详细]
  • 本文详细介绍了批处理技术的基本概念及其在实际应用中的重要性。首先,对简单的批处理内部命令进行了概述,重点讲解了Echo命令的功能,包括如何打开或关闭回显功能以及显示消息。如果没有指定任何参数,Echo命令会显示当前的回显设置。此外,文章还探讨了批处理技术在自动化任务执行、系统管理等领域的广泛应用,为读者提供了丰富的实践案例和技术指导。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有