【问题标题】:Drawing stars in Image-Box在 Image-Box 中绘制星星
【发布时间】:2016-08-22 10:58:01
【问题描述】:

我想做一个小测试,如何在 WPF-C#-Application 中将“星星”绘制到名为 image1 的 Imagebox 中。有一个计时器,当它经过时调用函数来创建和绘制星集。整个方法可能有点谦虚,因为我的数学真的很差,所以对于数学更好的人来说可能有点深奥。问题是当我创建一个新的星集时,新星的新坐标,它完美地打印出一个新的图像。 (注释掉 DrawTimer_Elapsed 中的 !starList.Any() 子句和 updateStars() 调用 - 所以只保留 createStarSet() ),但是当 updateStars 执行时,星星的 X 和 Y 值似乎增加了(因为它们应该和与他们一起,我希望绘图点)但图片保持不变,即使它应该由 draw() 更新。希望它至少有点难以理解

已经谢谢了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Diagnostics;
using System.Windows.Media;
using System.Drawing;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DrawTimer.Interval = 100;
            DrawTimer.Elapsed += new System.Timers.ElapsedEventHandler(this.DrawTimer_Elapsed);
            DrawTimer.Enabled = true;
        }

        public System.Timers.Timer DrawTimer = new System.Timers.Timer();
        public Random rndGen = new Random();
        public bool drawable = true;

        public void DrawTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {          
            DrawTimer.Stop();
        if (!starList.Any())
        {
            image1.Dispatcher.Invoke(new Action(() => this.createStarSet()), System.Windows.Threading.DispatcherPriority.Background);
        }
        else
        {
            image1.Dispatcher.Invoke(new Action(() => this.updateStars()), System.Windows.Threading.DispatcherPriority.Background);
        }
            image1.Dispatcher.Invoke(new Action(() => this.draw()), System.Windows.Threading.DispatcherPriority.Background); 
            DrawTimer.Start();
        }

        public void updateStars()
        {
            foreach (Star myStar in starList)
            {
                myStar._X += 1;
                myStar._Y += 1;
            }
        }

        private void canvas1_Loaded(object sender, RoutedEventArgs e)
        {
            DrawTimer.Enabled = true;
        }

        public List<Star> starList = new List<Star>();

        public const int MAX_STARS = 100;

        public void draw() 
        {
            drawable = false;
            GeometryGroup allMyStars = new GeometryGroup();
            foreach (Star myStar in starList)
            {
                allMyStars.Children.Add(new EllipseGeometry(new Point(myStar._X, myStar._Y), 2, 2));
            }
            GeometryDrawing drawing = new GeometryDrawing();
            drawing.Geometry = allMyStars;
            drawing.Pen = new Pen(Brushes.Black, 2);
            DrawingImage finishedImage = new DrawingImage();
            finishedImage.Drawing = drawing;
            image1.Source = finishedImage;
            image1.Stretch = Stretch.None;
            drawable = true;
        }

        public void createStarSet()
        {
            starList = new List<Star>();
            for (int i = 0; i < MAX_STARS; i++)
            {
                starList.Add(new Star(rndGen,this));
            }
        }

        public class Star 
        {
            public int _X = 0;
            public int _Y = 0;
            public double _Speed = 0.0f;
            public Star(Random rndGen, Window wdw)
            {
                _X = rndGen.Next(-(int)Math.Floor((wdw.Width / 8)), (int)Math.Floor((wdw.Width / 8)));
                _Y = rndGen.Next(-(int)Math.Floor((wdw.Height / 8)), (int)Math.Floor((wdw.Height / 8)));
                _Speed = rndGen.Next(1, 100) / 100;
            }
        }
    }
}

XAML

<Window x:Name="asca" x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="399.875" Width="806" MouseMove="asca_MouseMove">
    <Image x:Name="image1" Margin="0"/>
</Window>

【问题讨论】:

  • 我们可以看看你的 XAML 代码吗?
  • 哦,是的,我现在就附上它!

标签: c# .net wpf image drawing


【解决方案1】:

好的..这个是一个棘手的问题,我已经花了大约一个小时。您的代码的问题是您一直在以相同的步骤移动所有星星,因此它们之间的“相对位置”是相同的。我从未使用过GeometryGroupGeometryDrawing,但它似乎会自动调整图像大小并将其全部居中,所以这就是为什么在你看来没有任何东西在移动。

我认为您有一些选择。一种是绘制你自己的位图,在那里你可以为你的星星设置绝对位置(我认为这样就可以了)。其他人可能正在使用 wpf 动画。

无论如何,如果您为每颗星指定不同的方向,您的代码就可以工作,从而改变它们之间的相对位置,例如:

明星班

public class Star 
    {
        public int _X = 0;
        public int _Y = 0;
        public double _Speed = 0.0f;
        public int _Direction;

        public Star(int x, int y, double speed)
        {
            _X = x;
            _Y = y;
            _Speed = speed;
        }

        public Star(Random rndGen, Window wdw)
        {
            _X = rndGen.Next(-(int)Math.Floor((wdw.Width / 8)), (int)Math.Floor((wdw.Width / 8)));
            _Y = rndGen.Next(-(int)Math.Floor((wdw.Height / 8)), (int)Math.Floor((wdw.Height / 8)));
            _Speed = rndGen.Next(1, 100) / 100;
            _Direction = rndGen.Next(0, 4);
        }
    }

UpdateStars 方法

public void updateStars()
    {

        foreach (Star myStar in starList)
        {

            switch (myStar._Direction)
            {
                case 1:
                    myStar._X += 1;
                    break;
                case 2:
                    myStar._Y += 1;
                    break;
                case 3:
                    myStar._X -= 1;
                    break;
                case 4:
                    myStar._Y -= 1;
                    break;
            }

        }

    }

您可以通过这种方式看到真正的“星星”在移动。希望这会有所帮助

【讨论】:

  • 这确实很有帮助 :) 有道理,我没有深入了解 GeometryDrawing 内部的工作原理。我试图找出一个解决方案并将其也放在这里。感谢您的意见。
猜你喜欢
  • 1970-01-01
  • 2017-04-04
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多