繁体   English   中英

在Mandelbrot Fractal上拖动鼠标时绘制一个矩形(从Java转换为C#)

[英]Drawing a rectangle while dragging the mouse on Mandelbrot Fractal ( Conversion to C# from Java )

这是我的第二篇有关从Java到C#的Mandelbrot分形转换的文章。 根据我的任务,我需要在窗体上绘制一个曼德布罗形分形,绘制后,允许用户使用鼠标放大,同时还要绘制一个从初始点击点到释放点击点的矩形。 。 我认为这是代码的一部分,它负责矩形。

private static void Swap<T>(ref T t1, ref T t2)
    {
        T temp = t1;
        t1 = t2;
        t2 = t1;
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        Graphics g1 = e.Graphics;
        g1.DrawImage(bitmap, 0, 0, x1, y1);

        if (action)
        {
            //g.setColor(Color.White);
            if (xe < xs)
            {
                Swap(ref xs, ref xe);
            }

            if (ye < ys)
            {
                Swap(ref ys, ref ye);
            }

            g1.DrawRectangle(Pens.White, xs, ys, (xe - xs), (ye - ys));
            //g1.Dispose();
        }
    }
    //load method here 
    private void Form1_Load(object sender, EventArgs e)
    //while loading
    {
        init();
        start();

    }
    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (action)
        {
            xe = e.X;
            ye = e.Y;
        }
    }

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        action = true;
        // e.consume();
        if (action)
        {
            xs = xe = e.X;
            ys = ye = e.Y;
        }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        using (Graphics g = this.CreateGraphics())
        {
            Pen pen = new Pen(Color.White);
            g.DrawRectangle(pen, xs, ys, Math.Abs(xs - xe), Math.Abs(ys - ye));

        }

        int z, w;
        if (xs > xe)
        {
            z = xs;
            xs = xe;
            xe = z;
        }
        if (ys > ye)
        {
            z = ys;
            ys = ye;
            ye = z;
        }
        w = (xe - xs);
        z = (ye - ys);
        if ((w < 2) && (z < 2)) initvalues();
        else
        {
            if (((float)w > (float)z * xy)) ye = (int)((float)ys + (float)w / xy);
            else xe = (int)((float)xs + (float)z * xy);
            xende = xstart + xzoom * (double)xe;
            yende = ystart + yzoom * (double)ye;
            xstart += xzoom * (double)xs;
            ystart += yzoom * (double)ys;
        }
        xzoom = (xende - xstart) / (double)x1;
        yzoom = (yende - ystart) / (double)y1;
        mandelbrot();

        this.Invalidate();
    }

代码的作用是,在完成拖动后绘制一个矩形,然后在仍显示绘制的矩形的情况下进行放大。 我需要的是拖动鼠标时要绘制的矩形。

我提到了这个问题,那里提到的解决方案没有帮助。 Java到C#的转换。 如何在位图上绘制矩形?

任何帮助,将不胜感激。

绘制矩形

首先,似乎Graphics.DrawRectangle方法无法绘制具有负宽度或高度的矩形。 因此,您将必须编写一种方法,该方法将获取两个点并生成一个满足要求的矩形(正宽度和高度)。

private Rectangle CreateRectangle(Point pt1, Point pt2)
{
    // we use this method to create the rectangle with positive width and height
    int x1 = Math.Min(pt1.X, pt2.X);
    int y1 = Math.Min(pt1.Y, pt2.Y);


    return new Rectangle(x1, y1, Math.Abs(pt1.X - pt2.X), Math.Abs(pt1.Y - pt2.Y));
}

其次,在MouseDown事件的事件处理程序中,记录鼠标被按下的位置。

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
        this.startPoint = e.Location;// record the start position
}

接下来,修改您的鼠标移动方法以更新保存鼠标当前位置的变量。 此外,使其无效窗体,以便重新绘制图像(以及矩形)。

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        // record the current position as the end point if the left button is down
        this.endPoint = e.Location;
        // force a redraw
        this.Invalidate();
    }
}

在窗体的Paint事件处理程序中,使您的代码使用矩形的起点和终点调用CreateRectangle方法,以便在窗体上绘制矩形。

private void Form1_Paint(object sender, PaintEventArgs e)
{
    // draw the cached Mandelbrot image
    e.Graphics.DrawImage(mandelbrotCache, new Point(0, 0));

    // draw the current rectangle
    e.Graphics.DrawRectangle(rectPen, CreateRectangle(startPoint, endPoint));
}

最后,为了在不再按下鼠标按钮时删除矩形,请将startPointendPoint设置为在图像外部绘制的值。 这应该在MouseUp事件处理程序中完成。

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.Left)
    {
        // setting the point to -1,-1 makes them get drawn off the screen
        startPoint = new Point(-1, -1);
        endPoint = new Point(-1, -1);

        // force an update so that the rectangle disappears
        this.Invalidate();
    }
}

解决闪烁的问题

为了在绘制时阻止表单闪烁,您将需要在表单上启用双重缓冲。 这是通过将表单的DoubleBuffered属性设置为true 您可以在任何地方执行此操作,但是我更喜欢在创建表单后立即执行此操作,如下所示:

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

        // this reduces the flickering
        this.DoubleBuffered = true;
    }
}

完整的代码:

这是上面我详细介绍的所有步骤的完整代码。 您可以插入您的方法,以获得有效的解决方案。

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Point startPoint;
        private Point endPoint;
        private Image mandelbrotCache;
        private Pen rectPen;

        public Form1()
        {
            InitializeComponent();

            // this reduces the flickering
            this.DoubleBuffered = true;

            // initialize a dummy image. Cache a copy of your Mandelbrot fractal here
            mandelbrotCache = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            using (var g = Graphics.FromImage(mandelbrotCache))
            {
                var imgRect = new Rectangle(0, 0,
                                            mandelbrotCache.Width,
                                            mandelbrotCache.Height);

                g.FillRectangle(new HatchBrush(HatchStyle.Cross, Color.DarkBlue,
                                Color.LightBlue), imgRect);
            }

            // this is the pen to draw the rectangle with
            rectPen = new Pen(Color.Red, 3);
        }

        private Rectangle CreateRectangle(Point pt1, Point pt2)
        {
            // we use this method to create a rectangle with positive width and height
            int x1 = Math.Min(pt1.X, pt2.X);
            int y1 = Math.Min(pt1.Y, pt2.Y);

            return new Rectangle(x1, y1, Math.Abs(pt1.X - pt2.X), Math.Abs(pt1.Y - pt2.Y));
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
                this.startPoint = e.Location;// record the start position
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                // record the current position as the end point if the left button is down
                this.endPoint = e.Location;
                // force a redraw
                this.Invalidate();
            }
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                // setting the point to -1,-1 makes them get drawn off the screen
                startPoint = new Point(-1, -1);
                endPoint = new Point(-1, -1);

                // force an update so that the rectangle disappears
                this.Invalidate();
            }
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            // draw the cached Mandelbrot image
            e.Graphics.DrawImage(mandelbrotCache, new Point(0, 0));

            // draw the current rectangle
            e.Graphics.DrawRectangle(rectPen, CreateRectangle(startPoint, endPoint));
        }
    }
}

这是绘制矩形的屏幕截图。
注意:鼠标左键仍然处于按下状态。 释放按钮后,矩形立即消失。

Screenshot of a rectangle being drawn on the form

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM