C# 用于WPF显示的计时器,具有奇怪的行为
我用WPF制作了一个有几个按钮的面板。 当鼠标进入某个按钮时,会出现新按钮,并在鼠标离开1000毫秒后消失 但我有一个奇怪的行为:在某些情况下,1000毫秒在每次使用后变得越来越短 计时器事件C# 用于WPF显示的计时器,具有奇怪的行为,c#,.net,wpf,C#,.net,Wpf,我用WPF制作了一个有几个按钮的面板。 当鼠标进入某个按钮时,会出现新按钮,并在鼠标离开1000毫秒后消失 但我有一个奇怪的行为:在某些情况下,1000毫秒在每次使用后变得越来越短 计时器事件 private void TimerEventProcessorForButtonA(Object myObject, EventArgs myEventArgs) { _myTimerForButtonA.Stop(); miniButton1.Visibility = System.
private void TimerEventProcessorForButtonA(Object myObject, EventArgs myEventArgs)
{
_myTimerForButtonA.Stop();
miniButton1.Visibility = System.Windows.Visibility.Hidden;
}
private void TimerEventProcessorForButtonB(Object myObject, EventArgs myEventArgs)
{
_myTimerForButtonB.Stop();
miniButton2.Visibility = System.Windows.Visibility.Hidden;
}
WaitTime函数调用计时器:
public void WaitThisTimeAndHideMiniButton1(int givenTime)
{
_myTimerForButtonA = new System.Windows.Forms.Timer();
_myTimerButtonA.Tick += new EventHandler(TimerEventProcessorForForButtonA);
_myTimerForForButtonA.Interval = givenTime;
_myTimerForForButtonA.Start();
}
public void WaitThisTimeAndHideMiniButton2(int givenTime)
{
_myTimerForButtonB = new System.Windows.Forms.Timer();
_myTimerForButtonB.Tick += new EventHandler(TimerEventProcessorForForButtonB);
_myTimerForForButtonB.Interval = givenTime;
_myTimerForForButtonB.Start();
}
“离开”按钮时发生的事件:
private void buttonA_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton1(1000); // hide minibuttons
}
private void buttonB_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush) new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton2(1000);
}
如代码中所述,我有buttonA和buttonB。当我输入buttonA时,miniButton1出现-它将在鼠标离开事件1000毫秒后消失。
buttonB和miniButton2一样
如果我只按进出按钮,一切都是正确的。和ButtonA一样。
问题:如果我输入/离开按钮A和B,那么这1000毫秒会越来越短。在我离开按钮A和B之前,迷你按钮也会消失。在我离开按钮之前,迷你按钮也会消失
每件事都表现得好像计时器在互相混淆。
你知道怎么解决吗?所以基本上这是在鼠标离开时发生的:
creating the timer
starting the timer
当计时器过期时会发生这种情况:
stopping the timer
所以,若鼠标反复进入和离开一个按钮,它会不断创建和启动新的计时器。这会导致多个计时器同时运行
public void WaitThisTimeAndHideMiniButton1(int givenTime)
{
if(_myTimerForButtonA != null && _myTimerForButtonA.Enabled)
{
_myTimerForButtonA.Stop();
}
_myTimerForButtonA = new System.Windows.Forms.Timer();
_myTimerButtonA.Tick += new EventHandler(TimerEventProcessorForForButtonA);
_myTimerForForButtonA.Interval = givenTime;
_myTimerForForButtonA.Start();
}
尽管如评论中所述,此处存在更多问题,但这应该可以解决该问题。每次触发
MouseLeave
事件时,如果您在1000毫秒内两次触发该事件,您将重新创建一个新的计时器,在执行上一个计时器的勾选事件之前,您将重新创建一个新的计时器
,这将使上一个计时器
无限期运行
以下是在1000毫秒内两次触发MouseLeave
事件时发生的情况:
1) MouseLeave: _myTimerForButtonA is assigned a new Timer instance (ie: Timer1), Tick event registered.
2) MouseLeave: _myTimerForButtonA is assigned a new Timer instance (ie: Timer2), Tick event registered.
3) Timer1.Tick event fires TimerEventProcessorForButtonA, whichs stops _myTimerForButtonA which points to Timer2.
4) Timer2.Tick event fires TimerEventProcessorForButtonA, whichs stops _myTimerForButtonA which points to Timer2 (and is already stopped).
5) Timer1.Tick event fires TimerEventProcessorForButtonA indefinitely, because Timer1 is not referenced anymore and no one will ever call `Stop` on it.
我可以通过停止MouseEnter
事件上的计时器来修复您的代码
private void TimerEventProcessorForButtonA(Object myObject, EventArgs myEventArgs)
{
Debug.WriteLine("TimerEventProcessorForButtonA");
_myTimerForButtonA.Stop();
_myTimerForButtonA.Dispose();
miniButton1.Visibility = System.Windows.Visibility.Hidden;
}
private void TimerEventProcessorForButtonB(Object myObject, EventArgs myEventArgs)
{
Debug.WriteLine("** TimerEventProcessorForButtonB");
_myTimerForButtonB.Stop();
_myTimerForButtonB.Dispose();
miniButton2.Visibility = System.Windows.Visibility.Hidden;
}
public void WaitThisTimeAndHideMiniButton1(int givenTime)
{
_myTimerForButtonA = new System.Windows.Forms.Timer();
_myTimerForButtonA.Tick += new EventHandler(TimerEventProcessorForButtonA);
_myTimerForButtonA.Interval = givenTime;
_myTimerForButtonA.Start();
}
public void WaitThisTimeAndHideMiniButton2(int givenTime)
{
_myTimerForButtonB = new System.Windows.Forms.Timer();
_myTimerForButtonB.Tick += new EventHandler(TimerEventProcessorForButtonB);
_myTimerForButtonB.Interval = givenTime;
_myTimerForButtonB.Start();
}
private void buttonA_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton1(1000); // hide minibuttons
}
private void buttonB_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
Border button = sender as Border;
button.Background = (SolidColorBrush)new BrushConverter().ConvertFromString(_colorOut);
WaitThisTimeAndHideMiniButton2(1000);
}
private void buttonA_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_myTimerForButtonA?.Enabled == true)
_myTimerForButtonA.Stop();
miniButton1.Visibility = System.Windows.Visibility.Visible;
}
private void buttonB_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_myTimerForButtonB?.Enabled == true)
_myTimerForButtonB.Stop();
miniButton2.Visibility = System.Windows.Visibility.Visible;
}
正如你在文章的评论中所说,你不应该每次都创建一个新的计时器,你应该在完成后处理它。此外,在WPF项目中引用表单是一个坏主意,除非真的有必要,否则很少有必要。您可能需要阅读有关UI动画的内容。类System.Windows.Forms.Timer
实现IDisposable
。在创建新实例之前,是否要先处理以前的每个实例?不这样做可能会导致您的问题。你能试试看这是否能解决问题吗?需要水晶球应用程序。由于重复创建计时器对象,您遇到了麻烦。坏主意不止一种,你抱怨的是,前一个计时器对象仍然在愉快地滴答作响,所以按钮消失得太快了。更糟糕的是,它从未停止过,因为您无法再调用它的Stop()方法。仅在窗口的构造函数中创建一次计时器对象。使用Closed事件来处置它们。请查看Dispatchermer。不要在WPF应用程序中使用System.Windows.Forms.Timer
。改用System.Windows.Threading.dispatchermer
。不需要处理调度程序。如前所述,只创建一次计时器实例。然后反复启动和停止一个现有的计时器。正如前面提到的,我创建了计时器1次,只需使用停止和启动,它就可以工作了@克莱门斯:为什么WPF中不能使用System.Windows.Forms.Timer(实际上它不是winform,但会引发哪个问题)?请阅读此处的备注: