How to draw text in a bitmap using wxpython? - python

I want to draw a number centered inside a wx.EmptyBitmap.
How can I do it using wxpython?
Thanks in advance :)
import wx
app = None
class Size(wx.Frame):
def __init__(self, parent, id, title):
frame = wx.Frame.__init__(self, parent, id, title, size=(250, 200))
bmp = wx.EmptyBitmap(100, 100)
dc = wx.MemoryDC()
dc.SelectObject(bmp)
dc.DrawText("whatever", 50, 50)
dc.SelectObject(wx.NullBitmap)
wx.StaticBitmap(self, -1, bmp)
self.Show(True)
app = wx.App()
Size(None, -1, 'Size')
app.MainLoop()
This code only gives me a black image, what am I doing wrong?
What's missing here..

Select the bmp in a wx.MemoryDC, draw anything on that dc and then select that bitmap out e.g.
import wx
app = None
class Size(wx.Frame):
def __init__(self, parent, id, title):
frame = wx.Frame.__init__(self, parent, id, title, size=(250, 200))
w, h = 100, 100
bmp = wx.EmptyBitmap(w, h)
dc = wx.MemoryDC()
dc.SelectObject(bmp)
dc.Clear()
text = "whatever"
tw, th = dc.GetTextExtent(text)
dc.DrawText(text, (w-tw)/2, (h-th)/2)
dc.SelectObject(wx.NullBitmap)
wx.StaticBitmap(self, -1, bmp)
self.Show(True)
app = wx.App()
app.MainLoop()

You use a wx.MemoryDC

Related

wxPython Drag and Drop files onto image, to add to array

