wpf 动画 - 鼠标按下事件不起作用

Posted

技术标签:

【中文标题】wpf 动画 - 鼠标按下事件不起作用【英文标题】:wpf animation -- mouse down event doesn't work 【发布时间】:2016-09-22 15:08:03 【问题描述】:

每次都有一个蓝色矩形从窗口的左侧向右移动不同的距离。

无论是单击矩形还是动画完成,矩形都会从左侧重新开始移动。

如果点击矩形,它的颜色会变成绿色,持续时间为0.3s。

但是 MouseDown 事件似乎没有启动 ColorAnimation 并且矩形的移动距离/持续时间也不正确。

private int i;
private Storyboard hitTargetStoryboard;
private List<double> disList;

private void Window_Loaded(object sender, RoutedEventArgs e)

    disList = new List<double>.......;  // init with a list of values.

    /* Create a rectangle */
    Rectangle rect = new Rectangle();
    this.RegisterName("rect", rect);
    rect.Height = this.ActualHeight;
    rect.Width = 50;
    Canvas.SetTop(rect, 0);
    Canvas.SetLeft(rect, 0);

    /* Fill rect with a solid brush */
    SolidColorBrush targetRectBrush = new SolidColorBrush(Colors.Blue);
    this.RegisterName("targetRectBrush", targetRectBrush);
    rect.Fill = targetRectBrush;

    /* Add mouse down event */
    rect.MouseDown += Rect_MouseDown;

    /* Add rect to Canvas */
    myCanvas.Children.Add(rect);

    /* Create ColorAnimation to change color smoothly */
    ColorAnimation hitCA = new ColorAnimation();
    hitCA.To = Colors.Green;
    hitCA.Duration = TimeSpan.FromSeconds(0.3);
    hitCA.Completed += HitCA_Completed;

    /* Create storyboard and add ColorAnimation to it */
    hitTargetStoryboard = new Storyboard();
    Storyboard.SetTargetName(hitCA, "targetRectBrush");
    Storyboard.SetTargetProperty(hitCA, new PropertyPath(SolidColorBrush.ColorProperty));
    hitTargetStoryboard.Children.Add(hitCA);

    i = 0;
    TargetAnimation(i);



/* move the rect from 0--disList[i] */
private void TargetAnimation(int i)

    (this.FindName("rect") as Rectangle).Fill = Brushes.Blue;
    DoubleAnimation da = new DoubleAnimation();
    da.From = 0;
    da.To = disList[i];
    da.Duration = TimeSpan.FromSeconds(5);

    Storyboard.SetTargetName(da, "rect");
    Storyboard.SetTargetProperty(da, new PropertyPath(Canvas.LeftProperty));
    Storyboard storyboard = new Storyboard();
    storyboard.Children.Add(da);
    storyboard.Completed += Storyboard_Completed;
    storyboard.Begin(this);


/* If rect clicked, it will change color to green */
private void Rect_MouseDown(object sender, MouseButtonEventArgs e)

    hitTargetStoryboard.Begin(this);


/* After color changed, rect starts over */
private void HitCA_Completed(object sender, EventArgs e)

    TargetAnimation(++i);


/* If rect not clicked, it will start over */
private void Storyboard_Completed(object sender, EventArgs e)

    TargetAnimation(++i);

更新:

删除:(this.FindName("rect") as Rectangle).Fill = Brushes.Blue;

添加:hitCA.From = Colors.Blue;

ColorAnimation 效果很好。

静止:

如果我删除Storyboard_CompletedHitCA_Completed,rect 的移动顺利。而如果我两者都有,那么运动就会走错路。

更新 2:

编辑:storyboard.Begin(this, true)TargetAnimation(int i) 方法中。

HitCA_Completed 方法中添加:stroyboard.Stop(this)

如果不将isControallable设置为true,故事板将无法控制。

已解决

【问题讨论】:

它是从Window 派生的MainWindow 类的一部分。矩形是 System.Windows.Shapes.Rectangle。 @PetterHesselberg 【参考方案1】:

你的问题在这里:

(this.FindName("rect") as Rectangle).Fill = Brushes.Blue;

首先,将rect设为字段并直接设置Fill属性会容易得多:

rect.Fill = Brushes.Blue;

不过,这对您的彩色动画没有帮助。你已经设置了一个动画来使用targetRectBrush——它不再填充rect,因为你刚刚替换了它。删除那条线会为颜色设置动画。

更新

这是一个稍微调整的版本:

