首页 文章

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

提问于
浏览
2

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

  • 通过连接点绘制箭头图 . 然后不断改变x,y坐标 .

  • 制作箭头图像,然后不断改变其位置 .

问题是闪烁 . 每当我移动箭头图像(或重绘点)附近的图像(实际上很少有其他图像作为条形图)闪烁 . 我试图调用invalidate(rect),认为它只会重绘给定的矩形,但是一旦箭头图像越过这些条形图,一切都会闪烁 . 这看起来不太好 . 如何以平滑的方式移动此箭头图像 . PLS . 建议 . 或者我应该采用另一种方法?

//代码:**

public partial class Form1:Form {private Bitmap 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 回答

  • 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>
    
  • 0

    我在这里假设WinForms:

    你尝试过使用double buffering吗?

    你可以尝试implement your own double buffering .

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

  • 1

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

  • 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方法中的箭头坐标时,系统将不会执行任何绘制 .

相关问题