跟踪栏仅在最终值上触发事件,而不会在时间值发生变化时触发事件

发布于 2025-01-04 00:20:37 字数 404 浏览 1 评论 0原文

我正在开发一个非常基本的 C# Visual Studio 表单应用程序,但在让轨迹栏按照我想要的方式运行时遇到一些问题,因此希望社区中的某个人可以为此提供解决方案。

我所拥有的是一个非常基本的应用程序,其主要部分是一个值为 0 到 100 的轨迹栏。用户设置轨迹的值来表示“要执行的工作量”,此时程序将达到一些设备并告诉它们做“x”量的工作(x 是轨迹栏的值)。因此,我所做的就是使用轨迹栏滚动事件来捕获轨迹栏值何时发生更改,并在处理程序内部调用设备并告诉它们需要完成多少工作。

我的问题是,我的事件处理程序会为跟踪栏当前所在位置和结束位置之间的每个值调用。因此,如果它从 10 滑动到 30,我的事件处理程序将被调用 20 次,这意味着我正在联系我的设备并告诉它们以我什至不希望它们运行的​​值运行。是否只有在滚动停止发生时才发生事件,以便您可以检查最终值?

I am working on a pretty basic C# visual studio forms application but am having some issue getting the track bar to act as I want it to so hoping someone in the community might have a solution for this.

What I have is a pretty basic application with the main part being a track bar with a value of 0 to 100. The user sets the value of the track to represent "the amount of work to perform" at which point the program reaches out to some devices and tells them to do "x" amount of work (x being the value of the trackbar). So what I do is use the track bars scroll event to catch when the track bars value has changed and inside the handler call out to the devices and tells them how much work to do.

My issue is that my event handler is called for each value between where the track bar currently resides and where ever it ends. So if it is slid from 10 to 30, my event handler is called 20 times which means I am reaching out to my devices and telling them to run at values I don't even want them to run at. Is there someway only to event when scroll has stopped happening so you can check the final value?

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

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

发布评论

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

