Как я могу использовать DrawLine много раз в c # Windows Form?

#c# #winforms #graphics

#c# #winforms #графика

Вопрос:

У меня есть задача: построить фигуру из пары строк и сделать к ней аффинные преобразования. Также мне нужно выполнить эти преобразования самостоятельно: вычислить новые координаты и переместить фигуру с помощью преобразования матрицы. Но у меня ошибка «недопустимый параметр», когда я пытаюсь вызвать свой метод DrawLine. Вы можете мне помочь?

Матричный класс

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Smile
{
    class Matrix
    {
        double[,] matrix;
        public Matrix(double[,] matrix)
        {
            this.matrix = matrix;
        }

        public int cols
        {
            get
            {
                return this.matrix.GetUpperBound(1)   1;
            }
        }

        public int rows
        {
            get
            {
                return this.matrix.Length / this.cols;
            }
        }

        public double getElement(int row, int col)
        {
            return this.matrix[row, col];
        }
    }
}
  

Класс Arrow(это фигура, которую я построил из строк), где у меня проблема с Drawar Row(), затем пытаюсь перевести стрелку в новые координаты.

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace Smile
{
    class Arrow
    {
        Pen p = new Pen(Color.Blue, 5);// цвет линии и ширина
        //Graphics graphics;
        Matrix affine, dots;
        public Arrow(Graphics graphics)
        {
            //this.graphics = graphics;
            this.DrawArrow(5, 10, 40, 100, 40, 60, 10, 70, graphics);
        }

        private void DrawArrow(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, Graphics graphics)
        {
            graphics.DrawLine(this.p, new Point(x1, y1), new Point(x2, y2));
            graphics.DrawLine(this.p, new Point(x2, y2), new Point(x3, y3));
            graphics.DrawLine(this.p, new Point(x2, y2), new Point(x4, y4));
            initializeDotMatrix(x1, y1, x2, y2, x3, y3, x4, y4);
        }

        public void createAffine(double a, double b, double c, double d)
        {
            double[,] affine = { { a, b }, { c, d } };
            this.affine = new Matrix(affine);
        }

        private void initializeDotMatrix(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
        {
            double[,] dots = { { x1, y1 }, { x2, y2 }, { x3, y3 }, { x4, y4 } };
            this.dots = new Matrix(dots);
        }
        private void reInitializeLines(int[,] coordinates, Graphics graphics)
        {
            DrawArrow(coordinates[0, 0],
                coordinates[0, 1],
                coordinates[1, 0],
                coordinates[1, 1],
                coordinates[2, 0],
                coordinates[2, 1],
                coordinates[3, 0],
                coordinates[3, 1], graphics);
        }

        public void moveRight(int step, Graphics graphics)
        {
            createAffine(1, step, 0, 1);
            reInitializeLines(this.multiply(), graphics);
        }

        public int[,] multiply()
        {
            int[,] result = new int[dots.rows, affine.cols];

            for (int resultRow = 0; resultRow < dots.rows; resultRow  )
            {
                for (int resultCol = 0; resultCol < affine.cols; resultCol  )
                {
                    double value = 0;

                    for (int i = 0; i < affine.cols; i  )
                    {
                        value  = dots.getElement(resultRow, i) * affine.getElement(i, resultCol);
                    }
                    result[resultRow, resultCol] = Convert.ToInt32(value);
                }
            }

            return resu<
        }
    }
}
  

Класс формы

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Smile
{
    public partial class Form1 : Form
    {

        Arrow arrow;
        Graphics gr;
        bool changed = true;
        bool isExist = false;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
        
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            this.gr = e.Graphics;
            arrow = new Arrow(gr);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (!isExist)
            {
                isExist = false;
                this.gr = e.Graphics;
                arrow = new Arrow(gr);
            }

            /*if (changed)
            {
                changed = false;
                //gr.Invalidate();
                gr.Clear(Color.White);
                base.OnPaint(e);
                
            }*/
            
        }

        private void Right_Click(object sender, EventArgs e)
        {
            changed = true;
            arrow.moveRight(200, gr);
        }
    }
}

  

Комментарии:

1. Первое, что вам нужно удалить, это это поле : Graphics gr; . Right_Click() предполагается Invalidate() , что холст (ваша форма, здесь) рисует движение. Решите, хотите ли вы переопределить OnPaint событие или подписаться на Paint него (выберите одно). Затем передайте new Arrow(e.Graphics); . isExist всегда false , по крайней мере, из того, что вы здесь показываете: это подразумевает, что…

2. Код выглядит немного запутанным. Обратите внимание, что вы не должны пытаться кэшировать графический объект. Что отладчик сообщает вам о каждом из элементов в вызовах DrawLine??

3. Вы должны использовать индексатор вместо getElement метода

4. @Jimi Я новичок, не могли бы вы рассказать мне, как проверить OnPaint или подписаться на Paint. Если вы можете использовать мой код в качестве примера

Ответ №1:

