Flexible 'em' style Fonts with wxPython - python

Im looking for a way to present a flexible font, that will increase and decrease in size according to to the size of the screen resolution. I want to be able to do this without the HTML window class. Is there a way? I thought I've done quite a bit of googling without success.
EDIT
This seems a good question, I changed the title to reflect closer what I was looking for.
EDIT
So now I've realized that the regular pixel sizes will scale in the way I mentioned already - but I saw this the other day and realized it might be helpful if someone wanted to use CSS with their wxPython Apps - its a library that allows you to 'skin' your application and I can think of a dozen neat ways to use it already - here is a link in lieu of a more well thought out question :)
link text

Maybe something like this? You can scale any wx.Window in this way. Not sure if this is exactly what you mean though.
import wx
def scale(widget, percentage):
font = widget.GetFont()
font.SetPointSize(int(font.GetPointSize() * percentage / 100.0))
widget.SetFont(font)
class Frame(wx.Frame):
def __init__(self):
super(Frame, self).__init__(None, -1, 'Scaling Fonts')
panel = wx.Panel(self, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
for i in range(50, 201, 25):
widget = wx.StaticText(panel, -1, 'Scale Factor = %d' % i)
scale(widget, i)
sizer.Add(widget, 0, wx.ALL, 5)
panel.SetSizer(sizer)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = Frame()
frame.Show()
app.MainLoop()

Related

How do i resize a widget in WxPython using GridSizer

Introduction and Issue
I've made a gridsizer to resize my frame itself.
But because of the gridsizer if I use WX_EXPAND flag (to let them have a new height and width when I use self.Layout() to refresh when the app is resized) they don't resize the % of the screen I gave them (I put blank widget to put all my widget where I want).
Example here
What I have tried
I've tried to make a wx.GridBagSizer but I can't understand why it always say that GenericTreeCtrl don't exist (its a must I need this tree) so I'm asking a way to do this with wx.GridSizer.
I want to work with something like that and be able to resize my widget: what I want to be resizable
Question
Can you please tell me whats the correct and optimal way to dynamically resize a widget using a wx.GridSizer?
class mainPanel(wx.Panel):
def __init__(self, parent, pageNum, FrameSize):
self.parent = parent
self.pageNum = pageNum
wx.Panel.__init__(self, parent=parent)
Sizer = wx.GridSizer(6,6,0,0)
self.PathList = []
self.PathSelected = []
self.pastePath = ""
self.SetSizer(Sizer)
#tree
widthA,heightA = FrameSize[0],FrameSize[1]
path = "/media/" + os.getlogin()
self.folder_tree_project = wx.GenericDirCtrl(self, wx.ID_ANY,path, (0,0), wx.Size(widthA*0.3,heightA*0.75),wx.FULL_REPAINT_ON_RESIZE|wx.DIRCTRL_MULTIPLE)
Sizer.Add(self.folder_tree_project,0,wx.LEFT,0)
self.t1 = self.folder_tree_project.GetTreeCtrl()
self.folder_tree_project.ShowHidden(False)
self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelect,id=self.t1.GetId())
self.Bind(wx.EVT_SIZE, self.OnResize)
#--------------------------------------------------------
def OnResize(self,event):
FrameSize = self.GetSize()
self.Sizer.Layout()
Try this
def OnResize(self,event):
FrameSize = self.GetSize()
widthA,heightA = FrameSize[0],FrameSize[1]
self.folder_tree_project.SetSize((int(widthA*0.3),int(heightA*0.75)))
self.Sizer.Layout()
I will not be able to test it Leonardo but thanks for the reply ! (i did not answered because of the Global Game Jam that i was participating)
I've found another way thanks to someone on another forum, using the app 'WxGlade' I was able to understand how GridBagSizer work.
You can't do things like GenericDirCtrl in WxGlade but I've read the code given by it by putting button and blank text like I want and putting gridbagsizer, with the previsualization and the generated code I was able to understand how GridBagSizer work.

Setting the background color in ThumbnailCtrl in wxPython

