Draw randomly colored dots in DrawingArea - how?

Post

Posted
Rating:
#1 (In Topic #1230)
Trainee
I've got this simple program that I'm trying to create randomly colored dots in the drawing area but all I get is the first dot (when program loads) and the last dot (after clicking the button).

How do I make is to that I get to see randomly colored dots across the entire DrawingArea?

To make the dots standout, I'm using an expanded a 128x128 canvas.

This is my first foray into the DrawingArea object and there's very little documentation (that I could find) to help me trundle along so here I am.

Code (gambas)

  1. ' Gambas class file
  2. Private factor As Integer = 4
  3.  
  4. Public Sub DrawingArea1_Draw()
  5.   With Paint
  6.     .Brush = .Color(Color.RGB(red, green, blue, 0))
  7.     .LineWidth = 3.0
  8.     .MoveTo(xpos, ypos)
  9.     .LineTo(xpos + factor - 1, ypos)
  10.     .LineTo(xpos + factor - 1, ypos + factor - 1)
  11.     .Lineto(xpos, ypos + factor - 1)
  12.     .LineTo(xpos, ypos)
  13.     .Stroke
  14.     .End
  15.  
  16. Public Sub btnDrawRandomlyColoredDots_Click()
  17.   Dim x, y As Integer
  18.   For x = 0 To 127
  19.     For y = 0 To 127
  20.       xpos = x * factor
  21.       ypos = y * factor
  22.       red = Rand(100, 255)
  23.       green = Rand(100, 255)
  24.       blue = Rand(100, 255)
  25.       DrawingArea1.Refresh
  26.     Next
  27.     DrawingArea1.Refresh
  28.   Next
  29.   DrawingArea1.Refresh
  30.  
  31. Public Sub Form_Open()
  32.  
  33.  
  34.  
Online now: No Back to the top

Post

Posted
Rating:
#2
Guru
BruceSteers is in the usergroup ‘Guru’
The DrawingArea_Draw event is to paint the entire Drawing area surface , totally, from blank.

Calling .Refresh triggers the draw event to clear the area and draw anew. (not just part of it)

So what you have there is an animation rapidly showing random single dots.

you should put the loop in the Draw event and call the paint function and not DrawingArea1.Refresh so many times.

Code (gambas)

  1.  
  2. Public Sub btnDrawRandomlyColoredDots_Click()
  3.  
  4.   DrawingArea1.Refresh   ' trigger Draw event
  5.  
  6.  
  7. Public Sub PaintDot()
  8.  
  9.   With Paint
  10.     .Brush = .Color(Color.RGB(red, green, blue, 0))
  11.     .LineWidth = 3.0
  12.     .MoveTo(xpos, ypos)
  13.     .LineTo(xpos + factor - 1, ypos)
  14.     .LineTo(xpos + factor - 1, ypos + factor - 1)
  15.     .Lineto(xpos, ypos + factor - 1)
  16.     .LineTo(xpos, ypos)
  17.     .Stroke
  18.  
  19. Public Sub DrawingArea1_Draw()
  20.  
  21.   Dim x, y As Integer
  22.   For x = 0 To 127
  23.     For y = 0 To 127
  24.       xpos = x * factor
  25.       ypos = y * factor
  26.       red = Rand(100, 255)
  27.       green = Rand(100, 255)
  28.       blue = Rand(100, 255)
  29.       PaintDot()
  30.     Next
  31.   Next
  32.  
  33.  
  34. Public Sub Form_Open()
  35.  
  36.    
  37.  
  38.  
Online now: No Back to the top

Post

Posted
Rating:
#3
Guru
BruceSteers is in the usergroup ‘Guru’
Depending on the application it can be better to use a simple PictureBox and use paint functions to paint the picture.

Like I say it depends on the application, sometimes a DrawingArea is prefered , sometimes a Picture

A PictureBox can be easily manipulated and things added to it,

Code (gambas)

  1.  
  2.  PictureBox1.Picture = New Picture(100, 100, True)
  3.  Paint.Begin(PictureBox1.Picture)
  4.   '  paint code here
  5.  Paint.End
  6.  
  7.  
The benefits of a Picture over a drawing area is a Picture can be made/added to by code and the picture just then displayed as it is,
or then there's the DrawingArea that has to paint its contents via code with each refresh..


Another option is to paint the Picture and then use Paint.DrawPicture() in the DrawingArea1_Draw() event to paint it as a background that you then paint on top of.


PS. i noticed in your code you used Paint.End in the Draw event.
you should not really do that, you should only use Paint.End if you have used Paint.Begin() on an object.  
The Draw event is inside the controls Paint.Begin/Paint.End instructions so you do not need to use Paint.End. the control may possibly have more drawing to do and will expect the Paint device to be active.
Online now: No Back to the top

Post

Posted
Rating:
#4
Trainee

BruceSteers said

Depending on the application it can be better to use a simple PictureBox and use paint functions to paint the picture.

Like I say it depends on the application, sometimes a DrawingArea is prefered , sometimes a Picture

A PictureBox can be easily manipulated and things added to it,

Code (gambas)

  1.  
  2.  PictureBox1.Picture = New Picture(100, 100, True)
  3.  Paint.Begin(PictureBox1.Picture)
  4.   '  paint code here
  5.  Paint.End
  6.  
  7.  
The benefits of a Picture over a drawing area is it can be added to bit by bit and the picture just displayed as it is,
or the drawingarea that has to paint its contents via code each refresh..


PS. i noticed in your code you used Paint.End in the Draw event.
you should not do that, you should only use Paint.End if you have used Paint.Begin() on an object.  
The Draw event is inside the controls Paint.Begin/Paint.End instructions you you do not need to End it. the control may possibly have more drawing to do and will expect the Paint device to be active.

Thanks muchly, Bruce.

I'll experiment with the PictureBox too as I'm still in the early stage of my project so no lock-in yet - brain or code -  :D!

PS: The code in DrawingArea1_Draw() was a copy and paste from an example I spotted somewhere in the forum - copied and pasted without any understanding as I experimented.

Let the awakening begin…

Cheers,
ak.
Online now: No Back to the top

Post

Posted
Rating:
#5
Trainee
 Hey Bruce,

I've modified my code as you had it above and noticed that the DrawingArea refresh several times when loses or gains focus and on form resize.  Is this something that can be overcome?

As it currently stands, it's not ideal for what I'm planning to do with it.  The PictureBox is already gaining favor.

ak.
Online now: No Back to the top

Post

Posted
Rating:
#6
Guru
BruceSteers is in the usergroup ‘Guru’

ak2766 said

Hey Bruce,

I've modified my code as you had it above and noticed that the DrawingArea refresh several times when loses or gains focus and on form resize.  Is this something that can be overcome?

As it currently stands, it's not ideal for what I'm planning to do with it.  The PictureBox is already gaining favor.

ak.

Sorry i just adapted your code to work but didn't really think about it, yes a Refresh can happen all by itself.

This is what i meant about using a Picture or DrawingArea depending on purpose.

options are to paint a picture and just show that in the Draw event.

or make your dots an array that the Draw event paints the same array each time.
Online now: No Back to the top

Post

Posted
Rating:
#7
Trainee

BruceSteers said


or make your dots an array that the Draw event paints the same array each time.

Ouch!  That was like a wake up slap - duh -  :mrgreen: !
Online now: No Back to the top

Post

Posted
Rating:
#8
Guru
BruceSteers is in the usergroup ‘Guru’

ak2766 said

BruceSteers said


or make your dots an array that the Draw event paints the same array each time.

Ouch!  That was like a wake up slap - duh -  :mrgreen: !

Haha.

I think your main problem was thinking the Draw() event and refresh do little bits.
But no , the refresh triggers the Draw event for a complete draw.

knowing that you should get thing rolling now :)

PS. never use Refresh in a Draw event as it will recursively crash.

also a good tip. try not to use anything that causes a Refresh in a draw event. like changing size or setting certain other properties. use the BeforeArrange() event for things like that.
Online now: No Back to the top

Post

Posted
Rating:
#9
Trainee

BruceSteers said

Haha.

I think your main problem was thinking the Draw() event and refresh do little bits.
But no , the refresh triggers the Draw event for a complete draw.

Exactly!  I initially only had the redraw in the inner loop but thought maybe I needed more -  ;).

Thanks for your help.  Really appreciated.

Cheers,
ak.
Online now: No Back to the top

Post

Posted
Rating:
#10
Trainee
BruceSteers

If I wanted to clear the DrawingArea, what's the process?

Some reading [1] led me to believe that the .Clear method would be the answer but it doesn't do what I expected:

Code (gambas)

  1. Public Sub btnClear_Click()
  2.  
  3.   clearform = True
  4.   DrawingArea1.Clear
  5.   DrawingArea1.Refresh
  6.  
  7.  

I even tried setting the .Cached to True but that caused dots to not be drawn at all.

Help!

[1]: /comp/gb.qt4/drawingarea/clear - Gambas Documentation

EDIT: Nevermind.  I figured out how to do it by iterating through all dots and deleting them one by one and then calling PaintDot.  I was hoping there was a way to clear them all at once but this has the added benefit of allowing me to delete selectively - which is something I need later anyway.
Online now: No Back to the top
1 guest and 0 members have just viewed this.