none
怎样使另一个窗体显示时进度条开始工作,我的编码看不到进度的过程,怎么办? RRS feed

  • 问题

  • 在一个窗体中点击按钮显示另一个窗体后,使进度条立即自动开始工作,
    我尝试用构造函数sub new()
    但运行后,窗体进度条直接显示100%,没有看到进度的过程,该如何处理?

    2009年6月8日 3:20

答案

  • 你好 你可以设置ProgressBar的Maximum和Minimum属性来设置进度条的范围
    然后通过Increment 方法 或者Step和PerformStep来增加进度

    而这些增长一般是放在其他对象的异步事件响应的方法中的
    比如我用WebClient异步下载文件 有个事件
    public event DownloadProgressChangedEventHandler DownloadProgressChanged
    它的事件处理方法的一个参数e的类型为 DownloadProgressChangedEventArgs
    它的一个属性ProgressPercentage   就是下载了百分之多少 这样我可以把我的ProgressBar的Maximum设置为100,然后在这个事件的处理方法中设置进度条的值 根据面那个 ProgressPercentage 
    努力着就不会放弃!.net技术交流群 33083877http://hi.baidu.com/1987raymond
    • 已标记为答案 Kira Qian 2009年6月14日 11:40
    2009年6月8日 3:37
    版主
  • 我先设置了窗体form2,在其中添加了一个menustrip控件命名为“计算”,我想点击“计算”按钮,弹出窗体form3,里面有一个进度条,要求进度条在form3弹出后自动开始。我在窗体form2代码编辑器编码如下
    Public Class Form3
        Public Sub New()
            InitializeComponent()
            Dim looptimes As Integer = 6000000
            '设置进度条的最大值属性
            ProgressBar1.Maximum = looptimes
            For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值
                If i Mod 100 = 0 Then
                    ProgressBar1.Value = i
                End If
            Next
        End Sub
    End Class
    运行后,点击form2的按钮,弹出form3窗体,进度条直接显示为100%,没有过程,怎么办?
    窗体form2的代码为
    Public Class Form2

        Private Sub 计算ToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 计算ToolStripMenuItem.Click
            Dim form3 As New Form3()
            form3.ShowDialog()
        End Sub

    End Class


     For i As Integer = 1 To looptimes不需要执行完才会执行后面的程序

    改成放到timer
    http://feiyun0112.cnblogs.com/
    • 已标记为答案 Kira Qian 2009年6月14日 11:40
    2009年6月8日 5:59
    版主
  • Hi huangyingkuai ,

    在你的代码中,将循环放入了构造函数中,这样在窗口显示之前已经做完了所有循环,所以显示出来的窗体进度条直接满了。对于这个问题你需要用到多线程,先要让窗体显示出来,然后另一个线程做循环,并用委托来设置UI线程中的ProgressBar控件的值。以下是我修改后的代码
    Imports System.Threading

    Public Class Form2
        Private looptimes As Integer = 6000000
        Private thread As Thread
        Public Delegate Sub SetProgressDelg(ByVal value As Integer)

        Public Sub New()
            InitializeComponent()

            '设置进度条的最大值属性
            ProgressBar1.Maximum = looptimes

            '开另一个进程做循环并设置ProgressBar的值
            thread = New Thread(AddressOf Perform)
            thread.Start()
        End Sub

        Public Sub Perform()
            For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值
                If i Mod 100 = 0 Then
                    '必须用Invoke来做跨线程操作
                    Me.Invoke(New SetProgressDelg(AddressOf SetProgressBarValue), i)
                End If
            Next
        End Sub

        Public Sub SetProgressBarValue(ByVal value As Integer)
            ProgressBar1.Value = value
        End Sub
    End Class

    在这段代码中,窗体会先显示出来,然后thread执行循环,通过委托调用SetProgressBarValue函数来改变ProgressBar的值。我已经测试过了,应该能完全符合你的要求。

    Sincerely,
    Kira Qian


    Please mark the replies as answers if they help and unmark if they don't.
    • 已建议为答案 Kira Qian 2009年6月9日 7:45
    • 已标记为答案 Kira Qian 2009年6月14日 11:41
    2009年6月9日 7:42