评论(9

人间☆小暴躁 2025-01-11 00:20:38

尝试使用 MouseCaptureChanged 事件 - 这是此任务的最佳选择

Try the MouseCaptureChanged event - that is the best for this task

羁客 2025-01-11 00:20:38

用户还可以在短时间内多次移动轨迹栏,或者多次单击轨迹来增加拇指,而不是拖动拇指。所有这些都是其他情况,其中在“拇指移动”结束时注册的值实际上并不是用户想要的最终值。

听起来您需要一个按钮来确认更改,然后该按钮会捕获轨迹栏的当前值并将其发送到您的设备。

A user could also move the track bar multiple times in a short period of time, or click on the track multiple times to increment the thumb over instead of dragging the thumb. All being additional cases where the value that registers at the end of a "thumb move" is not really the final value your user desires.

Sounds like you need a button to confirm the change, which would then capture the current value of the trackbar and send it off to your devices.

孤寂小茶 2025-01-11 00:20:38

使用 trackbar_valuechanged 事件处理程序尝试此操作:

trackbar_valuechanged(s,e) {
    if(trackbar.value == 10){
        //Do whatever you want
    } else{
        //Do nothing or something else
    }
}

Try this with the trackbar_valuechanged event handler:

trackbar_valuechanged(s,e) {
    if(trackbar.value == 10){
        //Do whatever you want
    } else{
        //Do nothing or something else
    }
}
魂归处 2025-01-11 00:20:38

我发现一个相当可靠的方法是使用连接在 trackbar.Scroll 事件中的计时器:

private Timer _scrollingTimer = null;

private void trackbar_Scroll(object sender, EventArgs e)
{
    if (_scrollingTimer == null)
    {
        // Will tick every 500ms (change as required)
        _scrollingTimer = new Timer() 
        {
                Enabled = false,
                Interval = 500,
                Tag = (sender as TrackBar).Value
        };
        _scrollingTimer.Tick += (s, ea) =>
        {
            // check to see if the value has changed since we last ticked
            if (trackBar.Value == (int)_scrollingTimer.Tag)
            {
                // scrolling has stopped so we are good to go ahead and do stuff
                _scrollingTimer.Stop();

                // Do Stuff Here . . .

                _scrollingTimer.Dispose();
                _scrollingTimer = null;
            }
            else
            {
                // record the last value seen
                _scrollingTimer.Tag = trackBar.Value;
            }
        };
        _scrollingTimer.Start();
    }
}

I found a fairly reliable way to do this is to use a timer hooked up in the trackbar.Scroll event:

private Timer _scrollingTimer = null;

private void trackbar_Scroll(object sender, EventArgs e)
{
    if (_scrollingTimer == null)
    {
        // Will tick every 500ms (change as required)
        _scrollingTimer = new Timer() 
        {
                Enabled = false,
                Interval = 500,
                Tag = (sender as TrackBar).Value
        };
        _scrollingTimer.Tick += (s, ea) =>
        {
            // check to see if the value has changed since we last ticked
            if (trackBar.Value == (int)_scrollingTimer.Tag)
            {
                // scrolling has stopped so we are good to go ahead and do stuff
                _scrollingTimer.Stop();

                // Do Stuff Here . . .

                _scrollingTimer.Dispose();
                _scrollingTimer = null;
            }
            else
            {
                // record the last value seen
                _scrollingTimer.Tag = trackBar.Value;
            }
        };
        _scrollingTimer.Start();
    }
}
陌路终见情 2025-01-11 00:20:38

我刚刚遇到了这个问题,因为我正在实现一个内置视频播放器,并希望用户能够更改视频的位置,但我不想通过为每个视频播放 API 发送 SetPosition 调用来超载视频播放 API勾选用户在前往最终目的地的途中经过的位置。

这是我的解决方案:

首先,方向键是一个问题。您可以尽力通过计时器或其他机制来处理箭头键,但我发现它比它值得的更痛苦。因此,如 @Matthias 提到的,将属性 SmallChange 和 LargeChange 设置为 0。

对于鼠标输入,用户必须向下单击、移动它,然后放开,以便处理轨迹栏的 MouseDown、MouseUp 和 Scroll 事件,如下所示:

    private bool trackbarMouseDown = false;
    private bool trackbarScrolling = false;

    private void trackbarCurrentPosition_Scroll(object sender, EventArgs e)
    {
        trackbarScrolling = true;
    }

    private void trackbarCurrentPosition_MouseUp(object sender, MouseEventArgs e)
    {
        if (trackbarMouseDown == true && trackbarScrolling == true)
            Playback.SetPosition(trackbarCurrentPosition.Value);
        trackbarMouseDown = false;
        trackbarScrolling = false;
    }

    private void trackbarCurrentPosition_MouseDown(object sender, MouseEventArgs e)
    {
        trackbarMouseDown = true;
    }

I had this problem just now as I'm implementing a built in video player and would like the user to be able to change the position of the video but I didn't want to overload the video playback API by sending it SetPosition calls for every tick the user passed on the way to his/her final destination.

This is my solution:

First, the arrow keys are a problem. You can try your best to handle the arrow keys via a timer or some other mechanism but I found it more pain than it is worth. So set the property SmallChange and LargeChange to 0 as @Matthias mentioned.

For mouse input, the user is going to have to click down, move it, and let go so handle the MouseDown, MouseUp, and the Scroll events of the trackbar like so:

    private bool trackbarMouseDown = false;
    private bool trackbarScrolling = false;

    private void trackbarCurrentPosition_Scroll(object sender, EventArgs e)
    {
        trackbarScrolling = true;
    }

    private void trackbarCurrentPosition_MouseUp(object sender, MouseEventArgs e)
    {
        if (trackbarMouseDown == true && trackbarScrolling == true)
            Playback.SetPosition(trackbarCurrentPosition.Value);
        trackbarMouseDown = false;
        trackbarScrolling = false;
    }

    private void trackbarCurrentPosition_MouseDown(object sender, MouseEventArgs e)
    {
        trackbarMouseDown = true;
    }
浮生未歇 2025-01-11 00:20:38

我也遇到了类似的问题,只是使用了范围 TrackBar 控件。同样的想法也适用于这个,只是对于这种情况来说更容易。

我处理了 TrackBar 上的 MouseUp 事件,以便在您松开鼠标按钮后启动我需要的程序。如果您将该栏拖动到所需位置或仅单击它,则此操作有效。

私有无效rangeTrackBarControl1_MouseUp(对象发送者,System.Windows.Forms.MouseEventArgs e)
{
你的程序在这里();
}

I had a similar problem, only with a range TrackBar Control. Same idea applies to this also, only it's easier for this case.

I handled the MouseUp Event on the TrackBar to launch the procedures I needed, only after you would let go of the mouse button. This works if you drag the bar to your desired position or just click it.

private void rangeTrackBarControl1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
YourProcedureHere();
}

