c# - 让 Graphic 最初显示出来

标签 c# winforms graphics paint picturebox

我正在尝试开发一个“PictureBox”,它显示一个小圆圈“围绕”一个大圆圈。关键方面是这个小圆圈的位置(以及因此的整体图片)可以根据我每秒进行的半昂贵的硬件调用而改变。我正在用“AngleValueTextBox”调用来进行说明。

研究了有关该主题的几篇文章,这似乎是执行此操作的正确方法:

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();

    AngleValueTextBox_TextChanged(null, null); // Why doesn't this make the box appear on program start?
    PictureBox.Invalidate();  // Or this?
  }

  public class CircleCenterClass { public double X; public double Y; 
    public CircleCenterClass(double X, double Y) { this.X = X; this.Y = Y; }
  }

  CircleCenterClass GetCenterOfOrbitCircle(CircleCenterClass OrbitCenter, double OrbitRadius, double Angle)
  {
    CircleCenterClass Result = new CircleCenterClass(0, 0);
    Result.X = OrbitCenter.X + OrbitRadius * Math.Sin(Angle * (3.141592654 / 180));
    Result.Y = OrbitCenter.Y - OrbitRadius * Math.Cos(Angle * (3.141592654 / 180));
    return Result;
  }

  private void drawPictureBox(Graphics graphics, bool ownGraphics)
  {
    double Angle= 0; 
    // Normally this is an expensive hardware call which I don't want to make more than 
    // once a second.
    try {
      Double.TryParse(AngleValueTextBox.Text, out Angle);
    } catch (Exception e) {
      MessageBox.Show("Could not parse Angle " + 
                       AngleValueTextBox.Text);
    }

    using (Bitmap bitmap = new Bitmap(PictureBox.Width, PictureBox.Height))
    {
      using (Graphics gx = Graphics.FromImage(bitmap))
      {
        double OrbitedCircleRadius = 40;
        CircleCenterClass OrbitedCircleCenter = new CircleCenterClass(60, 60);
        double OrbitingCircleRadius = 7;
        Pen MyRedPen = new Pen(Color.Red, 2f);
        Brush MyBlackBrush = new SolidBrush(Color.Black);

        gx.DrawEllipse(MyRedPen, (Int32)(OrbitedCircleCenter.X - OrbitedCircleRadius),
                                        (Int32)(OrbitedCircleCenter.Y - OrbitedCircleRadius),
                                        (Int32)(2 * OrbitedCircleRadius),
                                        (Int32)(2 * OrbitedCircleRadius));

        CircleCenterClass CircleCenter = GetCenterOfOrbitCircle(
                            OrbitedCircleCenter, OrbitedCircleRadius,
                            Angle);

        gx.FillEllipse(MyBlackBrush, (Int32)(CircleCenter.X - OrbitingCircleRadius),
                                     (Int32)(CircleCenter.Y - OrbitingCircleRadius),
                                     (Int32)(2 * OrbitingCircleRadius),
                                     (Int32)(2 * OrbitingCircleRadius));

        // Draw Electronics box. 
        Graphics g = PictureBox.CreateGraphics();
        g.Clear(BackColor);
        g.DrawImage(bitmap, 0, 0);  
      }
    }
  }

  private void PictureBox_Paint(object sender, PaintEventArgs e)
  {
    drawPictureBox(e.Graphics,false);
  }

  private void AngleValueTextBox_TextChanged(object sender, EventArgs e)
  {
    drawPictureBox(PictureBox.CreateGraphics(), true);
  }
}

关键问题:

  1. 我一开始无法显示图片(即当 GUI 启动时)。我已经尝试将事件添加到我的 Form 构造函数(如您所见)但没有成功。什么是“正确”的方式?

  2. 有没有更好的方法来绘制不断变化的图形?

最佳答案

用名为 PictureBox 的 Panel 替换 PictureBox 控件

或者将图片框的Image属性设置为创建的位图

请注意,这不是一种特别有效的方法。

