-
Notifications
You must be signed in to change notification settings - Fork 7
HowTo : Drawing on a Panel Canvas
Martin Corino edited this page Mar 27, 2024
·
1 revision
About FAQ User Guide Reference documentation
One of the simplest ways to implement some image painting functionality for an application is using a Wx::Panel as to paint on. The following example code shows a basic drawing pane derived from Wx::Panel:
require 'wx'
class SimpleDrawingPane < Wx::Panel
def initialize(parent, id=Wx::ID_ANY)
super(parent, id)
# connecting this event handler is essential
evt_paint :on_paint
# connecting the following event handlers might be useful
# evt_erase_background :on_erase_background
# evt_motion :on_motion
# evt_left_down :on_left_down
# evt_left_up :on_left_up
# evt_left_up :on_right_down
# evt_left_up :on_right_up
# evt_left_dclick :on_left_double_click
# evt_right_dclick :on_right_double_click
# evt_left_up :on_leave_window
# evt_left_up :on_enter_window
# evt_left_up :on_key_down
# evt_left_up :on_key_up
# evt_left_up :on_mousewheel
end
def on_paint(evt)
# Drawing in the EVT_PAINT handler requires a Wx::PaintDC which we could create ourselves
# but luckily Wx::Window offers the convenience methods `#paint` and `#paint_buffered` which
# nicely handle creating **and** cleaning up the DC for us
self.paint { |dc| do_paint(dc) }
end
protected
# Separating the actual drawing operations this way will allow (later) addition of drawing functionality
# on other DCs than just a Paint DC (like for example a Memory DC for painting a bitmap image).
def do_paint(dc)
# draw some text
dc.draw_text('Testing', 40, 60)
# draw a circle
dc.set_brush(Wx::GREEN_BRUSH) # green filling
dc.set_pen(Wx::Pen.new(Wx::Colour.new(255,0,0), 5)) # 5-pixels-thick red outline
dc.draw_circle(Wx::Point.new(200,100), # centre
25) # radius
# draw a rectangle
dc.set_brush(Wx::BLUE_BRUSH) # blue filling
dc.set_pen(Wx::Pen.new(Wx::Colour.new(255,175,175), 10)) # 10-pixels-thick pink outline
dc.draw_rectangle([300, 100], # topleft
[400, 200]) # size
# draw a line
dc.set_pen(Wx::Pen.new(Wx::Colour.new(0,0,0), 3)) # black line, 3 pixels thick
dc.draw_line(300, 100, 700, 300) # draw line across the rectangle
end
end
This drawing pane could than be used in an application frame like this:
Wx::App.run do
frame = Wx::Frame.new(nil, title: 'Hello SimpleDrawingPane', pos: [50,50], size: [800,600])
sizer = Wx::HBoxSizer.new
sizer.add(SimpleDrawingPane.new(frame), 1, Wx::EXPAND)
frame.sizer = sizer
frame.set_auto_layout(true)
frame.show
end
- You must handle the paint event and the connected handler must be able to redraw the whole drawing at any time.
This is because your window manager may throw away your drawing at any time and ask you to draw it again later through
a paint event.
- The best way to deal with this is to separate state/data from view; i.e. the actual drawing routine reads variables describing the current state and draws according to this state. When something needs to change, don't draw it straight away; instead update state variables and call for a repaint (Wx::Window#refresh).
- Use a Wx::PaintDC (or Wx::BufferedPaintDC but see below) in paint events, and a Wx::ClientDC outside paint events.
- If you do handle the paint event, you must create a Wx::PaintDC in it, even if you don't use it. If a Wx::PaintDC object isn't created, the event isn't correctly handled which can cause weird behavior.
- Do not store the created DC or keep it for later in any way.
- Try buffered DCs, they may be necessary on some platforms although most platforms nowadays support native double-buffering.
Wx::AutoBufferedPaintDC would be best as that reverts
to a simple Wx::PaintDC if the platform supports native double-buffering.
- Event easier to use are the Wx::Window convenience methods Wx::Window#paint and Wx::Window#paint_buffered.
- Call Wx::Window#set_double_buffered(true) on the panel when on a platform not using native double-buffering (Windows only?).
- Call Wx::Window#set_background_style(Wx::BG_STYLE_PAINT).
-
-
Basic Guides
-
Widget Guides
-
Drawing Guides
-
Event Guides
-