I have a simple wxPython application with 1 image "Drop files here!" and 2 buttons.
I want the user to be able to drag and drop files onto the top section/image, at which point the image changes and the files are loaded into an array.
That's all I need but I have hit a major roadblock getting the drag and drop to work. Can someone please take a look at my code and figure out how/where to integrate the Drag and drop event? Any help would be great.
UI image
import wx
class DropTarget(wx.FileDropTarget):
def OnDropFiles(self, x, y, filenames):
print(filenames)
image = Image.open(filenames[0])
image.thumbnail((PhotoMaxSize, PhotoMaxSize))
image.save('thumbnail.png')
pub.sendMessage('dnd', filepath='thumbnail.png')
return True
def __init__(self, parent, ID, title):
wx.FileDropTarget.__init__(self, parent, ID, title, size=(300, 340), style= wx.CLOSE_BOX)
#self.widget = widget
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title, size=(300, 340), style= wx.CLOSE_BOX)
panel1 = wx.Panel(self,-1, style=wx.SUNKEN_BORDER)
panel2 = wx.Panel(self,-1, style=wx.SUNKEN_BORDER)
panel1.SetBackgroundColour("BLUE")
panel2.SetBackgroundColour("RED")
image_file = 'bgimage1.png'
bmp1 = wx.Image(
image_file,
wx.BITMAP_TYPE_ANY).ConvertToBitmap()
# image's upper left corner anchors at panel
# coordinates (0, 0)
self.bitmap1 = wx.StaticBitmap(
self, -1, bmp1, (0, 0))
# show some image details
str1 = "%s %dx%d" % (image_file, bmp1.GetWidth(),
bmp1.GetHeight())
# button
closeButton = wx.Button(self.bitmap1, label='Generate', pos=(30, 280))
closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
clearButton = wx.Button(self.bitmap1, label='Clear', pos=(170, 280))
clearButton.Bind(wx.EVT_BUTTON, self.OnClose)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(panel1, 5, wx.EXPAND)
box.Add(panel2, 1, wx.EXPAND)
self.SetAutoLayout(True)
self.SetSizer(box)
self.Layout()
def OnDropFiles(self, x, y, filenames):
self.window.updateDisplay(filenames)
for name in filenames:
self.window.WriteText(name + "\n")
print(name)
return True
def OnClose(self, e):
self.Close(True)
app = wx.App()
frame = MyFrame(None, -1, "Sizer Test")
frame.Show()
app.MainLoop()
You have the class DropTarget back to front with the init after the dropfiles. You also need to put the image and buttons on to one of the panels.
See below:
import wx
class DropTarget(wx.FileDropTarget):
def __init__(self, obj):
wx.FileDropTarget.__init__(self)
self.obj = obj
def OnDropFiles(self, x, y, filenames):
print("Drop Event",filenames)
# image = Image.open(filenames[0])
# image.thumbnail((PhotoMaxSize, PhotoMaxSize))
# image.save('new.png')
# pub.sendMessage('dnd', filepath='new.png')
return True
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title, size=(300, 340))
panel1 = wx.Panel(self,-1, style=wx.SUNKEN_BORDER)
panel2 = wx.Panel(self,-1, style=wx.SUNKEN_BORDER)
panel1.SetBackgroundColour("BLUE")
panel2.SetBackgroundColour("RED")
image_file = 'bgimage1.png'
bmp1 = wx.Image(image_file,wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap1 = wx.StaticBitmap(panel1, -1, bmp1, (0, 0))
# button
closeButton = wx.Button(panel2, -1, label='Generate',pos=(30, 280))
closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
clearButton = wx.Button(panel2, -1, label='Clear',pos=(170, 280))
clearButton.Bind(wx.EVT_BUTTON, self.OnClose)
self.file_drop_target = DropTarget(self)
self.SetDropTarget(self.file_drop_target)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(panel1, 0, wx.EXPAND,0)
box.Add(panel2, 0, wx.EXPAND,0)
self.SetAutoLayout(True)
self.SetSizer(box)
self.Layout()
def OnClose(self, e):
self.Close(True)
app = wx.App()
frame = MyFrame(None, -1, "Sizer Test")
frame.Show()
app.MainLoop()
This may not be what you want to achieve but at least it's a startiing point and the drag and drop works.

wxpython:How can I get the size of a panel or let a image fit the size of panel

I want to put an image into the center of a wxPanel, I am considering that I need to resize the image to fit the wxPanel. But I can't get the size of a wxPanel dynamically. And here is a test code.
#!/usr/bin/python
# wxboxsizer.py
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(500, 500))
panel1 = wx.Panel(self, -1,style= wx.SIMPLE_BORDER)
panel2 = wx.Panel(self, -1,style= wx.SIMPLE_BORDER)
panel3 = wx.Panel(self, -1,style= wx.SIMPLE_BORDER)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(panel1, 1,flag = wx.EXPAND|wx.ALL,border = 3 )
box.Add(panel2, 1,flag = wx.EXPAND|wx.ALL,border = 3 )
box.Add(panel3, 1,flag = wx.EXPAND |wx.ALL,border = 3)
self.SetSizer(box)
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'wxboxsizer.py')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()
This code can let the 3 panels fit the frame perfectly, but how can I get the size of the panel dynamically.
Furthermore, how can I put an image into a panel, and let the image fit the panel dynamically?
My solution: I just got a method to get the size of panel when the frame is resized.
#!/usr/bin/python
# wxboxsizer.py
import wx,os
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(500, 500))
self.panel1 = wx.Panel(self, -1,style= wx.SIMPLE_BORDER)
panel2 = wx.Panel(self, -1,style= wx.SIMPLE_BORDER)
panel3 = wx.Panel(self, -1,style= wx.SIMPLE_BORDER)
box = wx.BoxSizer(wx.VERTICAL)
box.Add(self.panel1, 1,flag = wx.EXPAND|wx.ALL,border = 3 )
box.Add(panel2, 1,flag = wx.EXPAND|wx.ALL,border = 3 )
box.Add(panel3, 1,flag = wx.EXPAND |wx.ALL,border = 3)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.SetSizer(box)
def OnSize(self, event):
size = self.GetSize()
size2 = self.panel1.GetSize()
print size,size2
event.Skip()
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'wxboxsizer.py')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()
This code can show the size of panel when the frame is resized.
The panel sizes are available after a Show()
Here is an example of both getting the panel sizes and fitting the same image into different size panels. 3 panels showing the same image. You would have to amend the Aspect calculation if you where showing the images in a vertical sizer.
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(500, 500))
self.MaxImageSize = 500
self.panel1 = wx.Panel(self)
self.panel2 = wx.Panel(self)
self.panel3 = wx.Panel(self)
self.Image1 = wx.StaticBitmap(self.panel1, bitmap=wx.EmptyBitmap(self.MaxImageSize, self.MaxImageSize))
self.Image2 = wx.StaticBitmap(self.panel2, bitmap=wx.EmptyBitmap(self.MaxImageSize, self.MaxImageSize))
self.Image3 = wx.StaticBitmap(self.panel3, bitmap=wx.EmptyBitmap(self.MaxImageSize, self.MaxImageSize))
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.panel1, 1,flag = wx.EXPAND|wx.ALL,border = 3)
box.Add(self.panel2, 2,flag = wx.EXPAND|wx.ALL,border = 3)
box.Add(self.panel3, 3,flag = wx.EXPAND|wx.ALL,border = 3)
self.SetSizer(box)
Img1 = wx.Image('./image2.png', wx.BITMAP_TYPE_PNG)
Img2 = wx.Image('./image2.png', wx.BITMAP_TYPE_PNG)
Img3 = wx.Image('./image2.png', wx.BITMAP_TYPE_PNG)
self.Show()
W,H = self.panel1.GetSize()
IW = Img1.GetWidth()
IH = Img1.GetHeight()
NewW = W
if IH>IW:
Aspect = float(IW) /float(IH)
else:
Aspect = float(IH) / float(IW)
NewH = W * Aspect
# scale the image, keeping ratio
Img1 = Img1.Scale(NewW,NewH)
self.Image1.SetBitmap(wx.BitmapFromImage(Img1))
W,H = self.panel2.GetSize()
NewW = W
NewH = W * Aspect
# scale the image, keeping ratio
Img2 = Img2.Scale(NewW,NewH)
self.Image2.SetBitmap(wx.BitmapFromImage(Img2))
W,H = self.panel3.GetSize()
NewW = W
NewH = W * Aspect
# scale the image, keeping ratio
Img3 = Img3.Scale(NewW,NewH)
self.Image3.SetBitmap(wx.BitmapFromImage(Img3))
self.Fit()
self.Layout()
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'Fit images')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()