请帮我爱他 2025-01-11 00:20:38

我通过两个事件解决了我的应用程序的问题:

  1. 捕获值更改事件中的 Trackbar-ValueChange-Event
  2. 禁用 valuechange 事件并启用 MouseUp-Event
    public MainWindow()
        {
            //Event for new Trackbar-Value
            trackbar.ValueChanged += new System.EventHandler(trackbar_ValueChanged);
        }
    
    private void trackbar_ValueChanged(object sender, EventArgs e)
        {
            //enable Trackbar Mouse-ButtonUp-Event
            trackbar.MouseUp += ch1_slider_MouseUp;
            //disable Trackbar-ValueChange-Event
            trackbar.ValueChanged -= ch1_slider_ValueChanged;
        }

        private void trackbar_MouseUp(object sender, EventArgs e)
        {
            //enable Trackbar-ValueChange-Event again
            trackbar.ValueChanged += new System.EventHandler(trackbar_ValueChanged);
            //disable Mouse-ButtonUp-Event
            trackbar.MouseUp -= trackbar_MouseUp;

            //This is the final trackbar-value
            textBox.AppendText(trackbar.Value);
        }

注意:如果轨迹栏被鼠标移动,则此方法有效。也可以通过键盘移动轨迹栏。然后必须实现进一步的代码来处理该事件。

i solved the problem for my application with two events:

  1. catch the Trackbar-ValueChange-Event
  2. whithin the value-change event disable the valuechange event and enable the MouseUp-Event
    public MainWindow()
        {
            //Event for new Trackbar-Value
            trackbar.ValueChanged += new System.EventHandler(trackbar_ValueChanged);
        }
    
    private void trackbar_ValueChanged(object sender, EventArgs e)
        {
            //enable Trackbar Mouse-ButtonUp-Event
            trackbar.MouseUp += ch1_slider_MouseUp;
            //disable Trackbar-ValueChange-Event
            trackbar.ValueChanged -= ch1_slider_ValueChanged;
        }

        private void trackbar_MouseUp(object sender, EventArgs e)
        {
            //enable Trackbar-ValueChange-Event again
            trackbar.ValueChanged += new System.EventHandler(trackbar_ValueChanged);
            //disable Mouse-ButtonUp-Event
            trackbar.MouseUp -= trackbar_MouseUp;

            //This is the final trackbar-value
            textBox.AppendText(trackbar.Value);
        }

ATTENTION: this works if the trackbar is moved by mose. It is also possible to move the trackbar by keyboard. Then futher code must be implemented to handle this event.

抚你发端 2025-01-11 00:20:38

这是 wpf 但同样的问题。我使用滑块以 1 为步长设置 0 ... 8 之间的值。很容易使用轨迹栏的最终值更新文本框。但对于“ValueChanged”从未提供实际值,而总是以前的值,我最终使用 PreviewMouseLeftButtonUp 事件以及 KeyUp 事件来使用键盘移动滑块。

