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).
Related
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.
The rectangle won't show up for me on a windows computer. I gave this to someone else who was a mac user and the rectangle showed up. I am not receiving any errors so I can't seem to figure this out. I am using python 2.7.7.
import socket
import wx
class WindowFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title = title, size=(500, 400))
self.panel=wx.Panel(self)
self.panel.SetBackgroundColour("#E6E6E6")
self.control = wx.TextCtrl(self.panel, style = wx.TE_MULTILINE, size =(410, 28), pos=(0,329))
sendbutton=wx.Button(self.panel, label ="Send", pos =(414,325), size=(65,35))
self.panel.Bind(wx.EVT_PAINT, self.OnPaint)
self.Centre()
self.Show()
def OnPaint(self, event):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('#d4d4d4'))
dc.SetBrush(wx.Brush('#c56c00'))
dc.DrawRectangle(10, 15, 90, 60)
self.Show(True)
if __name__=="__main__":
app = wx.App(False)
frame = WindowFrame(None, 'ChatClient')
app.MainLoop()
The problem with this code is that the OP is wanting to draw on the panel, but then proceeds to tell the PaintDC object to paint to the frame. The OnPaint method should look like this:
def OnPaint(self, event):
dc = wx.PaintDC(self.panel) # <<< This was changed
dc.SetPen(wx.Pen('#d4d4d4'))
dc.SetBrush(wx.Brush('#c56c00'))
dc.DrawRectangle(10, 15, 90, 60)
The following code makes a window with a grey gradient bar.
import wx
class GradientFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Center()
self.Show()
def OnSize(self, event):
event.Skip()
self.Refresh()
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
rect = self.GetClientRect()
dc.SetBackground(wx.Brush("white"))
dc.Clear()
rect.SetHeight(30)
dc.GradientFillLinear(rect, '#fbfbfb', '#efefef', wx.SOUTH)
rect.SetTop(30)
rect.SetHeight(2)
dc.GradientFillLinear(rect, '#dbdbdb', '#c1c1c1', wx.SOUTH)
app = wx.App(0)
frame = GradientFrame(None, 'Test')
app.MainLoop()
I would like to add toogle buttons like the following screenshot, that allows to access to different pages / panels of the GUI (each of them containing their own widgets, etc.)
What is the good framework for that : should these buttons be created manually in OnPaint (this would be very 'low-level') or somewhere else? Is there a ready-to-use way to use buttons linked to different pages ?
There is no good framework for creating custom widgets. However, there are some good recipes out there:
https://stackoverflow.com/questions/1351448/how-to-make-custom-buttons-in-wx
http://wiki.wxpython.org/CreatingCustomControls
Those two links should get you started. You can also take a look at the source for GenericButtons, AquaButton or PlateButton for additional ideas.
Alternatively, you could also just create a panel that's a specific size and put some of the custom buttons or just regular buttons on it instead.
Here's an example of how to use PlateButtons that should get you started:
import wx
import wx.lib.platebtn as platebtn
class GradientFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title)
self.panel = wx.Panel(self)
self.panel.Bind(wx.EVT_PAINT, self.OnPaint)
self.panel.Bind(wx.EVT_ERASE_BACKGROUND, lambda event: None)
self.panel.Bind(wx.EVT_SIZE, self.OnSize)
# add plate buttons
top_sizer = wx.BoxSizer(wx.VERTICAL)
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
labels = ["Morceaux", "Albums", "Artistes", "Genres"]
style = platebtn.PB_STYLE_GRADIENT
for label in labels:
btn = platebtn.PlateButton(self.panel, label=label, style=style)
btn.SetPressColor(wx.Colour(208,208,208))
btn_sizer.Add(btn, 0, wx.RIGHT|wx.LEFT|wx.CENTER, 5)
top_sizer.Add(btn_sizer, 0, wx.ALL|wx.CENTER, 5)
top_sizer.Add((1,1), 1, wx.EXPAND)
self.panel.SetSizer(top_sizer)
self.Center()
self.Show()
def OnSize(self, event):
event.Skip()
self.Refresh()
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self.panel)
rect = self.panel.GetClientRect()
dc.SetBackground(wx.Brush("white"))
dc.Clear()
rect.SetHeight(30)
dc.GradientFillLinear(rect, '#fbfbfb', '#efefef', wx.SOUTH)
rect.SetTop(30)
rect.SetHeight(2)
dc.GradientFillLinear(rect, '#dbdbdb', '#c1c1c1', wx.SOUTH)
app = wx.App(0)
frame = GradientFrame(None, 'Test')
app.MainLoop()
I want to limit the size of a list control box. Let us take the following code:
import wx
class Students(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(380, 230))
hbox = wx.BoxSizer(wx.HORIZONTAL)
panel = wx.Panel(self, -1)
self.list = wx.ListCtrl(panel, -1, style=wx.LC_REPORT)
self.list.InsertColumn(0, 'name')
self.list.InsertColumn(1, 'age')
hbox.Add(self.list, 1,wx.EXPAND)
panel.SetSizer(hbox)
self.Centre()
self.Show(True)
app = wx.App()
Students(None, -1, 'studs')
app.MainLoop()
If I make the horizontal box sizer's proportion=0, like this:
hbox.Add(self.list, 0,wx.EXPAND)
then there is a different problem. The problem with proportion=1 is that after 'Age' column, there is a lot of empty space the list control box is eating up for the third column which doesn't exist.
The problem with proportion=0 is that it is too short in width.
I want to display the list control box with 'Name' and 'Age' columns only and save the rest of the space. How do I do that?
You can set the width of your list control manually and then set the proportion to 0.
The width of columns can be set manually:
import wx
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour(wx.GREEN)
self.list = wx.ListCtrl(self, style=wx.LC_REPORT, size=(200, -1))
column_size = self.list.GetSize()[0] / 2 - 2
self.list.InsertColumn(0, 'Name')
self.list.InsertColumn(1, 'Age')
self.list.SetColumnWidth(0, column_size)
self.list.SetColumnWidth(1, column_size)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.list, proportion=0, flag=wx.EXPAND)
self.sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
self.SetSizerAndFit(self.sizer)
self.SetSize((600, 400))
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
Or the ListCtrlAutoWidthMixin may be used:
import wx
import wx.lib.mixins.listctrl as listmix
class TestListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
def __init__(self, *args, **kwargs):
wx.ListCtrl.__init__(self, *args, **kwargs)
listmix.ListCtrlAutoWidthMixin.__init__(self)
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour(wx.GREEN)
self.list = TestListCtrl(self, style=wx.LC_REPORT, size=(200, -1))
self.list.InsertColumn(0, 'Name')
self.list.InsertColumn(1, 'Age')
self.sizer = wx.BoxSizer()
self.sizer.Add(self.list, proportion=0, flag=wx.EXPAND)
self.sizer.Add(self.panel, proportion=1, flag=wx.EXPAND)
self.SetSizerAndFit(self.sizer)
self.SetSize((600, 400))
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
Don't use wx.EXPAND if you don't want the control to resize. You could also put a spacer into the horizontal sizer right after the list control and make it expand instead. Then the spacer will take up all the available space.
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