Я нашел ответ. Посмотрите на мой новый код. Код формы

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Smile
{
    public partial class Form1 : Form
    {

        Arrow arrow;
        Graphics gr;
        public Form1()
        {
            InitializeComponent();
            gr = pictureBox1.CreateGraphics();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(Color.White);
            arrow = new Arrow(e.Graphics);
        }
        private void Right_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);   
            arrow.moveX(100,gr);
        }

        private void Left_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.moveX(-100, gr);
        }

        private void Up_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.moveY(-100, gr);
        }

        private void Down_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.moveY(100, gr);
        }

        private void ScaleX_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.scaleX(2, gr);
        }

        private void ScaleY_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.scaleY(2, gr);
        }

        private void Rotate_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.rotate(1,gr);
        }

        private void ReflectX_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.reflectX(1, gr);
        }

        private void ReflectY_Click(object sender, EventArgs e)
        {
            gr.Clear(Color.White);
            arrow.reflectY(1, gr);
        }
    }
}
  

Код матричного класса (необязательно)

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Smile
{
    class Matrix
    {
        double[,] matrix;
        public Matrix(double[,] matrix)
        {
            this.matrix = matrix;
        }

        public int cols
        {
            get
            {
                return this.matrix.GetUpperBound(1)   1;
            }
        }

        public int rows
        {
            get
            {
                return this.matrix.Length / this.cols;
            }
        }

        public double getElement(int row, int col)
        {
            return this.matrix[row, col];
        }
    }
}
  

Класс стрелки

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace Smile
{
    class Arrow
    {
        Pen p = new Pen(Color.Blue, 5);
        Matrix affine, dots;
        public Arrow(Graphics graphics)
        {
            this.DrawArrow(755, 60, 790, 150, 790, 110, 760, 120, graphics);
        }

        private void DrawArrow(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, Graphics graphics)
        {
            graphics.DrawLine(this.p, new Point(x1, y1), new Point(x2, y2));
            graphics.DrawLine(this.p, new Point(x2, y2), new Point(x3, y3));
            graphics.DrawLine(this.p, new Point(x2, y2), new Point(x4, y4));
            initializeDotMatrix(x1, y1, x2, y2, x3, y3, x4, y4);
        }

        public void createAffine(double a, double b, double b1, double c, double d, double d1, double e0, double e1, double e2)
        {
            double[,] affine = { { a, b, b1 }, { c, d, d1 }, { e0, e1, e2 } };
            this.affine = new Matrix(affine);
        }

        private void initializeDotMatrix(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
        {
            double[,] dots = { { x1, y1, 1 }, { x2, y2, 1 }, { x3, y3, 1 }, { x4, y4, 1 } };
            this.dots = new Matrix(dots);
        }
        private void reInitializeLines(int[,] coordinates, Graphics graphics)
        {
            DrawArrow(coordinates[0, 0],
                coordinates[0, 1],
                coordinates[1, 0],
                coordinates[1, 1],
                coordinates[2, 0],
                coordinates[2, 1],
                coordinates[3, 0],
                coordinates[3, 1], graphics);
        }

        public void scaleX(int step, Graphics graphics)
        {
            createAffine(step, 0, 0, 0, 1, 0, 0, 0, 1);
            reInitializeLines(this.multiply(), graphics);
        }

        public void scaleY(int step, Graphics graphics)
        {
            createAffine(1, 0, 0, 0, step, 0, 0, 0, 1);
            reInitializeLines(this.multiply(), graphics);
        }

        public void scaleXY(int step, Graphics graphics)
        {
            createAffine(step, 0, 0, 0, step, 0, 0, 0, 0);
            reInitializeLines(this.multiply(), graphics);
        }

        public void moveX(int step, Graphics graphics)
        {
            createAffine(1, 0, 0, 0, 1, 0, step, 0, 1);
            reInitializeLines(this.multiply(), graphics);
        }

        public void moveY(int step, Graphics graphics)
        {
            createAffine(1, 0, 0, 0, 1, 0, 0, step, 1);
            reInitializeLines(this.multiply(), graphics);
        }

        public void rotate(double step, Graphics graphics)
        {
            createAffine(Math.Cos(step), Math.Sin(step), 0, -Math.Sin(step), Math.Cos(step), 0, 0, 0, 1);
            reInitializeLines(this.multiply(), graphics);
        }

        public void reflectY(int step, Graphics graphics)
        {
            createAffine(step, 0, 0, 0, -step, 0, 0, 0, 1);
            reInitializeLines(this.multiply(), graphics);

            createAffine(1, 0, 0, 0, 1, 0, 0, 500, 1);
            reInitializeLines(this.multiply(), graphics);
        }
        public void reflectX(int step, Graphics graphics)
        {
            createAffine(-step, 0, 0, 0, step, 0, 0, 0, 1);
            reInitializeLines(this.multiply(), graphics);

            createAffine(1, 0, 0, 0, 1, 0, 1000, 0, 1);
            reInitializeLines(this.multiply(), graphics);
        }
        public int[,] multiply()
        {
            int[,] result = new int[dots.rows, affine.cols];

            for (int resultRow = 0; resultRow < dots.rows; resultRow  )
            {
                for (int resultCol = 0; resultCol < affine.cols; resultCol  )
                {
                    double value = 0;

                    for (int i = 0; i < affine.cols; i  )
                    {
                        value  = dots.getElement(resultRow, i) * affine.getElement(i, resultCol);
                    }
                    result[resultRow, resultCol] = Convert.ToInt32(value);
                }
            }

            return resu<
        }
    }
}
  

Итак, моя проблема заключалась в использовании графики из PaintEventArg. Но я могу получить те же параметры из PictureBox.Создайте graphics(), а затем перерисуйте по своему усмотрению) Удачи всем исследователям! Я хочу помочь другим в решении моей проблемы.