I'm trying to use the ThumbnailCtrl and I would like to change the background color.
I would have expected this code to work
self.thumbnail_ctrl.SetBackgroundColour('red')
Unfortunately it does not works and I ended hacking a solution show in the following minimal example in which I used the internal field _scrolled setting the background color on it.
I'm still a beginner and would like to ask if I did something wrong with the expected call show above.
#!/usr/bin/env python
import wx
import wx.lib.agw.thumbnailctrl as TC
class MyPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent=parent)
self.thumbnail_ctrl = TC.ThumbnailCtrl(parent=self, imagehandler=TC.NativeImageHandler)
self.thumbnail_ctrl.ShowFileNames(False) # do not show the filename under the thumbs
self.thumbnail_ctrl.SetThumbOutline(TC.THUMB_OUTLINE_RECT) # outline the rect
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.main_sizer.Add(window=self.thumbnail_ctrl, proportion=1, flag=wx.ALL|wx.EXPAND, border=0)
self.SetSizer(self.main_sizer)
# Hack to set the background color of self.thumbnail_ctrl
# self.thumbnail_ctrl.SetBackgroundColour('red') # Calling this does not works
self.thumbnail_ctrl._scrolled.SetBackgroundColour('red') # Calling this the background color is set to red
self.Refresh()
class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='minimal set background example')
self.panel = MyPanel(parent=self)
self.Show()
if __name__ == '__main__':
app = wx.App(redirect=True)
frame = MyFrame()
app.MainLoop()
As far as I remember I haven’t put in any way to set the background color of Thumbnailctrl - I simply forgot I guess. So your solution, while of course a hack, it’s a perfectly valid one. You may want to open an issue or submit a PR to wxPython github so a proper SetBackgroundColour can be added to the class in the source.

TextCtrl scrollbar unusable until window is resized

Solved:
Thanks to Aya's answer below I now know that the issue was caused by self.panel = wx.Panel(self, -1) on line 18. I created a panel and didn't attach anything to it. The original issue description is still below for reference.
My Google-fu has failed me. I'm building the text editor that you can find here, written in Python with wxPython:
https://github.com/joshsaintjacque/py-ed/blob/master/pyed.py
The issue that I'm running into is this: when I open a text file (the only functionality built in at this point) that's larger than the viewable area in the TextCtrl the scroll bar remains disabled until the window is re-sized, then it works fine.
I know that the act of re-sizing the window is running some command that I'm neglecting to include in my OpenFile function (or perhaps in init), but I can't figure out what.
Any thoughts anyone has that could lead me in the right direction would be greatly appreciated.
Thanks!
+1 for including a link to the full source code - makes it so much easier to test.
I couldn't reproduce the fault you describe on wxPython 2.8.12 on Win32, but upon running your code, I found a seemingly extraneous wx.Panel object being created on pyed.py line 18...
self.panel = wx.Panel(self, -1)
...which seems to be interfering with the correct operation of the program. After commenting out that line, it seems to work fine.
A couple of other things I noticed: line 56...
self.SetTitle("PyEd - Editing ... " + filename)
...should probably be put in the preceding if-block, otherwise you'll get an error if the user clicks "Cancel" on the wx.FileDialog, and on line 16...
wx.Frame.__init__(self, parent, id, 'PyEd', (-1, -1), wx.Size(640, 480))
...if you use keyword args rather than positional args...
wx.Frame.__init__(self, parent=parent, id=id, title='PyEd', size=wx.Size(640, 480))
...you needn't bother re-specifying the default value for the window position, which is also slightly safer, in case the wxPython developers decide to change the defaults in a future version.
You can also factor out constant values, and the optional creation of the wx.Size object to reduce that line to...
wx.Frame.__init__(self, parent=None, title='PyEd', size=(640, 480))
Finally, with regards to IDs: in most cases you'll probably find they're of little use. Where they come in handy is where you want many similar controls, and it makes more sense to have them handled by a single event handler function.
Consider this example...
def create_buttons(parent):
parent.button1 = wx.Button(label='Button 1')
parent.button2 = wx.Button(label='Button 2')
parent.button3 = wx.Button(label='Button 3')
parent.button1.Bind(wx.EVT_BUTTON, on_button_1)
parent.button2.Bind(wx.EVT_BUTTON, on_button_2)
parent.button3.Bind(wx.EVT_BUTTON, on_button_3)
def on_button_1(event):
print 'You clicked button 1'
def on_button_2(event):
print 'You clicked button 2'
def on_button_3(event):
print 'You clicked button 3'
...which is fine, but if you need, say, 100 buttons, you may prefer to implement it like this...
def create_buttons(parent):
parent.buttons = [wx.Button(id=i, label='Button %d' % i) for i in range(100)]
parent.Bind(wx.EVT_BUTTON, on_button)
def on_button(event):
button_id = event.GetId()
print 'You clicked button %d' % button_id
Oh, and be careful using id as a variable name, because it's also a Python built-in function name.
It looks as if you're not setting the min or max size hints for the window, nor are you calling Self.Fit() to fit the box sizer to the window size (or is it the other way round? I'm rusty on my wxPython...)
Right where you call self.SetSizer(sizer), you should be able to fix this by adding:
self.Fit()
self.SetSizeHintSz(minSize=wx.Size(640, 480))
You may be able to get around the separate call to self.Fit() by using self.SetSizerAndFit()
(edited for spelling.)