align wx.DrawCircle to the center of the frame

Hi there I wanted to draw a circle at the center of the Frame.
Is there anything like wx.Align_Center I can use with wx.DrawCircle Below is my code.
#!/usr/bin/python
# points.py
import wx
import random
class Points(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(250, 150))
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Centre()
self.Show(True)
def OnPaint(self, event):
dc = wx.PaintDC(self)
dc.SetBrush(wx.Brush('RED'))
dc.DrawCircle(20,20)
app = wx.App()
Points(None, -1, 'Test')
app.MainLoop()
Just get the size of the frame and then divide the width and the height by 2.
import wx
import random
class Points(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(250, 150))
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Centre()
self.Show(True)
def OnPaint(self, event):
w, h = self.GetClientSize()
dc = wx.PaintDC(self)
dc.SetBrush(wx.Brush('RED'))
dc.DrawCircle(w/2,h/2, 20)
app = wx.App()
Points(None, -1, 'Test')
app.MainLoop()
That will get you pretty close. You might need to tweak the height a bit as I don't think GetSize accounts for the width of the System Menu (the top bar on all windows).

Changing the image size dynamically when the sizer's size changes in wxPython

I am working with python v2.7 and wxPython v3.0 on Windows 8 OS.
In the code snippet provided below simply creates a frame which has a vertical sizer that contains an image and an other horizontal sizer that in turn contains two panels.
Question: When I resize the frame by dragging the border, the panels resize automatically. Unlike the panels the image doesn't resize? How can I make my image to behave like panels for the case of resizing?
Code: The image file used can be downloaded from here: green.bmp
import wx
class Frame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, style=wx.DEFAULT_FRAME_STYLE)
panelA = wx.Panel(self,-1)
imageFile = wx.Image('greenbig.bmp', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
myBitmap = wx.StaticBitmap(panelA, -1, imageFile)
panel1 = wx.Panel(self, -1,style=wx.SIMPLE_BORDER)
panel2 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)
panelSizer = wx.BoxSizer(wx.HORIZONTAL)
panelSizer.Add(panel1, 1, wx.ALL|wx.EXPAND, 0)
panelSizer.Add(panel2, 1, wx.ALL|wx.EXPAND, 0)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panelA, 1, wx.ALL|wx.EXPAND, 0)
sizer.Add(panelSizer, 1, wx.ALL|wx.EXPAND, 0)
self.SetSizer(sizer)
self.Show(True)
app = wx.App()
frame = Frame(None, wx.ID_ANY, 'Image')
app.MainLoop()
Thank you for your time!
(eight years later) I was struggling to show an image that was dynamically resized with the window frame. These days, I'm using Python 3 with wxPython version 4. I pieced this solution from a lot of reading of the documentation and tips on how best to use sizers. I then whittled my code down to the absolute minimum required to accomplish this narrow use case.
Notice that I don't ever call Frame.Layout() or Panel.Layout() because I rely on the initial size of the Frame and the fact that a single Panel in a Frame will be automatically resized with the Frame. Also, any call to Fit() was unnecessary. The sizer containing the ImagePanel does need the EXPAND flag, but the ImagePanel does not need a sizer itself.
Note: you'll have to supply your own example image to load.
import wx
class ImagePanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.img = wx.Image(width=1, height=1)
self.ctrl = wx.StaticBitmap(self, bitmap=self.img.ConvertToBitmap())
self.Bind(wx.EVT_SIZE, self.on_resize)
def load_image(self):
with open('image.png', 'rb') as fin:
self.img = wx.Image(fin)
self.update_bitmap()
def update_bitmap(self):
w, h = self.GetSize()
self.ctrl.SetBitmap(self.img.Scale(w, h).ConvertToBitmap())
def on_resize(self, evt):
self.update_bitmap()
class MainWindow(wx.Frame):
def __init__(self):
initial_size = wx.Size(width=480, height=480)
super().__init__(None, wx.ID_ANY, title='Main Window Title', size=initial_size)
self.panel = wx.Panel(self)
self.image = ImagePanel(self.panel)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.image, proportion=1, flag=wx.EXPAND)
self.panel.SetSizer(vbox)
if __name__ == '__main__':
app = wx.App()
win = MainWindow()
win.Show()
win.image.load_image()
app.MainLoop()
The image will never be resized automatically. If you want this behaviour, you need to handle wxEVT_SIZE and do it yourself in its handler.

