SaveFileDialog crashes in PaintEvent

I understand that the normal(correct) way is

  • add a canvas
  • create property pict (PictBuffer)
  • draw anything on the PictBuffer.graphics
  • then in the paint event of the canvas g.DrawPicture(PictBuffer,…

But this is not the case. I have not a PictBuffer.
But from the g property of the canvas I want to generate the picture.
Maybe is not possible?

I have not a PictBuffer.

Make one.
//property of window
pictBuffer as picture
pictBuffer = new picture (canvas.width, canvas.height)
//(you need to recreate that if the canvas size changes)

But from the g property of the canvas I want to generate the picture.
Maybe is not possible?

Thats correct.
G does not contain a picture for you to save.

“Make one”

Ok, but this means a lot of changing already working code. And, maybe at a performance cost…

changing already working code

I don’t think it is already working. :slight_smile:
But it’s your project, you know it better than us.

1 Like

To clarify things…

  1. Xojo should not crash using SavefileDialog on the paint event, event is it is not a good place to call it.
  2. I understand that is not possible, with Xojo, to recreate a picture from a Graphics. So if saving is needed should be used a buffer.

Two canvas show the same
FIRST CANVAS

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
  g.DrawRectangle(0,0,me.Width,me.Height)
  g.FontName = "Arial"
  g.FontSize = 20
  g.DrawingColor = Color.Blue
  g.DrawText("Hello!", 40, 40)
End Sub

SECOND CANVAS

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
  pictBuffer = new picture(400,400)
  var pBG as Graphics = pictBuffer.Graphics
  
  pBG.DrawRectangle(0,0,me.Width,me.Height)
  pBG.FontName = "Arial"
  pBG.FontSize = 20
  pBG.DrawingColor = Color.Blue
  pBG.DrawText("Hello! with buffer", 40, 40)
  g.DrawPicture(pictBuffer,0,0)
  
  // Now, pictBuffer contain the image showed
  // and may be saved.
End Sub

image

you could use the backdrop property as buffer.
in canvas open use

Sub Open() Handles Open
  Me.Backdrop = New Picture(Me.Width, Me.Height)
End Sub

if you paint use this

Sub Action() Handles Action
  Var pic As Picture = Canvas1.Backdrop
  
  Var r As New Random
  
  pic.Graphics.DrawingColor = Color.Red
  pic.Graphics.FillOval(r.InRange(32,128),r.InRange(32,128),r.InRange(24,32),r.InRange(24,32))
  
  Canvas1.Invalidate(False)
End Sub

try if you get canvas backdrop 1:1 to store as image file

If the image doesn’t change much, don’t draw it to the buffer in paint.
Draw it when it is convenient

In Paint, copy the buffer to G because it already exists.

Xojo may not actually be crashing, the application may be terminated by the OS for blocking windowServer. The contents of the crash report would confirm.

This design is making the OS wait for the content of the view, which maybe holding up a draw of the window, or even the entire screen. While at the same time, this design is asking the OS to draw another window atop the current window, which may be incurring additional redraws of a window that contains a view which is blocking a draw.

Even if the application was still running, it would impact system performance in a negative way.

You could always try creating a offscreen bitmap and using rectControl.drawInto to draw the canvas contents into the offscreen bitmap.

2 Likes
Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
  g.DrawRectangle(0,0,me.Width,me.Height)
  g.FontName = "Arial"
  g.FontSize = 20
  g.DrawingColor = Color.Blue
  g.DrawText("Hello!", 40, 40)
End Sub

Move this code to a new method

Sub Draw(g as graphics)
  g.DrawRectangle(0,0,me.Width,me.Height)
  g.FontName = "Arial"
  g.FontSize = 20
  g.DrawingColor = Color.Blue
  g.DrawText("Hello!", 40, 40)
End Sub

Change the paint event to

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
  Draw(g)
End Sub

Add a button for Save. In the Action event put

dim p as new Picture(canvas1.Width, Canvas1.Height)
Draw(p.Graphics)
// save p to disk

That will produce the exact same image you’re creating in Paint, but not incur the wrath of the OS. And you’re not really changing much code, just the location of that code. Does that make it any clearer?

2 Likes