<StackPanel Grid.Row="5" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" MinHeight="20">
    <Slider Name="SliderResistor" Maximum="8" Minimum="0" TickFrequency="1" IsSnapToTickEnabled="True" HorizontalAlignment="Left" Margin="0,0" VerticalAlignment="Top" Width="135">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                <i:InvokeCommandAction Command="{Binding UseValueCommand}" CommandParameter="{Binding ElementName=SliderResistor, Path=Value}"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="KeyUp">
                <i:InvokeCommandAction Command="{Binding UseValueCommand}" CommandParameter="{Binding ElementName=SliderResistor, Path=Value}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Slider>
    <TextBox Name="tbResistorValue" MinWidth="20" Height="20" IsReadOnly="True" Text="{Binding ElementName=SliderResistor, Path=Value, UpdateSourceTrigger=PropertyChanged}" AcceptsReturn="True">
    </TextBox>
    <Label Content="Ω"></Label>
</StackPanel>

这两个事件都会触发命令“UseValueCommand”,该命令将滑块的值传送到底层模型以在那里执行一些操作。
因此,如果我使用鼠标从位置“2”移动到“5”,则在释放鼠标按钮时将使用参数“5”调用该命令。
按向右箭头键会将值从“2”设置为“3”,该命令将使用参数“3”调用。

This is wpf but the same problem. I use a slider to set a value from 0 ... 8 in steps of 1. It was easy to get a TextBox updated with the final value of the trackbar. But for 'ValueChanged' never served the actual value but always the one before, I finally landed using the PreviewMouseLeftButtonUp-event as well as the KeyUp-event for moving the slider with the keyboard.

<StackPanel Grid.Row="5" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" MinHeight="20">
    <Slider Name="SliderResistor" Maximum="8" Minimum="0" TickFrequency="1" IsSnapToTickEnabled="True" HorizontalAlignment="Left" Margin="0,0" VerticalAlignment="Top" Width="135">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="PreviewMouseLeftButtonUp">
                <i:InvokeCommandAction Command="{Binding UseValueCommand}" CommandParameter="{Binding ElementName=SliderResistor, Path=Value}"/>
            </i:EventTrigger>
            <i:EventTrigger EventName="KeyUp">
                <i:InvokeCommandAction Command="{Binding UseValueCommand}" CommandParameter="{Binding ElementName=SliderResistor, Path=Value}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Slider>
    <TextBox Name="tbResistorValue" MinWidth="20" Height="20" IsReadOnly="True" Text="{Binding ElementName=SliderResistor, Path=Value, UpdateSourceTrigger=PropertyChanged}" AcceptsReturn="True">
    </TextBox>
    <Label Content="Ω"></Label>
</StackPanel>

Both events trigger a command 'UseValueCommand' that carries the value of the slider to the underlying model to do some work there.
So in case I would move from position '2' to '5' using the mouse the command will be called with parameter '5' when releasing the mouse button.
Pressing the right arrow key will set the value from '2' to '3', the command will be called with parameter '3'.

我不咬妳我踢妳 2025-01-11 00:20:37

如果用户单击了轨迹栏,只需检查一个变量。如果是这样,则延迟输出。

bool clicked = false;
trackBar1.Scroll += (s,
                        e) =>
{
    if (clicked)
        return;
    Console.WriteLine(trackBar1.Value);
};
trackBar1.MouseDown += (s,
                        e) =>
{
    clicked = true;
};
trackBar1.MouseUp += (s,
                        e) =>
{
    if (!clicked)
        return;

    clicked = false;
    Console.WriteLine(trackBar1.Value);
};

对于@roken提到的问题,您可以将LargeChange和SmallChange设置为0。

Just check a variable, if the user clicked the track bar. If so, delay the output.

bool clicked = false;
trackBar1.Scroll += (s,
                        e) =>
{
    if (clicked)
        return;
    Console.WriteLine(trackBar1.Value);
};
trackBar1.MouseDown += (s,
                        e) =>
{
    clicked = true;
};
trackBar1.MouseUp += (s,
                        e) =>
{
    if (!clicked)
        return;

    clicked = false;
    Console.WriteLine(trackBar1.Value);
};

For the problem @roken mentioned, you can set LargeChange and SmallChange to 0.

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