Animating gif in wxPython

I'm trying to animate a gif using wx-Python (2.7). The code listed below works but i want to create a function that animates the gif for me, so i can use it elsewhere. I've tried searching the internet but i can only find code that animates the gif within the __init__ function. Any ideas?
# -*- coding: cp1252 -*-
import wx
import wx.animate
class MyPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("black")
gif_fname = "skYmk.gif"
gif = wx.animate.GIFAnimationCtrl(self, id, gif_fname, pos=(10, 10))
gif.GetPlayer().UseBackgroundColour(True)
gif.Play()
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "wx.animate.GIFAnimationCtrl()", size = (200, 220))
MyPanel(frame, -1)
frame.Show(True)
app.MainLoop()
I don't understand your issue.... what is the problem in doing something like this?
import wx
import wx.animate
class MyPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("black")
gif_fname = "skYmk.gif"
gif = wx.animate.GIFAnimationCtrl(self, id, gif_fname, pos=(10, 10))
gif.GetPlayer().UseBackgroundColour(True)
self.gif = gif
def CallMeLater(self, play=True):
if play:
self.gif.Play()
else:
self.gif.Stop()
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "wx.animate.GIFAnimationCtrl()", size = (200, 220))
MyPanel(frame, -1)
frame.Show(True)
app.MainLoop()

Categories

Resources