如何通过鼠标按住和释放来检查 TrackBar 滑动

发布于 2024-11-02 10:20:34 字数 365 浏览 8 评论 0原文

我的 WinForms 程序中有一个轨迹栏,通过移动它,将刷新一个巨大且耗时的方法。看一下这段代码:

trackBar_ValueChanged(object sender, EventArgs e)
{
     this.RefreshData();
}

这个轨迹栏有 20 个步骤。在我的情况下,如果用户抓住轨迹栏的滑块并将其从 20 拉到 0,则“RefreshData”将执行 20 次,尽管它在结束“RefreshData”进程且值为 0 时显示正确的数据,我想做类似的事情它仅在轨迹栏滑块被释放时调用“RefreshData”,因此它不会处理到轨迹栏上释放点的所有步骤。

任何帮助和提示来实现这一点将不胜感激! 谢谢。

I have a trackbar in my WinForms program which by moving it a huge and time consuming method will be refreshed. Have a look at this code:

trackBar_ValueChanged(object sender, EventArgs e)
{
     this.RefreshData();
}

This track bar has 20 steps. If user grab the trackbar's slider and pull it from 20 to 0 in my case, 'RefreshData' will be executed 20 times although it shows correct data when it ends the process that is 'RefreshData' with value 0, I want to do something like it only calls the 'RefreshData' when the trackBar slider has been released so it wont process all the steps to the releasing point on the track bar.

Any help and tips to achieve this would be appericiated!
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

救赎№ 2024-11-09 10:20:34

怎么样:

Boolean user_done_updating = false;

private void MytrackBar_ValueChanged(object sender, EventArgs e)
{
    user_done_updating = true;
}

private void MytrackBar_MouseUp(object sender, MouseEventArgs e)
{
    if (user_done_updating)
    {
        user_done_updating = false;
        //Do Stuff
    }
}

How About:

Boolean user_done_updating = false;

private void MytrackBar_ValueChanged(object sender, EventArgs e)
{
    user_done_updating = true;
}

private void MytrackBar_MouseUp(object sender, MouseEventArgs e)
{
    if (user_done_updating)
    {
        user_done_updating = false;
        //Do Stuff
    }
}
原谅我要高飞 2024-11-09 10:20:34

我以前做过这种事情的方法是使用计时器。每次 TrackBar 的值发生变化时,重置计时器,使其在 500 毫秒内触发(或任何适合您的时间)。如果用户在计时器触发之前更改了该值,它将再次重置,这意味着即使更改多次,计时器也只会触发一次。

这里唯一需要注意的是,计时器将在不同的线程上触发,并且您将无法从该线程更新 UI,因此您必须调用回 UI 线程以在其中进行更改。不过,如果您可以将大部分昂贵的工作转移到这个后台线程上,您将使 UI 的响应时间保持更长时间。

这里有一些示例代码,应该可以让您了解我的意思。

public partial class Form1 : Form
{
    private int updateCount;
    private System.Threading.Timer timer;

    public Form1()
    {
        this.InitializeComponent();
        this.timer = new System.Threading.Timer(this.UpdateValue);
    }

    private void UpdateValue(object state)
    {
        // Prevent the user from changing the value while we're doing
        // our expensive operation
        this.Invoke(new MethodInvoker(() => this.trackBar1.Enabled = false));

        // Do the expensive updates - this is still on a background thread
        this.updateCount++;

        this.Invoke(new MethodInvoker(this.UpdateUI));
    }

    private void UpdateUI()
    {
        this.label1.Text = this.updateCount.ToString();

        // Re-enable the track bar again
        this.trackBar1.Enabled = true;
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Change(TimeSpan.FromMilliseconds(500), new TimeSpan(-1));
    }
}

编辑:这是一个使用 win 表单计时器来进行计时的解决方案。此处的区别在于,您将在计算运行时锁定 UI;对于您的情况来说,这可能可行,也可能不可行。

public partial class Form1 : Form
{
    private int updateCount;
    private Timer timer;

    public Form1()
    {
        this.InitializeComponent();

        this.timer = new Timer();
        this.timer.Interval = 500;
        this.timer.Tick += this.Timer_Tick;
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        this.timer.Stop();

        this.updateCount++;
        this.label1.Text = this.updateCount.ToString();
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Stop();
        this.timer.Start();
    }
}

The way that I've done this sort of thing before is to use a timer. Every time the value of the TrackBar changes, reset the timer so that it fires in 500ms (or whatever is appropriate for you). If the user changes the value before the timer fires, it will be reset again, meaning that even if it changes multiple times, the timer will only fire once.

The only thing to watch here is that the timer will fire on a different thread and you won't be able to update the UI from that thread, so you'll have to invoke back onto the UI thread to make changes there. That said, however, if you can move the majority of your expensive work onto this background thread, you'll keep the UI responsive for longer.

Here's some sample code that should give you some idea of what I mean.

public partial class Form1 : Form
{
    private int updateCount;
    private System.Threading.Timer timer;

    public Form1()
    {
        this.InitializeComponent();
        this.timer = new System.Threading.Timer(this.UpdateValue);
    }

    private void UpdateValue(object state)
    {
        // Prevent the user from changing the value while we're doing
        // our expensive operation
        this.Invoke(new MethodInvoker(() => this.trackBar1.Enabled = false));

        // Do the expensive updates - this is still on a background thread
        this.updateCount++;

        this.Invoke(new MethodInvoker(this.UpdateUI));
    }

    private void UpdateUI()
    {
        this.label1.Text = this.updateCount.ToString();

        // Re-enable the track bar again
        this.trackBar1.Enabled = true;
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Change(TimeSpan.FromMilliseconds(500), new TimeSpan(-1));
    }
}

Edit: Here's a solution that uses a win forms timer to do the timings. The difference here is that you'll lock the UI up while the calculation is running; this may or may not be ok in your situation.

public partial class Form1 : Form
{
    private int updateCount;
    private Timer timer;

    public Form1()
    {
        this.InitializeComponent();

        this.timer = new Timer();
        this.timer.Interval = 500;
        this.timer.Tick += this.Timer_Tick;
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        this.timer.Stop();

        this.updateCount++;
        this.label1.Text = this.updateCount.ToString();
    }

    private void trackBar1_ValueChanged(object sender, EventArgs e)
    {
        this.timer.Stop();
        this.timer.Start();
    }
}
一张白纸 2024-11-09 10:20:34

考虑在新线程中执行长时间运行的方法。维护对该线程的引用并在重新启动之前调用 Thread.Abort()。

Consider executing the long-running method in a new thread. Maintain a reference to that thread and call Thread.Abort() before re-starting it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文