Resizable divider line in wxpython?

I am not sure what they are called, but I would like a resizable divider line, to separate widgets.
I would like something like this (except horizontal):
http://imm.io/bKgf
If you do not know what i am talking about please comment, thanks and sorry for my ignorance.
You need, maybe, a splitterwindow:
import wx
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.splitter = wx.SplitterWindow(self)
pan1 = wx.Window(self.splitter, style=wx.BORDER_SUNKEN)
pan1.SetBackgroundColour("yellow")
wx.StaticText(pan1, -1, "My Left Panel")
pan2 = wx.Window(self.splitter, style=wx.BORDER_SUNKEN)
pan2.SetBackgroundColour("orange")
wx.StaticText(pan2, -1, "my Right Panel")
self.splitter.SplitVertically(pan1, pan2, -100)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
I'm not sure if this will exactly meet your needs, but you might have a look at wxPython's aui module. There's some demo code on that page that'll get you started, and the wxPython demo has some good examples to try out.
What you want is wx.StaticLine. Just create one of those and add it to your sizer with the EXPAND style flag. See http://www.wxpython.org/docs/api/wx.StaticLine-class.html for more info.
EDIT: Oh, I think Joaquin's suggestion for a SplitterWindow may be spot on. Note that there a couple other types of SplitterWindows, like MultiSplitterWindow and FourWaySplitter

sending colored text to a TextCtrl in wxpython

I'm trying to send colored text to a TextCtrl widget, but don't know how
style = wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2
self.status_area = wx.TextCtrl(self.panel, -1,
pos=(10, 270),style=style,
size=(380,150))
basically that snippet defines a status box in my window, and I want to write colored log messages to it. If I just do self.status_area.AppendText("blah") it will append text like I want, but it will always be black. I can't find the documentation on how to do this.
You need to call SetStyle to change the text behavior.
import wx
class F(wx.Frame):
def __init__(self, *args, **kw):
wx.Frame.__init__(self, None)
style = wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|wx.TE_RICH2
self.status_area = wx.TextCtrl(self, -1,
pos=(10, 270),style=style,
size=(380,150))
self.status_area.AppendText("blahblahhblah")
fg = wx.Colour(200,80,100)
at = wx.TextAttr(fg)
self.status_area.SetStyle(3, 5, at)
app = wx.PySimpleApp()
f = F()
f.Show()
app.MainLoop()
documentation of wxwidgets has this to say (you can also look up wxPython docs, but it points to wxwidgets anyway):
either use SetDefaultStyle before you append text to your textctrl, or after inserting text use SetStyle.
According to docs, the first solution is more efficient (and sounds easier to me.)

Categories