wxPython - Dynamically resize image when frame is maximized - image

I want two images placed side-by-side to increase in size when the frame is resize (maximized). How do I achieve that?
import wx
class MyFrame2 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer11 = wx.BoxSizer( wx.HORIZONTAL )
self.m_bitmap3 = wx.StaticBitmap( self, wx.ID_ANY, wx.Bitmap( u"img/im1.jpg", wx.BITMAP_TYPE_ANY ), wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer11.Add( self.m_bitmap3, 1, wx.ALL|wx.EXPAND, 5 )
self.m_bitmap4 = wx.StaticBitmap( self, wx.ID_ANY, wx.Bitmap( u"img/im2.jpg", wx.BITMAP_TYPE_ANY ), wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer11.Add( self.m_bitmap4, 1, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( bSizer11 )
self.Layout()
self.Centre( wx.BOTH )
def __del__( self ):
pass
app = wx.App(0)
MyFrame2(None).Show()
app.MainLoop()

Based on your pastebin code
import wx
class MyFrame2 ( wx.Frame ):
def __init__( self, parent ):
wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
bSizer11 = wx.BoxSizer( wx.HORIZONTAL )
self.img1=wx.Image("1.bmp", wx.BITMAP_TYPE_ANY)
self.img2=wx.Image("1.bmp", wx.BITMAP_TYPE_ANY)
self.m_bitmap3 = wx.StaticBitmap( self, wx.ID_ANY, wx.BitmapFromImage(self.img1), wx.DefaultPosition, wx.DefaultSize, 0 )
bSizer11.Add( self.m_bitmap3, 1, wx.EXPAND, 0 )
self.m_bitmap4 = wx.StaticBitmap( self, wx.ID_ANY, wx.BitmapFromImage(self.img2))
bSizer11.Add( self.m_bitmap4, 1, wx.EXPAND, 0 )
self.Bind(wx.EVT_SIZE, self.onResize)
self.SetSizer( bSizer11 )
self.Layout()
self.Centre(wx.BOTH)
def __del__( self ):
pass
def onResize(self, event):
# self.Layout()
frame_size = self.GetSize()
frame_h = (frame_size[0]-10) / 2
frame_w = (frame_size[1]-10) / 2
img1 = self.img1.Scale(frame_h,frame_w)
img2 = self.img2.Scale(frame_h,frame_w)
self.m_bitmap3.SetBitmap(wx.BitmapFromImage(img1))
self.m_bitmap4.SetBitmap(wx.BitmapFromImage(img2))
self.Refresh()
self.Layout()
app = wx.App(0)
MyFrame2(None).Show()
app.MainLoop()
Note: a single self.Bind
the size of the Scale is based on half of the frame size and the images are scaled from the original images each time, otherwise they slowly get more and more distorted.

You will need to bind to wx.EVT_SIZE since that is the event that is fired when you resize the frame. Then in that handler, you will want to update the image's size. You can use the Scale() method from wx.Image to change the image's size. Note that you will probably want to scale the image in such a way that you maintain it's aspect ratio or it will look weird when it gets stretched.
Here's an example based loosely on my tutorial for a Photo Viewer from a few years ago:
import os
import wx
class PhotoCtrl(wx.App):
def __init__(self, redirect=False, filename=None):
wx.App.__init__(self, redirect, filename)
self.frame = wx.Frame(None, title='Photo Control', size=(400, 400))
self.image_loaded = False
self.current_size = self.frame.GetSize()
self.filepath = None
self.panel = wx.Panel(self.frame)
self.Bind(wx.EVT_SIZE, self.onResize)
self.PhotoMaxSize = self.current_size.GetHeight() - 10
self.createWidgets()
self.frame.Show()
def createWidgets(self):
instructions = 'Browse for an image'
img = wx.EmptyImage(240,240)
self.imageCtrl = wx.StaticBitmap(self.panel, wx.ID_ANY,
wx.BitmapFromImage(img))
instructLbl = wx.StaticText(self.panel, label=instructions)
self.photoTxt = wx.TextCtrl(self.panel, size=(200,-1))
browseBtn = wx.Button(self.panel, label='Browse')
browseBtn.Bind(wx.EVT_BUTTON, self.onBrowse)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(wx.StaticLine(self.panel, wx.ID_ANY),
0, wx.ALL|wx.EXPAND, 5)
self.mainSizer.Add(instructLbl, 0, wx.ALL, 5)
self.mainSizer.Add(self.imageCtrl, 0, wx.ALL, 5)
self.sizer.Add(self.photoTxt, 0, wx.ALL, 5)
self.sizer.Add(browseBtn, 0, wx.ALL, 5)
self.mainSizer.Add(self.sizer, 0, wx.ALL, 5)
self.panel.SetSizer(self.mainSizer)
self.panel.Layout()
def onBrowse(self, event):
"""
Browse for file
"""
wildcard = "JPG files (*.jpg)|*.jpg"
dialog = wx.FileDialog(None, "Choose a file",
wildcard=wildcard,
style=wx.OPEN)
if dialog.ShowModal() == wx.ID_OK:
self.photoTxt.SetValue(dialog.GetPath())
self.onView()
dialog.Destroy()
def scale_image(self):
if self.filepath:
img = wx.Image(self.filepath, wx.BITMAP_TYPE_ANY)
# scale the image, preserving the aspect ratio
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.PhotoMaxSize
NewH = self.PhotoMaxSize * H / W
else:
NewH = self.PhotoMaxSize
NewW = self.PhotoMaxSize * W / H
img = img.Scale(NewW,NewH)
return img
def onView(self):
self.filepath = self.photoTxt.GetValue()
img = self.scale_image()
self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
self.panel.Refresh()
self.image_loaded = True
def onResize(self, event):
print 'resizing'
if self.image_loaded:
if self.current_size != self.frame.GetSize():
self.current_size = self.frame.GetSize()
self.PhotoMaxSize = self.current_size.GetHeight() - 30
img = self.scale_image()
self.imageCtrl.SetBitmap(wx.BitmapFromImage(img))
self.panel.Refresh()
self.panel.Layout()
if __name__ == '__main__':
app = PhotoCtrl()
app.MainLoop()
Note that this seems to scale the image just fine, but the buttons on the bottom are getting chopped off. I'm not sure why and don't really have the time at the moment to diagnose that issue, but in general this is probably the way you want to do it.

Related

wxPython - Fixing buttons to a given position in a image

I'm building a software where I need to display buttons over a image and make it stay somewhat in the same position (the best as possible) when the sizer the image is in gets resized.
The button-display-on-image is already done. I just need to get the math working now. I've tried a bunch of stuff with no luck yet. I guess the magic need to happen in the updateButtons function.
Thanks!
import wx
import wx.lib.platebtn as pb
class MainFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent)
self.bInfoSizerVisibility = False
self.images = []
self.initUI()
self.CenterOnScreen()
self.Bind(wx.EVT_SIZE, self.OnResizing)
def initUI(self):
self.imageSizer = wx.BoxSizer(wx.VERTICAL)
self.imageSizer.SetMinSize((800, 600))
self.bitmap = None
self.image = None
self.aspect = None
self.bmpImage = wx.StaticBitmap(self, wx.ID_ANY)
self.imageSizer.Add(self.bmpImage, 1, wx.EXPAND)
self.btn = pb.PlateButton(self.bmpImage, -1, 'Click Me!', style=pb.PB_STYLE_NOBG)
self.btn.Bind(wx.EVT_BUTTON, self.test)
self.btn.Position = 250, 250
self.SetSizerAndFit(self.imageSizer)
self.frameImage()
def test(self, event):
print('Button Pressed!')
def updateButtons(self):
w, h = self.bmpImage.GetSize()
u, v = 0.3, 0.7
self.btn.Position = int(u * w), int(v * h)
def frameImage(self, isJustResize=False):
if not isJustResize:
self.bitmap = wx.Bitmap('image.jpg', wx.BITMAP_TYPE_ANY)
self.image = wx.Bitmap.ConvertToImage(self.bitmap)
self.aspect = self.image.GetSize()[1] / self.image.GetSize()[0]
self.Layout()
sW, sH = self.imageSizer.GetSize()
newW = sW
newH = int(newW * self.aspect)
if newH > sH:
newH = sH
newW = int(newH / self.aspect)
image = self.image.Scale(newW, newH)
self.bmpImage.SetBitmap(image.ConvertToBitmap())
self.Layout()
self.Refresh()
self.updateButtons()
# print(f"Image New Size: ({newW}, {newH})")
# print(f"App Size: {self.GetSize()}")
# print(f"imageSizer Size: {self.imageSizer.GetSize()}\n")
def OnResizing(self, event):
self.frameImage(True)
event.Skip()
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
You need to take into account the fact that as you resize the image, white space appears, either to the left and right, or on top and bottom. Remember, the button position is relative to the frame and not the image.
I have rewritten your updateButtons method to implement this.
I have assumed that your button's position will be 0.3 * the width of the image from the left and 0.7 * the height of the image from the top
import wx
import wx.lib.platebtn as pb
IMAGE_MINIMUM_SIZE = (800, 600)
BUTTON_POSITION_RATIO = (0.3, 0.7)
class MainFrame(wx.Frame):
def __init__(self, parent):
super().__init__(parent)
self.bInfoSizerVisibility = False
self.images = []
self.initUI()
self.CenterOnScreen()
self.Bind(wx.EVT_SIZE, self.OnResizing)
def initUI(self):
self.imageSizer = wx.BoxSizer(wx.VERTICAL)
self.imageSizer.SetMinSize(IMAGE_MINIMUM_SIZE)
self.bitmap = None
self.image = None
self.image_aspect = None
self.bmpImage = wx.StaticBitmap(self, wx.ID_ANY)
self.imageSizer.Add(self.bmpImage, 1, wx.EXPAND)
self.btn = pb.PlateButton(self, -1, 'Click Me!', style=pb.PB_STYLE_NOBG)
self.btn.Bind(wx.EVT_BUTTON, self.test)
self.SetSizerAndFit(self.imageSizer)
self.frameImage()
def test(self, event):
print('Button Pressed!')
def updateButtons(self):
frame_aspect = self.Size[0] / self.Size[1]
button_horizontal = int(self.Size[0] * BUTTON_POSITION_RATIO[0])
button_vertical = int(self.Size[1] * BUTTON_POSITION_RATIO[1])
if self.image_aspect <= frame_aspect:
# Frame is wider than image so find the horizontal white space size to add
image_width = self.Size[1] * self.image_aspect
horizontal_offset = (self.Size[0] - image_width)/2
button_horizontal = int(horizontal_offset + image_width * BUTTON_POSITION_RATIO[0])
elif self.image_aspect > frame_aspect:
# Frame is higher than image so find the vertical white space size to add
image_height = self.Size[0] / self.image_aspect
vertical_offset = (self.Size[1] - image_height)/2
button_vertical = int(vertical_offset + image_height * BUTTON_POSITION_RATIO[1])
self.btn.Position = (button_horizontal, button_vertical)
def frameImage(self, isJustResize=False):
if not isJustResize:
self.bitmap = wx.Bitmap('image.jpg', wx.BITMAP_TYPE_ANY)
self.image = wx.Bitmap.ConvertToImage(self.bitmap)
self.image_aspect = self.image.GetSize()[0] / self.image.GetSize()[1]
image_width, image_height = self.imageSizer.GetSize()
new_image_width = image_width
new_image_height = int(new_image_width / self.image_aspect)
if new_image_height > image_height:
new_image_height = image_height
new_image_width = int(new_image_height * self.image_aspect)
image = self.image.Scale(new_image_width, new_image_height)
self.bmpImage.SetBitmap(image.ConvertToBitmap())
self.Layout()
self.Refresh()
self.updateButtons()
def OnResizing(self, event):
self.frameImage(True)
event.Skip()
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()

Is there a way to pass a parameter to the button event function?

Is there a way to pass a parameter to the event function? When I press the submit button, I receive the following error:
NameError: global name 'filename' is not defined
Here is the full error:
raceback (most recent call last):
File "C:\Users\sbing\OneDrive\Documents\CNM\Spring2018\CIS1250_Python\Labs\Prgm11\geopoint.py", line 60, in submit
file = open(filename.GetValue(), 'r')
NameError: global name 'filename' is not defined
Here is my code:
# handle submit button
def submit(self, event):
file = open(filename.GetValue(), 'r')
contents.SetValue(file.read())
file.close()
def createForm(self):
# establish the wxPython App
app = wx.App()
# establish the wxPython frame
win = wx.Frame(None,title="Closes Neighbor", size = (610,535))
# define the screen widgets
# text controls
filename = wx.TextCtrl(win, pos = (100, 50), size = (210, 25))
latitude = wx.TextCtrl(win, pos = (100, 80), size = (210, 25))
longitude = wx.TextCtrl(win, pos = (100, 110), size = (210, 25))
description = wx.TextCtrl(win, pos = (100, 140), size = (210, 25))
answer = wx.TextCtrl(win, pos = (100, 250), size = (400, 50),
style=wx.TE_MULTILINE | wx.HSCROLL)
answer.SetEditable(False)
messages = wx.TextCtrl(win, pos = (100, 350), size = (400, 50),
style=wx.TE_MULTILINE | wx.HSCROLL)
messages.SetEditable(False)
# static labels
lblTitle = wx.StaticText (win, pos = (200, 25), size = (210,25),
label = "Closest Neighbor", style = wx.ALIGN_CENTER)
lblFilename = wx.StaticText (win, pos = (10, 50), size = (210,25),
label = "Filename:")
lblLatitude = wx.StaticText (win, pos = (10, 80), size = (210,25),
label = "Latitude:")
lblLongitude = wx.StaticText (win, pos = (10, 110), size = (210,25),
label = "Longitude:")
lblDescription = wx.StaticText (win, pos = (10, 140), size = (210,25),
label = "Description:")
lblAnswer = wx.StaticText (win, pos = (10, 250), size = (210,25),
label = "Answer:")
lblMessages = wx.StaticText (win, pos = (10, 350), size = (210,25),
label = "Messages:")
# buttons
submitButton = wx.Button(win, label='Find the Closest Point',
pos = (100, 180), size = (180, 25))
submitButton.Bind(wx.EVT_BUTTON, self.submit)
# get the ball roling
win.Show()
app.MainLoop()
As mentioned in my comment, the easiest way to achieve what you want is to change the reference to self.filename but in answer to the question asked, yes you can.
Use the lambda function.
import wx
class TestFrame(wx.Frame):
def __init__(self, *args):
wx.Frame.__init__(self, *args)
Button = wx.Button(self, -1, "Click me")
Button.Bind(wx.EVT_BUTTON, lambda event: self.OnButton(event, flag1="Parameter", flag2="Something else"))
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(Button,1,0,0)
self.SetSizerAndFit(sizer)
self.Show()
def OnButton(self, event, flag1, flag2):
print ("The Button was pressed")
print ("Flag1 was set to ", flag1)
print ("Flag2 was set to ", flag2)
if __name__ == "__main__":
app = wx.App()
myframe = TestFrame(None, -1, "Button Test")
app.MainLoop()

Optimize resizing picture on a button with PIL

self.image2Code:
from tkinter import *
from tkinter import font
from PIL import Image, ImageTk
class App(Tk):
def __init__(self):
Tk.__init__(self)
self.variables()
self.makeUI()
def variables(self):
self.buttonlist = []
self.font = font.Font(family = "Consolas", size = 12, weight = "bold")
def makeUI(self):
self.title("Changing font")
self.geometry("300x300")
self.minsize(200, 200)
self.maxsize(1000, 1000)
self.columnconfigure(0, weight = 1)
self.rowconfigure(0, weight = 1)
self.buttonlist.append(Button(self, height = 2, width = 4, font = self.font))
self.buttonlist[0].grid(row = 0, column = 0, sticky = W+E+S+N, padx = 2, pady = 2)
self.update()
self.image2 = Image.open("1.png")
self.image = ImageTk.PhotoImage(self.image2.resize((self.buttonlist[0].winfo_width(), self.buttonlist[0].winfo_height()), Image.ANTIALIAS))
self.buttonlist[0].configure(image = self.image)
self.buttonlist[0].bind("<Configure>", self.changeimage)
def changeimage(self, *args):
self.update()
#use smaller size
x = self.buttonlist[0].winfo_width()
y = self.buttonlist[0].winfo_height()
x = x if x < y else y
self.image = ImageTk.PhotoImage(self.image2.resize((x, x), Image.ANTIALIAS))
self.buttonlist[0].configure(image = self.image)
def main():
root = App()
root.mainloop()
if __name__ == "__main__":
main()
The problem:
The code works, the problem is that the program is slow on a quite powerful PC. It is making unnecessary calculations. My image is called "1.png".I don't know if I'm using the right approach.

WxPython Resize an Image using GridBagSizer

I am sorry if this is too simple... I tried to add a logo to my first GUI, however, I am not sure what is the best way to resize it. At this moment, I am using image.Scale to adjust the logo size and place GridBagSizer.
self.image = wx.Image("logo11w.png", wx.BITMAP_TYPE_ANY)
w = self.image.GetWidth()
h = self.image.GetHeight()
self.image = self.image.Scale(w/8, h/8)
self.sb1 = wx.StaticBitmap(self.panel, -1, wx.BitmapFromImage(self.image))
self.sizer.Add(self.sb1, pos=(0, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=15)
.
I am wondering if there is an auto way to do this? Since I am using GridBagSizer, is it possible to leave one "grid" (e.g., 1 by 1 "box") for my logo? Thanks in advance!
Code:
import wx
class landing_frame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size(800, 600), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
self.font1 = wx.Font(18, wx.DECORATIVE, wx.ITALIC, wx.BOLD)
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
self.panel = wx.Panel(self)
self.sizer = wx.GridBagSizer(5, 15)
self.image = wx.Image("logo11w.png", wx.BITMAP_TYPE_ANY)
w = self.image.GetWidth()
h = self.image.GetHeight()
self.image = self.image.Scale(w/8, h/8)
self.sb1 = wx.StaticBitmap(self.panel, -1, wx.BitmapFromImage(self.image))
self.sizer.Add(self.sb1, pos=(0, 0), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=15)
self.text1 = wx.StaticText(self.panel, label="Welcome!")
self.sizer.Add(self.text1, pos=(0, 2), flag=wx.TOP|wx.LEFT|wx.BOTTOM, border=15)
line = wx.StaticLine(self.panel)
self.sizer.Add(line, pos=(1, 0), span=(1, 5), flag=wx.EXPAND|wx.BOTTOM, border=10)
self.text2 = wx.StaticText(self.panel, label="Question 1?")
self.sizer.Add(self.text2, pos=(2, 0), flag=wx.ALL, border=10)
self.sampleList = ['Op1', 'Op2', 'Op3']
self.combo = wx.ComboBox(self.panel, 10, choices=self.sampleList)
self.sizer.Add(self.combo, pos=(2, 1), span=(1, 5), flag=wx.EXPAND|wx.ALL, border=10)
self.input1 = wx.StaticText(self.panel, 11, label="Please Enter Filepath")
self.sizer.Add(self.input1, pos=(3, 0), span=(1, 1), flag=wx.ALL , border=10)
self.input2 = wx.FilePickerCtrl(self.panel, 12, wx.EmptyString, u"Select a file", u"*.*", wx.DefaultPosition, wx.DefaultSize, wx.FLP_DEFAULT_STYLE )
self.sizer.Add(self.input2, pos=(3, 1), span=(1, 20), flag=wx.EXPAND|wx.ALL, border=10)
self.input3 = wx.StaticText(self.panel, 13, label="Additional inputs")
self.sizer.Add(self.input3, pos=(4, 0), flag=wx.ALL , border=10)
self.input4 = wx.TextCtrl(self.panel, 14, 'E.g. ...', wx.DefaultPosition, wx.DefaultSize, 0, wx.DefaultValidator )
self.sizer.Add(self.input4, pos=(4, 1), span=(1, 10), flag=wx.EXPAND|wx.ALL, border=10)
self.panel.SetSizer(self.sizer)
if __name__ == '__main__':
app = wx.App(redirect=False, filename="mylogfile.txt")
landing_frame(None, title="Test")
app.MainLoop()
Here is the logo

wxPython - Resizing an image with the EVT_SIZE event of its parent panel

My previous attempt at asking this question was horrible and I had also made some progress, please bear with me, I did not intend to re-ask this so many times, and it is not my style.
Here is the final version: I am resizing a window that contains a DC Client painted bitmap and on the EVT_SIZE event, I am resizing it by re-scaling it (using scale, not rescale) and re-painting the image. The problem is it does not appear as though its respecting the aspect ratio even though I am calculating w/h for it. Also when it grows in height the image is distorted. Finally, when another window passes over it, the image goes white. Any ideas how to fix any of these issues? My window/image class is below:
class TransactionImage(wx.Window):
def __init__(self, parent, fname, name):
wx.Window.__init__(self, parent, name=name)
self.dc = wx.ClientDC(self)
self.load_image(fname)
cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER)
self.SetCursor(cursor)
self.Bind(wx.EVT_SIZE, self.resize_space)
def load_image(self, image):
self.image = wx.Image(image, wx.BITMAP_TYPE_JPEG)
(w, h) = self.image.GetSize()
self.image_ar = w/h
def resize_space(self, size):
(w, h) = self.get_best_size()
self.s_image = self.image.Scale(w, h)
self.bitmap = wx.BitmapFromImage(self.s_image)
self.dc.DrawBitmap(self.bitmap, 0, 0, useMask=False)
# how can I 'refresh this area to make it 'fit'
def get_best_size(self):
(window_width, window_height) = self.GetSizeTuple()
new_height = window_width / self.image_ar
new_size = (window_width, new_height)
return new_size
Also, I am having trouble understanding how to properly use the Client DC. I want to refresh the window area before re-drawing the next image, because if i dont i get weird risiduals and it looks bad. In order to fix this I tried using dc.Clear which cleans the background off. However, doing so on every size call as i would need to causes the image to flash white a million times while im re-sizing. how can i avoid this?
EDIT -
In response to Umyal's comment response - here is a very simplified version of my application. Either way I class my window generator for the images the size handler re-scaling the images causes the image to flicker badly, creating an unappealing artifact. Also, when another frame passes over the application, the image display becomes white, as if been erased.
I was thinking as a way around this - I could implement the solution windows image viewer seems to have, which is the image is only rescaled and repainted when the user lets go of the edge of the frame when resizing it. Problem with that solution is that there is no clear way to detect when the user stops resizing the frame. (wxEVT_SIZE, wxEVT_SIZING)
Here is the simplified application code, you will need to find your own images and the bigger the better. The original image dimentions are 3872 x 2592
# this is required for 'real' math - derive the 'aspect ratio'
from __future__ import division
import wx
class TransactionImage(wx.Window):
def __init__(self, parent, fname, name):
wx.Window.__init__(self, parent, name=name)
self.load_image(fname)
cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER)
self.SetCursor(cursor)
self.Bind(wx.EVT_SIZE, self.resize_space)
self.Bind(wx.EVT_PAINT, self.on_paint)
def load_image(self, image):
self.image = wx.Image(image, wx.BITMAP_TYPE_JPEG)
(w, h) = self.image.GetSize()
self.image_ar = w/h
self.bitmap = wx.BitmapFromImage(self.image)
def resize_space(self, event):
(w, h) = self.get_best_size()
self.s_image = self.image.Scale(w, h)
self.bitmap = wx.BitmapFromImage(self.s_image)
def on_paint(self, event):
self.dc = wx.PaintDC(self)
self.dc.DrawBitmap(self.bitmap, 0, 0, useMask=False)
def get_best_size(self):
(window_width, window_height) = self.GetSizeTuple()
new_height = window_width / self.image_ar
new_size = (window_width, new_height)
return new_size
class OriginalTransactionImage(wx.Window):
def __init__(self, parent, fname, name):
wx.Window.__init__(self, parent, name=name)
self.dc = wx.ClientDC(self)
self.load_image(fname)
cursor = wx.StockCursor(wx.CURSOR_MAGNIFIER)
self.SetCursor(cursor)
self.Bind(wx.EVT_SIZE, self.resize_space)
def load_image(self, image):
self.image = wx.Image(image, wx.BITMAP_TYPE_JPEG)
(w, h) = self.image.GetSize()
self.image_ar = w/h
def resize_space(self, size):
(w, h) = self.get_best_size()
self.s_image = self.image.Scale(w, h)
self.bitmap = wx.BitmapFromImage(self.s_image)
self.dc.DrawBitmap(self.bitmap, 0, 0, useMask=False)
def get_best_size(self):
(window_width, window_height) = self.GetSizeTuple()
new_height = window_width / self.image_ar
new_size = (window_width, new_height)
return new_size
class ImageBrowser(wx.Frame):
def __init__(self, image1, image2, parent=None, id=wx.ID_ANY,
pos=wx.DefaultPosition, title='Image Browser'):
size = (1500, 800)
wx.Frame.__init__(self, parent, id, title, pos, size)
self.CentreOnScreen()
self.panel = wx.Panel(self, wx.ID_ANY)
self.panel.SetBackgroundColour(wx.Colour(191,197,229))
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.image_panel = wx.Panel(self.panel, wx.ID_ANY, style=wx.SIMPLE_BORDER)
self.image_panel.SetBackgroundColour(wx.Colour(255, 255, 255))
self.image_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.image_panel.SetSizer(self.image_sizer)
self.load_image_sizer(image1, image2)
self.main_sizer.Add(self.image_panel, 1, wx.GROW|wx.ALIGN_CENTER|wx.ALL, 25)
self.panel.SetSizer(self.main_sizer)
def load_image_sizer(self, image1, image2):
#bitmap1 = OriginalTransactionImage(self.image_panel, image1, 'image1')
#bitmap2 = OriginalTransactionImage(self.image_panel, image2, 'image2')
bitmap1 = TransactionImage(self.image_panel, image1, 'image1')
bitmap2 = TransactionImage(self.image_panel, image2, 'image2')
self.image_sizer.Add(bitmap1, 1, wx.GROW|wx.ALIGN_LEFT|wx.ALL, 20)
self.image_sizer.Add(bitmap2, 1, wx.GROW|wx.ALIGN_RIGHT|wx.ALL, 20)
class IBApp(wx.App):
def OnInit(self):
img1 = "0_3126_image1.jpeg"
img2 = "0_3126_image2.jpeg"
ib = ImageBrowser(img1, img2)
ib.Show()
self.SetTopWindow(ib)
return True
app = IBApp(False, None)
app.MainLoop()
Do not keep a reference to client DC in your window instance(http://docs.wxwidgets.org/2.6/wx_wxclientdc.html) ,neither it is the proper way of drawing over window dc
instead bind to PAINT_EVENT and draw there, below i have shown the things you said add to your class
class TransactionImage(wx.Window):
def __init__(self, parent, fname, name):
self.Bind(wx.EVT_SIZE, self.resize_space)
self.Bind(wx.EVT_PAINT, self.onpaint)
def onpaint(self):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bitmap, 0, 0, useMask=False)
def resize_space(self, size):
(w, h) = self.get_best_size()
self.s_image = self.image.Scale(w, h)
self.bitmap = wx.BitmapFromImage(self.s_image)
self.Refresh()

Resources