如何使用抽象工厂设计模式在c#中打开子窗口并绘制/绘制形状?

如何使用抽象工厂设计模式在c#中打开子窗口并绘制/绘制形状?,c#,winforms,graphics,C#,Winforms,Graphics,我正在用c#开发一个简单的命令行图形应用程序。 和上面一样,在单击debug/run或在下面的窗口中键入run之后,程序会逐行检查预定义的语法 private void execute() { Output outputWindow = new Output(); //object of output window compiler = new Compiler(outputWindow);

我正在用c#开发一个简单的命令行图形应用程序。 和上面一样,在单击debug/run或在下面的窗口中键入run之后,程序会逐行检查预定义的语法

        private void execute()
            {
                Output outputWindow = new Output(); //object of output window 
                compiler = new Compiler(outputWindow); //sending object of output window to compiler
                //get all text and save in lines string array
                string output = "";
                string[] lines = GetActiveEditor().Lines;
                lines = lines.Where(x => !string.IsNullOrEmpty(x)).ToArray();
                if (lines == null || lines.Length == 0)
                {
                    consoleBox.Text += "\n Error: Compiling Failed. Empty File.";
                }
                else
                {
                    foreach (var line in lines)
                    {
                        output = compiler.Compile(line);
                        consoleBox.Text += "\n" + output;
                        if (output.Contains("Error"))
                        {
                        break;
                        }
                    }

                }


            }

            private void ToolBtnDebug_Click(object sender, EventArgs e)
            {
                consoleBox.Clear();
                consoleBox.Text = " \n CPaint Compiler:- Compiling Started... \n";
                execute();
            }

    // In Compiler 

        string[] commands = { "clear", "reset", "rectangle", "circle", "triangle", "position pen", "pen draw" };
        Public string Line { get; set; }
        Public Output outputWindow;

        public Compiler(Output form)
            {
                outputWindow = form;
            }

        //checks syntax
        public bool IsSyntax(string syntax)
            {
                bool result = false;
                if (Array.Exists(commands, element => element == syntax.ToLower().Trim()))
                {
                    result = true;
                }
                return result;
            }

    //Compile class 
    public string Compile(string line)
            {
                string output = "";
                //splitting the line by comma"," and small brackets "()" and assigning into an string a`enter code here`rray
                string[] code = line.Split(',', '(', ')');
                //removing extra spaces 
                code = code.Where(x => !string.IsNullOrEmpty(x)).ToArray();
    bool checkSyntax = IsSyntax(code[0]);
                if (checkSyntax == true)
                {
                  if (code[0].Trim().ToLower().Equals("circle"))
                    {
                        try
                        {
                                int parameter1 = Int32.Parse(code[1]);
                                int parameter2 = Int32.Parse(code[2]);
                                //string shapeType = "circle";

                                ShapeFactory shapeFactory = new ShapeFactory();
                                Circle circle = shapeFactory.GetShape("circle").Shape as Circle;
                                circle.Draw(12, 12);
                                output = "command executed successfully: parameter is" + parameter1;
                                //      output = "is numeric ";
                            }

                        }
                        catch (Exception ex)
                        {

                            Console.WriteLine("Exception Message: " + ex.Message);
                            output = "\n Parameter Error : Invalid/Insufficient Parameter. \n";
                        }

                    }
成型工厂法:

class ShapeFactory:AbstractFactory
{
    public override FactoryShape GetShape(string shapeType)
    {
        FactoryShape factoryShape = null;
        if (shapeType.Equals("circle"))
        {
            factoryShape = new FactoryShape(new Circle());
        }

        return factoryShape;
    }
}
        //Circle Method Code: 
            namespace CPaint.Class
            {
            class Circle
            {
                Graphics graphics;
                public void Draw(float initX, float initY)
                {
                    Output outputWindow=new Output();
                    Graphics graphics=outputWindow.outputArea.CreateGraphics();
                    outputWindow.outputArea.Image=Color.Red;
                    Pen pen = new Pen(Color.Black, 4);
                    SolidBrush brush = new SolidBrush(Color.Black);
                    graphics.FillEllipse(brush, 12, 12, 12, 12);
                    graphics.DrawEllipse(pen, 12, 12, 12, 12);
                    Console.WriteLine("ok drawing circle for you" + initX + "   " + initY);
output.show();
                }
            }
            }
这段代码打开两个读空输出窗口,它应该在同一个输出窗口中画两个圆。
请帮帮我,我从三天起就被困在这里了。提前感谢。

首先,我们需要改进您的设计

  • 工厂模式只有在您编写抽象代码时才有意义,这意味着工厂应该创建具体类型,但您不应该知道具体类型,而应该只知道抽象类型。在您的设计中并非如此。您说您使用的是抽象工厂模式,但您将创建的对象转换为圆形,即“编码到实现”

  • 编译器将行编译为形状,并执行它们。编译器只应将文本(代码)转换为可执行对象,而不应执行它们。不幸的是,在当前的设计中,无法将创建的形状传递到输出表单并绘制它们

  • 您需要将所有已编译的形状传递到输出表单中,并且应该在运行时正在重新绘制控件(表单)表面的OnPaint override中进行绘制

  • 抽象(形状):

    以及具体类型:

    public class Circle : Shape
    {
        public float Radius { get; set; }
    
        public override void Draw(System.Drawing.Graphics surface)
        {
            surface.DrawEllipse(Pens.Black, 0, 0, Radius, Radius);
        }
    }
    
    public class Rectangle : Shape
    {
        public float Width { get; set; }
        public float Height { get; set; }
    
        public override void Draw(System.Drawing.Graphics surface)
        {
            surface.DrawRectangle(Pens.Black, 0, 0, Width, Height);
        }
    }
    
    下面是我的实现中的ShapeFactory

    public class ShapeFactory
    {
        public static Shape CreateShape(string shapeName, params string[] parameters)
        {
            switch (shapeName)
            {
                case "circle":
                    return new Circle() { Radius = Convert.ToSingle(parameters[0]) };
                case "rectangle":
                    return new Rectangle { Width = Convert.ToSingle(parameters[0]), Height = Convert.ToSingle(parameters[1]) };
                default:
                    throw new NotSupportedException("shapeName");
            }
        }
    }
    
    编译器:

    public Shape Compile(string line)
    {
        string[] code = line.Split(new char[] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
        if (IsSyntax(code[0]))
        {
            try
            {
                return ShapeFactory.CreateShape(code[0], code.Skip(1).ToArray());
            }
            catch (Exception shapeCreationException)
            {
                // Exception handling here.
                // . . .
            }
        }
        else
        {
            // Syntax Error handling here
            // . . .
        }
        return null;
    }
    
    最后是输出形式:

    public partial class Output : Form
    {
        public List<Shape> Shapes { get; set; }
    
        public Output()
        {
            Shapes = new List<Shape>();
            InitializeComponent();
        }
    
        protected override void OnPaint(PaintEventArgs e)
        {
            foreach (Shape shapeToDraw in Shapes)
            {
                shapeToDraw.Draw(e.Graphics);
            }
        }
    }
    
    这是测试和工作


    如果您不理解某些内容或无法完成此工作,请发表评论,但不幸的是,您的案例由于其设计缺陷而没有简单的修复。

    首先,我们需要改进您的设计

  • 工厂模式只有在您编写抽象代码时才有意义,这意味着工厂应该创建具体类型,但您不应该知道具体类型,而应该只知道抽象类型。在您的设计中并非如此。您说您使用的是抽象工厂模式,但您将创建的对象转换为圆形,即“编码到实现”

  • 编译器将行编译为形状,并执行它们。编译器只应将文本(代码)转换为可执行对象,而不应执行它们。不幸的是,在当前的设计中,无法将创建的形状传递到输出表单并绘制它们

  • 您需要将所有已编译的形状传递到输出表单中,并且应该在运行时正在重新绘制控件(表单)表面的OnPaint override中进行绘制

  • 抽象(形状):

    以及具体类型:

    public class Circle : Shape
    {
        public float Radius { get; set; }
    
        public override void Draw(System.Drawing.Graphics surface)
        {
            surface.DrawEllipse(Pens.Black, 0, 0, Radius, Radius);
        }
    }
    
    public class Rectangle : Shape
    {
        public float Width { get; set; }
        public float Height { get; set; }
    
        public override void Draw(System.Drawing.Graphics surface)
        {
            surface.DrawRectangle(Pens.Black, 0, 0, Width, Height);
        }
    }
    
    下面是我的实现中的ShapeFactory

    public class ShapeFactory
    {
        public static Shape CreateShape(string shapeName, params string[] parameters)
        {
            switch (shapeName)
            {
                case "circle":
                    return new Circle() { Radius = Convert.ToSingle(parameters[0]) };
                case "rectangle":
                    return new Rectangle { Width = Convert.ToSingle(parameters[0]), Height = Convert.ToSingle(parameters[1]) };
                default:
                    throw new NotSupportedException("shapeName");
            }
        }
    }
    
    编译器:

    public Shape Compile(string line)
    {
        string[] code = line.Split(new char[] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
        if (IsSyntax(code[0]))
        {
            try
            {
                return ShapeFactory.CreateShape(code[0], code.Skip(1).ToArray());
            }
            catch (Exception shapeCreationException)
            {
                // Exception handling here.
                // . . .
            }
        }
        else
        {
            // Syntax Error handling here
            // . . .
        }
        return null;
    }
    
    最后是输出形式:

    public partial class Output : Form
    {
        public List<Shape> Shapes { get; set; }
    
        public Output()
        {
            Shapes = new List<Shape>();
            InitializeComponent();
        }
    
        protected override void OnPaint(PaintEventArgs e)
        {
            foreach (Shape shapeToDraw in Shapes)
            {
                shapeToDraw.Draw(e.Graphics);
            }
        }
    }
    
    这是测试和工作


    如果您不了解某些内容或无法完成此项工作,请发表评论,但不幸的是,您的案例由于其设计缺陷而没有简单的修复。

    在控件表面绘制的常用方法是获取其
    图形
    对象并绘制到其中<代码>output.outputArea.CreateGraphics().drawerlipse(笔,12,12,12,12)请不要忘记处理对象。请在using()块中使用它。我也这样做了,但我也不能画画<代码>output.outputrea.BackColor=Color.Red这可以工作,但是
    output.outputArea.CreateGraphics().drawerlipse(笔,12,12,12)这不是。我用两个表单做了一个非常小的应用程序。我展示了输出表单,并使用Output.CreateGraphics().Dropellipse()在其上进行了绘制,它成功了。我想你需要的是别的东西。你能分享一下你创建输出表单的代码吗?如果需要传递新输出表单的图形对象,只需使用output.CreateGraphics()获取它,并将其传递给形状,以便它可以使用此图形对象进行绘制。将
    Graphics Graphics
    参数添加到
    draw
    方法,并传递
    output.CreateGraphics()的返回值
    @Oguz-Ozgul:在控件表面绘制的常用方法是获取其图形对象并绘制到其中。嗯,如果你想让你的输出持续下去,那就不要了您需要使用绘制事件及其e.Graphics参数。在控件的曲面上绘制的通常方法是获取其
    图形
    对象并绘制到其中<代码>output.outputArea.CreateGraphics().drawerlipse(笔,12,12,12,12)请不要忘记处理对象。请在using()块中使用它。我也这样做了,但我也不能画画<代码>output.outputrea.BackColor=Color.Red
    这可以工作,但是
    output.outputArea.CreateGraphics().drawerlipse(笔,12,12,12)这不是。我用两个表单做了一个非常小的应用程序。我展示了输出表单,并使用Output.CreateGraphics().Dropellipse()在其上进行了绘制,它成功了。我想你需要的是别的东西。你能分享一下你创建输出表单的代码吗?如果需要传递新输出表单的图形对象,只需使用output.CreateGraphics()获取它,并将其传递给形状,以便它可以使用此图形对象进行绘制。将
    Graphics Graphics
    参数添加到
    draw
    方法,并传递
    output.CreateGraphics()的返回值
    @Oguz-Ozgul:在控件表面绘制的常用方法是获取其图形对象并绘制到其中。嗯,如果你想让你的输出持续下去,那就不要了您需要使用Paint事件及其e.Graphics参数。我尝试了相同的代码,但它也不会绘制圆形和矩形。在我的系统上,它会绘制圆形和矩形,在您的系统上,如果您正确实现它,它应该会绘制圆形和矩形。你能把你的全部源代码上传到某个地方吗?我已经上传到谷歌硬盘了。在这里,图像输出区域完全覆盖了表单表面(Dock=Fill)。代码当前直接绘制在表单上。做