Hi
I would like to load an image from file, draw on top of the image then
display it in a frame. I based this code on some of the examples in
WPIA (rather crudely - apologies to the authors) but am now totally
confused about DC’s, panels, sizers etc. What I need to do (I
think) is
(a) load the image from file
(b) create an empty bitmap the same size as the image to use as a
buffer
© copy the image to the buffer
(d) draw on the buffer
(e) copy the buffer to the frame
(f) redraw (repaint?) the frame
The code is attached below and the image is (hopefully) attached.
The image loading and display in the frame (which seems to work OK) is
completely divorced from the DC stuff and I have no clue how to link the
two or get the DC back to the frame. Also, nothing seems to happen
when I draw on the DC. Again, your help and patience are much
appreciated. BTW the reason that I have used a sizer is that the
“proper” version of the code has a tree control in the top
frame where the image is displayed.
import wx
================
Class definition
================
Container class for model data
class ForecastData:
def __init__(self):
# Create empty lists
self.wells=[]
self.platforms=[]
WELL Class definition
class Well:
# Constructor
def __init__(self, name, xp, yp):
# Transfer arguments
self.name=name
self.xp=xp
self.yp=yp
==================
Define main window
==================
class TopFrame(wx.Frame):
"""Frame class that acts as top level
window"""
# Constructor for main window
def __init__(self, data):
self.data = data
# Create a Frame
instance
wx.Frame.__init__(self, None,
title=‘Test load map and wells’)
# Create panel to hold
sizer
self.panel =
wx.Panel(self)
# Create the menu bar
menuBar =
wx.MenuBar()
menuFile = wx.Menu()
file_open =
menuFile.Append(wx.ID_ANY, “&Initialise wells”)
file_exit =
menuFile.Append(wx.ID_ANY, “E&xit”)
menuBar.Append(menuFile,"&File")
self.SetMenuBar(menuBar)
# Create the status
bar
self.CreateStatusBar()
self.SetStatusText("Test
model")
# Create a sizer to hold the
tree and image widgets
box=wx.BoxSizer(wx.HORIZONTAL)
# Load the image, convert to a
bitmap and add bitmap to sizer
bmp =
self.InitBuffer()
box.Add(bmp, 0)
# Add the sizer to the panel
and fit to window
self.panel.SetSizerAndFit(box)
# Automatically resize the
window
self.Fit()
# Event handlers
self.Bind(wx.EVT_MENU,
self.OnFileOpen, file_open)
self.Bind(wx.EVT_MENU,
self.OnFileExit, file_exit)
self.Bind(wx.EVT_PAINT,
self.OnPaint)
bmp.Bind(wx.EVT_MOTION,
self.OnMove)
# Draw the buffer
def InitBuffer(self):
img =
wx.Image(‘structure_map.jpg’, wx.BITMAP_TYPE_JPEG)
bmp =
wx.StaticBitmap(self.panel, wx.ID_ANY, img.ConvertToBitmap())
size = img.GetSize()
self.buffer =
wx.EmptyBitmap(size.width, size.height)
dc = wx.BufferedDC(None,
self.buffer)
# Draw the wells
dc.SetPen(wx.Pen(‘red’))
for well in
self.data.wells:
···
#
Convert from UTMs to pixels
x =
int( 0.0566 * well.xp - 28175 )
y =
int(-0.0567 * well.yp + 533462)
dc.DrawCircle(x, y, 10)
dc.DrawText(well.name, x+8, y+8)
# Draw the platforms
dc.SetPen(wx.Pen(‘green’))
for plat in
self.data.platforms:
#
Convert from UTMs to pixels
x =
int( 0.0566 * plat.xp - 28175)
y =
int(-0.0567 * plat.yp + 533462)
dc.DrawRectangle(x-3, y-3, 6, 6)
dc.DrawText(plat.name, x+8, y+8)
return bmp
# Copy from buffer to screen
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self,
self.buffer)
# ==============
# Event handlers
# ==============
# Quit the application
def OnFileExit(self, event):
self.Destroy()
# Read forecast data from file (simplified
here)
def OnFileOpen(self, event):
wells = [
(“N01”, 499972, 9403796),
(“N02”, 500153, 9405231),
(“N03”, 501742, 9406500),
(“N04”, 503362, 9405067),
(“N05”, 501697, 9405257),
(“N06”, 502318, 9404462),
(“S01”, 503695, 9404609),
(“S02”, 504680, 9402994),
(“S03”, 504484, 9401498),
(“S04”, 502532, 9400929),
(“S05”, 500790, 9401976),
(“S06”, 501410, 9403508),
(“S07”, 502833, 9403160),
(“S08”, 499760, 9402927),
(“N07”, 499654, 9403216) ]
plats = [
(“main_plat”, 502500, 9403000), (“sat_north”, 501500,
9405250) ]
# Create well/platform objects
and transfer to data object
# (pretend platforms are wells
here for simplicity)
for well in wells:
name,
xp, yp = well
new_well = Well(name, xp, yp)
self.data.wells.append(new_well)
for plat in plats:
name,
xp, yp = plat
new_plat = Well(name, xp, yp)
self.data.platforms.append(new_plat)
# Repaint the image
self.InitBuffer()
# Display the location of the mouse
def OnMove(self, event):
pos =
event.GetPosition()
# Convert to pixels to
UTMs
utme = 498048 + 17.677 *
float(pos.x)
utmn = 9408000 - 17.636 *
float(pos.y)
if utme >= 499000.0 and
utme <= 505000.0 and utmn >= 9399000.0 and utmn <=
9408000.0:
self.SetStatusText(“Cursor at %d, %d” % (int(utme), int(utmn))
)
else:
self.SetStatusText(“Cursor outside model area”)
========================
Define application class
========================
class App(wx.App):
"""Application
class."""
def OnInit(self):
# Define data object
fcst_data =
ForecastData()
# Display top level
window
self.frame =
TopFrame(fcst_data)
self.frame.Show()
self.SetTopWindow(self.frame)
return True
def main():
app = App(False)
app.MainLoop()
if name == ‘main’:
main()