如果图像仅每秒更新一次,那么您也许可以仅在值更改时才绘制图像,将位图保留为窗体上的私有(private)属性,并且仅在绘制中复制位图(就像您所做的那样,但采取出所有绘图代码,仅在值发生变化时执行)

enter image description here

    Bitmap bitmap;
    public Form1()
    {
        InitializeComponent();
        bitmap = new Bitmap(PictureBox.Width, PictureBox.Height);
        AngleValueTextBox_TextChanged(null, null); // Why doesn't this make the box appear on program start?
        PictureBox.Invalidate();  // Or this?
    }

    public class CircleCenterClass
    {
        public double X; public double Y;
        public CircleCenterClass(double X, double Y) { this.X = X; this.Y = Y; }
    }

    CircleCenterClass GetCenterOfOrbitCircle(CircleCenterClass OrbitCenter, double OrbitRadius, double Angle)
    {
        CircleCenterClass Result = new CircleCenterClass(0, 0);
        Result.X = OrbitCenter.X + OrbitRadius * Math.Sin(Angle * (3.141592654 / 180));
        Result.Y = OrbitCenter.Y - OrbitRadius * Math.Cos(Angle * (3.141592654 / 180));
        return Result;
    }

    private void drawPictureBox(Graphics graphics, bool ownGraphics)
    {



    }

    private void DrawImage()
    {
        double Angle = 0;
        // Normally this is an expensive hardware call which I don't want to make more than 
        // once a second.
        try
        {
            Double.TryParse(AngleValueTextBox.Text, out Angle);
        }
        catch (Exception e)
        {
            MessageBox.Show("Could not parse Angle " +
                             AngleValueTextBox.Text);
        }

        using (Graphics gx = Graphics.FromImage(bitmap))
        {
            gx.Clear(BackColor);
            double OrbitedCircleRadius = 40;
            CircleCenterClass OrbitedCircleCenter = new CircleCenterClass(60, 60);
            double OrbitingCircleRadius = 7;
            Pen MyRedPen = new Pen(Color.Red, 2f);
            Brush MyBlackBrush = new SolidBrush(Color.Black);

            gx.DrawEllipse(MyRedPen, (Int32)(OrbitedCircleCenter.X - OrbitedCircleRadius),
                                            (Int32)(OrbitedCircleCenter.Y - OrbitedCircleRadius),
                                            (Int32)(2 * OrbitedCircleRadius),
                                            (Int32)(2 * OrbitedCircleRadius));

            CircleCenterClass CircleCenter = GetCenterOfOrbitCircle(
                                OrbitedCircleCenter, OrbitedCircleRadius,
                                Angle);

            gx.FillEllipse(MyBlackBrush, (Int32)(CircleCenter.X - OrbitingCircleRadius),
                                         (Int32)(CircleCenter.Y - OrbitingCircleRadius),
                                         (Int32)(2 * OrbitingCircleRadius),
                                         (Int32)(2 * OrbitingCircleRadius));
        }
    }

    private void PictureBox_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImage(bitmap, 0, 0);
    }

    private void AngleValueTextBox_TextChanged(object sender, EventArgs e)
    {
        DrawImage();
        PictureBox.Invalidate();
    }

关于c# - 让 Graphic 最初显示出来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15927862/

相关文章:

c# - Mono 是否足够稳定和快速?

c# - 从二进制文件中的结构中解析内容

c# - 静态存储库 - 解决方法

c# - 如何在运行时查找窗体中的所有控件

.net - 如何设置任务栏分组图标

c# - C# 中可调整大小的表格布局面板

c# - 来自 MemoryStream 的电子邮件附件为空

r - 如何根据绘图/图形/设备区域的坐标从 0 到 1 放置文本?

python - Surface.scroll() 是在 Pygame 中实现可移动 2D 视点的正确方法吗?

c# - 通过 C# 图形绘制 "transparent"文本,但以某种方式将绘制的文本变为 "missing",因此它在生成的图像中是透明的