public partial class MainWindow

    private int i;
    private Storyboard hitTargetStoryboard;
    private List<double> disList;
    private Rectangle rect;

    public MainWindow()
    
        InitializeComponent();
        Loaded += Window_Loaded;
    

    private void Window_Loaded(object sender, RoutedEventArgs e)
    
        disList = new List<double> 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ;  // init with a list of values.

        /* Create a rectangle */
        rect = new Rectangle();
        this.RegisterName("rect", rect);
        rect.Height = this.ActualHeight;
        rect.Width = 50;
        Canvas.SetTop(rect, 0);
        Canvas.SetLeft(rect, 0);

        /* Fill rect with a solid brush */
        SolidColorBrush targetRectBrush = new SolidColorBrush(Colors.Blue);
        this.RegisterName("targetRectBrush", targetRectBrush);
        rect.Fill = targetRectBrush;

        /* Add mouse down event */
        rect.MouseDown += Rect_MouseDown;

        /* Add rect to Canvas */
        myCanvas.Children.Add(rect);

        /* Create ColorAnimation to change color smoothly */
        ColorAnimation hitCA = new ColorAnimation
            
                From = Colors.Blue, // (Instead of setting Fill to Blue)
                To = Colors.Green,
                Duration = TimeSpan.FromSeconds(0.3),
                FillBehavior = FillBehavior.Stop, // Returns to Blue
            ;
        hitCA.Completed += HitCA_Completed;

        /* Create storyboard and add ColorAnimation to it */
        hitTargetStoryboard = new Storyboard();
        Storyboard.SetTargetName(hitCA, "targetRectBrush");
        Storyboard.SetTargetProperty(hitCA, new PropertyPath(SolidColorBrush.ColorProperty));
        hitTargetStoryboard.Children.Add(hitCA);

        i = 0;
        TargetAnimation(i);
    


    /* move the rect from 0--disList[i] */
    private void TargetAnimation(int i)
    
        i = i % disList.Count; // Don't overflow

        DoubleAnimation da = new DoubleAnimation
            
                From = 0,
                To = disList[i],
                Duration = TimeSpan.FromSeconds(5),
            ;

        Storyboard.SetTargetName(da, "rect");
        Storyboard.SetTargetProperty(da, new PropertyPath(Canvas.LeftProperty));
        Storyboard storyboard = new Storyboard();
        storyboard.Children.Add(da);
        storyboard.Completed += Storyboard_Completed;
        storyboard.Begin(this);
    

    /* If rect clicked, it will change color to green */
    private void Rect_MouseDown(object sender, MouseButtonEventArgs e)
    
        hitTargetStoryboard.Begin(this);
    

    /* After color changed, rect starts over */
    private void HitCA_Completed(object sender, EventArgs e)
    
        TargetAnimation(++i);
    

    /* If rect not clicked, it will start over */
    private void Storyboard_Completed(object sender, EventArgs e)
    
        TargetAnimation(++i);
    

您发现距离/持续时间有什么问题?

【讨论】:

我删除了该行并且 colorAnimation 有效。但我需要将矩形恢复为蓝色。我该怎么办? 另外,移动 rect 的 DoubleAnimation 在 rect 中途停止的 MouseDown 事件后效果不佳。 我已经更新了我的答案,将FillBehavior 设置为将颜色恢复为蓝色。我不明白你的运动有什么问题;当彩色动画完成时,您显式调用TargetAnimation。如果这不是你想要的,你可以完全放弃HitCA_Completed Storyboard_Completed 是在完成后重新开始移动的那个。 HitCA_Completed 是在彩色动画完成后重新开始运动的那个。如果我理解正确,您需要保留 Storyboard_Completed,但删除 HitCA_Completed... 你能解释一下“运行错误”是什么意思吗?可以想象,您需要在开始新动画之前停止任何正在运行的动画。以下是关于在代码中控制动画的相当不错的读物:msdn.microsoft.com/en-us/library/ms741997(v=vs.110).aspx

以上是关于wpf 动画 - 鼠标按下事件不起作用的主要内容,如果未能解决你的问题,请参考以下文章

WPF DataGridCheckBoxColumn检查/取消选中有时不起作用

当我有鼠标悬停事件时,Animate()不起作用

按下按钮时 Gtkmm scroll_event 不起作用

鼠标按下时CSS光标更改不起作用

鼠标滚动在带有 wpf 数据网格和其他 UI 元素的滚动查看器中不起作用

WPF中MouseDown事件不起作用