如何在C#中绘制移动箭头图像

时间:2011-07-04 09:19:03

标签: c# winforms visual-studio-2008

我必须在2条(图像)之间绘制一个移动的箭头图像(使用C#代码VS2008)。我尝试了两种方法:

  1. 通过加入点绘制箭头图。然后不断改变x,y坐标。
  2. 制作箭头图像,然后不断改变其位置。
  3. 问题在于闪烁。每当我移动箭头图像(或重绘点)附近的图像(实际上很少有其他图像作为条形图)闪烁。我试着调用invalidate(rect),认为它只会重绘给定的矩形,但是一旦箭头图像越过这些条,一切都会闪烁。这看起来不太好。如何以平滑的方式移动此箭头图像。 PLS。建议。或者我应该采用另一种方法?

    //代码:**

    公共部分类Form1:表单 {     私有位图bitmapAntenna;     private Bitmap bitmapArrow;

    public Form1()
    {
        bitmapAntenna = new Bitmap("D:\\AntennaBar.JPG");
        bitmapArrow = new Bitmap("D:\\Arrow.JPG");
    }
    
    private void DrawAntennaImages(int antennaNo)
    {
        Graphics grph = this.CreateGraphics();
        if (1 == antennaNo)
        {
            grph.DrawImage(bitmapAntenna, new RectangleF(350, 300, bitmapAntenna.Width*(1.00F), bitmapAntenna.Height*(1.00F))) ;
        }
        else
            grph.DrawImage(AntennaImage, new Point(550, 300));
    }
    
    private void DrawArrowImages(int X)
    {
        Graphics grph = this.CreateGraphics();
        grph.DrawImage(bitmapArrow, new Point(380 + X, 350));
    }
    
    private void PaintHandler(Object sender, System.Windows.Forms.PaintEventArgs e)
    {
        DrawAntennaImages(1);
        DrawAntennaImages(2);
    }
    
    private void button_Click(object sender, EventArgs e)
    {
        for (int i = 1; i < 40; i++)
        {
            //  Note: first draw antenna 1 image, arrow image then antenna 2 image so that arrow will overlap
            //  only antenna 1 image only.
    
            DrawAntennaImages(1);       //  Draw Antenn 1 image
            DrawArrowImages(i * 2);     //  Draw Arrow image
            DrawAntennaImages(2);       //  Draw Antenn 2 image
    
            System.Threading.Thread.Sleep(25);  //  Sleep before drawing next time ..
        }
        this.Invalidate(); // If I don't call this, arrow image does not elope after last draw
    }
    

    }

    //在设计师

    this.Paint + = new System.Windows.Forms.PaintEventHandler(this.PaintHandler);

    //代码 *

    由于 RPS

4 个答案:

答案 0 :(得分:1)

我在这里假设WinForms:

您是否尝试过使用double buffering

您可以尝试implement your own double buffering

不要指望奇迹在这里; WinForms从来没有打算做过这样的事情。

答案 1 :(得分:1)

只需打开表单的双缓冲

myCanvasForm.SetStyle(
  ControlStyles.AllPaintingInWmPaint |
  ControlStyles.UserPaint |
  ControlStyles.DoubleBuffer,true);

或您使用的控件。

myCanvasControl.DoubleBuffered = true;

Here is some more information关于Windows窗体和GDI +中的双缓冲。

哦,顺便说一下:WPF中不存在这类问题。在图形质量和易用性方面(对于你正在做的简单事情),WPF远远优于Windows窗体和GDI +。

这是你如何在WPF / XAML中绘制移动的恐怖:

<Canvas>
    <Canvas.Resources>
        <Storyboard x:Key="OnLoaded1">
            <DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="blockArrow">
                <EasingDoubleKeyFrame KeyTime="0:0:6" Value="500"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Canvas.Resources>
    <ed:BlockArrow x:Name="blockArrow" Stroke="Black" Width="100" Height="50" Canvas.Left="0" Canvas.Top="200"/>
</Canvas>

答案 2 :(得分:0)

如果您PictureBox尝试设置DoubleBuffering = true。如果此闪烁仍然存在,请在屏幕上绘制Bitmap之前将所有内容绘制到Bitmap上。

答案 3 :(得分:0)

我们在WinForms中制作动画,并且不会因为我们的技术而出现任何闪烁,这是这样的:

  • 创建System.Windows.Forms.Timer对象。设置每秒25帧的间隔:timer.Interval = 1000/25;向Tick事件添加回调方法:timer.Tick += new EventHandler(animateCallback)
  • animateCallback应更新Arrow实例的坐标并调用Invalidate()以让.NET图形系统调用控件的Paint方法。

使用System.Windows.Forms.Timer类对于避免闪烁至关重要。此计时器在UI线程中运行。这意味着,您获得的回调位于UI线程中。因此,当您在animateCallback方法中更新箭头坐标时,系统不会进行任何绘图。