鼠标活动减缓了WPF图形演示

时间:2012-11-07 01:58:12

标签: c# wpf

下面是WPF中的一个小型图形演示。它看起来像这样:

enter image description here

当它运行时,如果我在窗口的主区域周围移动鼠标,动画会变慢(至少在我的系统上)。如果我将鼠标指针完全移出窗口,动画会恢复速度。

有关如何防止鼠标移动干扰动画速度的任何建议吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Threading;

namespace WPF_Golden_Section
{
    class DrawingVisualElement : FrameworkElement
    {
        public DrawingVisual visual;

        public DrawingVisualElement() { visual = new DrawingVisual(); }

        protected override int VisualChildrenCount { get { return 1; } }

        protected override Visual GetVisualChild(int index) { return visual; }
    }

    public static class CanvasUtils
    {
        public static Canvas SetCoordinateSystem(this Canvas canvas, Double xMin, Double xMax, Double yMin, Double yMax)
        {
            var width = xMax - xMin;
            var height = yMax - yMin;

            var translateX = -xMin;
            var translateY = height + yMin;

            var group = new TransformGroup();

            group.Children.Add(new TranslateTransform(translateX, -translateY));
            group.Children.Add(new ScaleTransform(canvas.ActualWidth / width, canvas.ActualHeight / -height));

            canvas.RenderTransform = group;

            return canvas;
        }
    }

    public static class ColorUtils
    {
        public static Color Write(this Color color)
        {
            Console.Write("Color[{0} {1} {2} {3}]", color.A, color.R, color.G, color.B);

            return color;
        }

        static byte ColorComponentToByte(double n)
        {
            return 
                (byte)
                    Math.Round(Math.Min(Math.Max(n, 0), 1) * 255);
        }

        public static Color Rgb(double r, double g, double b)
        {
            return
                Color.FromRgb(
                    ColorComponentToByte(r),
                    ColorComponentToByte(g),
                    ColorComponentToByte(b));
        }

        public static Color SetArgb(this Color color, double a, double r, double g, double b)
        {
            color.A = ColorComponentToByte(a);
            color.R = ColorComponentToByte(r);
            color.G = ColorComponentToByte(g);
            color.B = ColorComponentToByte(b);

            return color;
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Width = 600;
            Height = 600;

            var dockPanel = new DockPanel();

            Content = dockPanel;

            var slider =
                new Slider()
                {
                    Minimum = 0.1,
                    Maximum = 10,
                    LargeChange = 0.001,
                    Value = 1
                };

            dockPanel.Children.Add(slider);

            DockPanel.SetDock(slider, Dock.Top);

            var incrementSlider =
                new Slider()
                {
                    Maximum = 0.001,
                    Minimum = 0.00001,
                    Value = 0.0001
                };

            dockPanel.Children.Add(incrementSlider);


            DockPanel.SetDock(incrementSlider, Dock.Top);

            var pauseButton = new Button() { Content = "Pause" };

            dockPanel.Children.Add(pauseButton);

            DockPanel.SetDock(pauseButton, Dock.Top);

            var canvas = new Canvas();

            dockPanel.Children.Add(canvas);

            DockPanel.SetDock(canvas, Dock.Top);

            SizeChanged += (s, e) => canvas.SetCoordinateSystem(-400, 400, -400, 400);

            var element = new DrawingVisualElement();

            Action draw = () =>
                {
                    canvas.Children.Clear();

                    // var element = new DrawingVisualElement();

                    using (var dc = element.visual.RenderOpen())
                    {
                        for (var i = 0.0; i < 720.0; i += slider.Value)
                        {
                            var radius = Math.Sin(i / 720.0 * Math.PI) * 30;

                            var phi = (1 + Math.Sqrt(5)) / 2;

                            var omega = 2 * Math.PI * (phi - 1) * i;

                            var x = Math.Cos(omega) * 0.5 * i;
                            var y = Math.Sin(omega) * 0.5 * i;

                            dc.DrawEllipse(
                                new SolidColorBrush(ColorUtils.Rgb(i / 360.0, i / 360.0, 0.25)),
                                new Pen(Brushes.Black, Math.Max(radius / 6, 1)),
                                new Point(x, y),
                                radius / 2,
                                radius / 2);
                        }
                    }

                    canvas.Children.Add(element);
                };

            slider.ValueChanged += (s, e) =>
            {
                Title = slider.Value.ToString() + "     " + incrementSlider.Value;
                draw();
            };

            var timer = new DispatcherTimer();

            timer.Tick += (s, e) =>
                {
                    if (slider.Value < 10.0)
                        slider.Value += incrementSlider.Value;
                };

            timer.Start();

            pauseButton.Click += (s, e) =>
                {
                    if (timer.IsEnabled)
                        timer.Stop();
                    else
                        timer.Start();
                };

            slider.Value = 3.5;
            incrementSlider.Value = 0.00001;
        }
    }
}

2 个答案:

答案 0 :(得分:3)

如果你在WPF,CompositionTarget.Rendering事件中使用第三个动画选项,那么我发现没有减速。我已经使用slider.ValueChanged:

调整了样本中的代码
        slider.Value = 3.5;
        incrementSlider.Value = 0.00001;

        EventHandler renderer = (s, e) =>
        {
            if (slider.Value < 10.0)
                slider.Value += incrementSlider.Value;

            //Title = slider.Value.ToString() + "     " + incrementSlider.Value;
            draw();
            _frameCounter++;
        };

        CompositionTarget.Rendering += renderer;
        pauseButton.Click += (sender, args) => CompositionTarget.Rendering -= renderer;

        var timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(1000);
        timer.Tick += (s, e) =>
                          {
                              Title = string.Format("fps: {0}", _frameCounter);
                              _frameCounter = 0;
                          };

        timer.Start();

CompositionTarget.Rendering以固定的60 fps速率发射,除非机器负载很重。您可以在互联网上找到代码来调整framedrops并避免可见的减速。

对于因示例中的鼠标活动导致的减速,我没有很好的解释。我的第一个想法是它是路由事件的基础上的瓶颈,但是通过从ValueChanged事件中提取draw方法来调整计时器间隔或重构似乎并没有解决问题。

BTW我喜欢你的样品。

答案 1 :(得分:0)

可能是热门测试。您可以尝试在画布上将IsHitTestVisible设置为false。