全部回复

  • 你好 你可以设置ProgressBar的Maximum和Minimum属性来设置进度条的范围
    然后通过Increment 方法 或者Step和PerformStep来增加进度

    而这些增长一般是放在其他对象的异步事件响应的方法中的
    比如我用WebClient异步下载文件 有个事件
    public event DownloadProgressChangedEventHandler DownloadProgressChanged
    它的事件处理方法的一个参数e的类型为 DownloadProgressChangedEventArgs
    它的一个属性ProgressPercentage   就是下载了百分之多少 这样我可以把我的ProgressBar的Maximum设置为100,然后在这个事件的处理方法中设置进度条的值 根据面那个 ProgressPercentage 
    努力着就不会放弃!.net技术交流群 33083877http://hi.baidu.com/1987raymond
    • 已标记为答案 Kira Qian 2009年6月14日 11:40
    2009年6月8日 3:37
    版主
  • 放到timer去改变进度,或者用自定义事件


    http://feiyun0112.cnblogs.com/
    2009年6月8日 4:06
    版主
  • 你好!
         请问你现在是怎样做的呢?进度条在哪个窗体中,进度如何计算的呢?最好提供相关的源代码!
    周雪峰
    2009年6月8日 4:13
    版主
  • 我先设置了窗体form2,在其中添加了一个menustrip控件命名为“计算”,我想点击“计算”按钮,弹出窗体form3,里面有一个进度条,要求进度条在form3弹出后自动开始。我在窗体form2代码编辑器编码如下
    Public Class Form3
        Public Sub New()
            InitializeComponent()
            Dim looptimes As Integer = 6000000
            '设置进度条的最大值属性
            ProgressBar1.Maximum = looptimes
            For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值
                If i Mod 100 = 0 Then
                    ProgressBar1.Value = i
                End If
            Next
        End Sub
    End Class
    运行后,点击form2的按钮,弹出form3窗体,进度条直接显示为100%,没有过程,怎么办?
    窗体form2的代码为
    Public Class Form2

        Private Sub 计算ToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 计算ToolStripMenuItem.Click
            Dim form3 As New Form3()
            form3.ShowDialog()
        End Sub

    End Class

    2009年6月8日 5:55
  • 我先设置了窗体form2,在其中添加了一个menustrip控件命名为“计算”,我想点击“计算”按钮,弹出窗体form3,里面有一个进度条,要求进度条在form3弹出后自动开始。我在窗体form2代码编辑器编码如下
    Public Class Form3
        Public Sub New()
            InitializeComponent()
            Dim looptimes As Integer = 6000000
            '设置进度条的最大值属性
            ProgressBar1.Maximum = looptimes
            For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值
                If i Mod 100 = 0 Then
                    ProgressBar1.Value = i
                End If
            Next
        End Sub
    End Class
    运行后,点击form2的按钮,弹出form3窗体,进度条直接显示为100%,没有过程,怎么办?
    窗体form2的代码为
    Public Class Form2

        Private Sub 计算ToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 计算ToolStripMenuItem.Click
            Dim form3 As New Form3()
            form3.ShowDialog()
        End Sub

    End Class


     For i As Integer = 1 To looptimes不需要执行完才会执行后面的程序

    改成放到timer
    http://feiyun0112.cnblogs.com/
    • 已标记为答案 Kira Qian 2009年6月14日 11:40
    2009年6月8日 5:59
    版主
  • 你好!
         因为你把设置进度条的循环代码放到窗体的构造函数中了,在窗体显示前,构造函数已经执行完毕了,循环也执行完毕了,所以进度是100%
         你把那个循环写在Form3的Shown事件处理程序中试试!
    周雪峰
    2009年6月8日 8:17
    版主
  • 我尝试用shown事件,编写了如下代码:
    Public Class Form3
        Sub EventHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
            Dim form3 As New Form3()
            AddHandler form3.Shown, AddressOf EventHandler
            Dim looptimes As Integer = 1000000
            '设置进度条的最大值属性
            ProgressBar1.Maximum = looptimes
            For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值
                If i Mod 100 = 0 Then
                    ProgressBar1.Value = i
                End If
            Next
        End Sub
    End Class
    但是form3窗体弹出后进度条不运行,什么原因呢,事件引用不正确吗?

    2009年6月8日 15:28
  • 你好!
         代码写的有点问题,你这样尝试一下:
         1,这两行有些问题,不要重新实例化另外的Form3实例,直接订阅Me的Shown事件
            Dim form3 As New Form3()
            AddHandler form3.Shown, AddressOf EventHandler
         2,你在Form2中不是需要实例化Form3,然后再显示出来form3吗?在调用了form3.Show()方法后,调用form3.Refresh()刷新一下窗体!这样进度条就可以显示了!
    周雪峰
    2009年6月9日 0:58
    版主
  • 我试了没问题,是不是显示得太快了

    For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值

                ProgressBar1.Value = i

            Next


    http://feiyun0112.cnblogs.com/
    2009年6月9日 2:26
    版主
  • Hi huangyingkuai ,

    在你的代码中,将循环放入了构造函数中,这样在窗口显示之前已经做完了所有循环,所以显示出来的窗体进度条直接满了。对于这个问题你需要用到多线程,先要让窗体显示出来,然后另一个线程做循环,并用委托来设置UI线程中的ProgressBar控件的值。以下是我修改后的代码
    Imports System.Threading

    Public Class Form2
        Private looptimes As Integer = 6000000
        Private thread As Thread
        Public Delegate Sub SetProgressDelg(ByVal value As Integer)

        Public Sub New()
            InitializeComponent()

            '设置进度条的最大值属性
            ProgressBar1.Maximum = looptimes

            '开另一个进程做循环并设置ProgressBar的值
            thread = New Thread(AddressOf Perform)
            thread.Start()
        End Sub

        Public Sub Perform()
            For i As Integer = 1 To looptimes
                '开始计算
                '设置进度条的值
                If i Mod 100 = 0 Then
                    '必须用Invoke来做跨线程操作
                    Me.Invoke(New SetProgressDelg(AddressOf SetProgressBarValue), i)
                End If
            Next
        End Sub

        Public Sub SetProgressBarValue(ByVal value As Integer)
            ProgressBar1.Value = value
        End Sub
    End Class

    在这段代码中,窗体会先显示出来,然后thread执行循环,通过委托调用SetProgressBarValue函数来改变ProgressBar的值。我已经测试过了,应该能完全符合你的要求。

    Sincerely,
    Kira Qian


    Please mark the replies as answers if they help and unmark if they don't.
    • 已建议为答案 Kira Qian 2009年6月9日 7:45
    • 已标记为答案 Kira Qian 2009年6月14日 11:41
    2009年6月9日 7:42
  • 我把代码添加进了Form3的窗体代码编辑器中,运行后
    在代码行Me.Invoke(New SetProgressDelg(AddressOf SetProgressBarValue), i)
    弹出InvalidOperationException窗口,显示
    在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
    这个怎么办呢?
    2009年6月9日 15:56
  • Hi huangyingkuai,

    你是完全复制我的代码去运行的吗?Me.Invoke不能在构造函数里调,但我用的是多线程的,在窗体显示之后才进入循环的,这就是以下这两句起的作用。
    thread = New Thread(AddressOf Perform)
    thread.Start()
    你当然先要把窗体显示出来,这样窗体的句柄就创建好了,可以调了。就是在另一个窗体中要show出Form2。
    Dim frm As Form2 = New Form2()
    frm.Show()

    还有什么问题请回我。

    Sincerely,
    Kira Qian


    Please mark the replies as answers if they help and unmark if they don't.
    2009年6月10日 1:52
  • 我对多线程处理不是太熟悉,谢谢你能告诉我这样做。
    之前我的要求我可能没有说太清楚,是这样:我在Form2窗体中创建一个MenuStrips控件,text属性为“计算”,当我点击它时要求把Form3窗体能弹出,同时Form3中的ProgressBar能开始运行至100%。
    我完全复制了你的代码添加到Form3代码编辑器中,结果就出现了
    在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke 的提示。
    在Form2代码编辑器中我编码如下:
    Public Class Form2
        Private Sub 计算ToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 计算ToolStripMenuItem.Click
            Dim form3 As New Form3()
            Me.ShowDialog()
        End Sub
    End Class
    这样似乎已经让Form3显示出来,但运行时弹出了提示,怎么办呢?
    2009年6月10日 6:05
  • 你这里写错了,应该是
    Dim form3 As New Form3()
    form3.ShowDialog()
    不是Me.ShowDialog()
    Please mark the replies as answers if they help and unmark if they don't.
    2009年6月10日 6:18
  • Hello,我将程序代码改过来了,ProgressBar可以运行了,但在调试时Form3中的几个Label控件的text属性不能显示,相应位置为空白,当进度条到达100%时,才显示出来,这是什么原因呢?

    2009年6月10日 15:44
  • Hi,

    在你第一个帖子中并没有提到label啊,你那个label是显示什么用的?你可以用label.Refresh()方法来刷新一下label的显示,应该可以解决问题。

    Sincerely,
    Kira Qian
    Please mark the replies as answers if they help and unmark if they don't.
    2009年6月11日 1:46