0

Firstly, i am a complete noob at both C# and Java.

So i have been given this assignment to convert a java applet into C#, i have managed to do everything apart from drawing a rectangle on the screen via drag and drop using mouse events.

Whats supposed to happen is when i click and drag my mouse across the screen a rectangle with no fill and white border should appear. The code i have below is just a white screen with a red cross through it, if i comment out the if(action) statement in the form1_Paint then it works but no rectangle so it must be that code that messing it up.

http://gyazo.com/b2506b8c2ea9b304e34172c42ce98aab <-- what it should look like

http://gyazo.com/a8764ac9f5380f0109623d7a7750ddb6 <-- what it actually looks like

[update]

I have now got a rectangle do display but it happens on the MouseUp event rather than creating it as i am dragging my mouse. The obvious next step was to move it to a different mouse event like mouseMove but then it really messes up and created rectangles constantly as i make it bigger. How can i make it constantly resize the rectangle as i drag my mouse and not keep creating rectangles constantly? The code

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

    }
    //added load method
    private void Form1_Load(object sender, EventArgs e)//runs functions on load
    {
        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();  
        xs = xe = e.X;
        ys = ye = e.Y; // starting point y
         Form1_MouseMove(sender, e);
         this.Invalidate();

    }

    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;  
        //e.consume();

            //xe = e.X;
            //ye = e.Y;
            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();
            //Repaint();



    }
TheBear
  • 13
  • 2
  • @furkle based on the `using System.Windows.Forms` my guess would be Windows Forms. – juharr Nov 03 '14 at 19:40
  • @juharr Ah, I didn't see System.Drawing.Bitmap. I've deleted the original comment. – furkle Nov 03 '14 at 19:42
  • Most of it's commented out. That's not going to help any. – weston Nov 03 '14 at 20:09
  • Woops sorry yeah just realized i commented more out that i should of. Edited it now. – TheBear Nov 03 '14 at 20:46
  • @TheBear: this code example is _far_ more complicated than necessary. Not only is the fact that you're porting from Java apparently irrelevant (it's not like you show an original Java implementation of the behavior you want), but you've got all your Mandelbrot viewer computations left in here, when they have nothing to do with dragging a rectangle on the screen. You should edit it to make the example better. That said, the short answer is: you need to invalidate any time you update the data pertaining to the dragged rectangle, and then in the `Form1_Paint` handler, draw the rectangle dragged. – Peter Duniho Nov 03 '14 at 20:59
  • @PeterDuniho yeah your probably right, sorry. Ive tried to make it as simple as possible are use only the code i think i need. Also, i tried to do what you said but im a beginner at this so i am not 100% sure. So i have the above code now but its still not displaying the rectangle. – TheBear Nov 03 '14 at 22:41

2 Answers2

1

The biggest problem in your code is this statement in the Form1_Paint() method:

g1.Dispose();

You should never be disposing the Graphics instance passed to you. It belongs to the framework, not your code. But you should especially never dispose an object that you plan to use later. When you dispose it here, then the Graphics instance isn't valid later on when you try to draw the rectangle.

Note that this is the same as in Java. I hope the original Java code didn't call Graphics.dispose() too!

Some other suggestions:

  • when creating a new Pen object, add a using statement to ensure the Pen instance you create is disposed properly (you do own that one! :) ). In this case though, you don't need to create a new Pen object...just use the stock Pen provided by .NET. I.e. Pens.White.
  • you don't appear to be calling Invalidate() in the MouseDown and MouseMove event handlers. You won't get any visual feedback unless you do that, because the Paint event handler won't be called.

Fix the code so it looks like this:

// Little helper method :)
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));
    }
}

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

}

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    action = true;
    // e.consume();
    if (action)
    {
        xs = xe = e.X;
        ys = ye = e.Y;
        Invalidate();
    }
}
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • hey man thanks for the reply. I have taken the dispose out. I have been going at this for a number of hours and my code has slightly changed for the better. Take a look. Thank a lot, really appreciate it. – TheBear Nov 04 '14 at 00:06
  • Also i tried the code you suggested but the "Swap" does not exist apparently. – TheBear Nov 04 '14 at 00:13
  • The `Swap()` method is included in the code I posted. – Peter Duniho Nov 04 '14 at 00:46
  • And looking at your edit, you still have the problem that you aren't calling `Invalidate()` in the `MouseMove` handler. You definitely should _not_ be drawing anywhere except the `Paint` event handler. Just copy the code of the methods I posted to your program (including `Swap()`), replacing the existing versions with mine, and of course fix your `MouseUp` handler so it's back to the way it used to be (with no drawing) and it will work. – Peter Duniho Nov 04 '14 at 00:50
0

I've had a look here, this doesn't seem to fix my problem, the Invalidate();'s make it stutter and when I have it in Form1_Paint it doesn't draw correctly, either draws before straight onto the form, straight after I've zoomed but doesn't actually appear when I'm dragging in my zoom!

Dave Jones
  • 53
  • 10