We're a community of 1077K IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,076,163 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion
Page 8 of Article: Starting wxPython (GUI code)
The idea of this thread is to help the beginning wxPython GUI programmer with hints and helpful code. Please feel free to contribute! If you have any questions start your own thread! For info on wxPython modules see: http://www.wxpython.org/docs/api/wx-module.html

Just an experiment with box sizers and panels to get a desired layout ...

# use a wx.BoxSizer() for multisizer widget layout
# wx.VERTICAL = stacked vertically
# wx.HORIZONTAL = stacked horizontally
# add widget with Add() --> has options ...
# proportion=0 no vertical stretch with frame stretch in sizer_v
# proportion=1 stretch with frame stretch
# proportion=2 fill remaining space proportional (eg. 1:2)
# proportion=3 fill remaining space proportional (eg. 1:3)
# border=n  use a n pixel wide border
# wx.ALL puts the specified border on all sides
# (also has wx.LEFT wx.RIGHT wx.TOP and wx.BOTTOM)
# flag=wx.EXPAND --> expand to fit frame
# flag=wx.SHAPED --> change size preserving original aspect ratio

import wx

class MyFrame(wx.Frame):
   def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, -1, mytitle, size=mysize)

        panel1 = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
        panel2 = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
        panel3 = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)

        panel1.SetBackgroundColour("blue")
        panel2.SetBackgroundColour("red")
        panel3.SetBackgroundColour("green")

        # use two different BoxSizer() to layout the controls
        # in this case the vertical sizer will be the main sizer
        sizer_v = wx.BoxSizer(wx.VERTICAL)
        sizer_h = wx.BoxSizer(wx.HORIZONTAL)
        # add widgets to horizontal sizer
        # proportions are set to fill space ratio 1:2
        # keeps ratio on frame stretch
        sizer_h.Add(panel1, proportion=1, flag=wx.EXPAND)
        sizer_h.Add(panel2, proportion=2, flag=wx.EXPAND)
        # now add to vertical sizer in order
        sizer_v.Add(panel3, proportion=1, flag=wx.EXPAND)
        sizer_v.Add(sizer_h, proportion=3, flag=wx.EXPAND)

        # set the main sizer only
        self.SetSizer(sizer_v)


app = wx.App(0)
# create a MyFrame instance and show the frame
MyFrame(None, "Multi BoxSizer() Test", (300, 250)).Show()
app.MainLoop()
vegaseat
DaniWeb's Hypocrite
Moderator
6,475 posts since Oct 2004
Reputation Points: 1,447
Solved Threads: 1,611
Skill Endorsements: 36

This shows you how to add transparency to the wx.PaintDC canvas ...

# a simple wx drawing surface (canvas) using wx.PaintDC
# draw two overlapping circles
# transparency added with wx.GCDC
# tested with Python26 and wxPython28  by vegaseat

import wx

def on_paint(event):
    dc = wx.PaintDC(event.GetEventObject())
    dc.Clear()
    # wx.GCDC gives realistic transparency
    gcdc = wx.GCDC(dc)

    # set pen (border) colour
    # wx.Pen(colour, width=1, style=wx.SOLID)
    gcdc.SetPen(wx.Pen('red', 1))
    
    # alpha tranparency value 0 to 255
    # play with alpha to see the effect
    alpha = 175
    # rgb for red
    r, g, b = 255, 0, 0    
    brushcolour1 = wx.Colour(r, g, b, alpha)
    # rgb for yellow
    r, g, b = 255, 255, 0   
    brushcolour2 = wx.Colour(r, g, b, alpha)    

    # set fill colour and draw circle1
    gcdc.SetBrush(wx.Brush(brushcolour1))
    # DrawCircle(x, y, r)
    # center coordinates (x, y) and radius r
    gcdc.DrawCircle(120, 120, 100)

    # set fill colour and draw circle2
    gcdc.SetBrush(wx.Brush(brushcolour2))
    # DrawCircle(x, y, r)
    # center coordinates (x, y) and radius r
    gcdc.DrawCircle(280, 120, 100)    


app = wx.App(0)

frame = wx.Frame(None, -1, "wx canvas with circles", size=(410, 280))
frame.SetBackgroundColour('white')
# create the canvas
wx.EVT_PAINT(frame, on_paint)
# center the frame and show it
frame.Center(True)
frame.Show(True)

app.MainLoop()
vegaseat
DaniWeb's Hypocrite
Moderator
6,475 posts since Oct 2004
Reputation Points: 1,447
Solved Threads: 1,611
Skill Endorsements: 36

Since many days I was looking for simple text editor program using wxPython and didn't get to find anywhere but finally I found here. This is really a great thread to get information regarding to wxPython.

... and you are spamming what in your signature? Stop it, it's rude!

Kendustin
Newbie Poster
3 posts since May 2010
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

Just experimented putting red text in a listbox:

# load, sort, clear and add to wxPython's
# wx.ListBox(parent, id, pos, size, choices, style, name)
# choices is a list of strings
#
# style -->
# wx.LB_SINGLE  single-selection list (default)
# wx.LB_MULTIPLE  multiple-selection list, the user can toggle
#   multiple items on and off
# wx.LB_EXTENDED  extended-selection list, the user can select multiple
#  items using the SHIFT key, the mouse or special key combinations
# wx.LB_HSCROLL  create horizontal scrollbar if contents are too wide
#  (Windows only)
# wx.LB_ALWAYS_SB  always show a vertical scrollbar
# wx.LB_NEEDED_SB  Only create a vertical scrollbar if needed (default)
# wx.LB_SORT  The listbox contents are sorted in alphabetical order
# source from:  Sneekula 2008

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, mytitle, name_list):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle)
        self.SetBackgroundColour("brown")
        self.name_list = list(name_list)

        self.listbox = wx.ListBox(self, wx.ID_ANY, choices=[],
            style=wx.LB_EXTENDED)
        self.listbox.Bind(wx.EVT_LISTBOX, self.listboxClick)
        # optional text color for the list box
        self.listbox.SetForegroundColour("red")

        # create buttons
        self.load_button = wx.Button(self, wx.ID_ANY, "load ListBox")
        self.clear_button = wx.Button(self, wx.ID_ANY, "clear ListBox")
        self.sort_button = wx.Button(self, wx.ID_ANY, "sort ListBox")
        self.add_button = wx.Button(self, wx.ID_ANY, "add to ListBox")
        # bind mouse event to an action
        self.load_button.Bind(wx.EVT_BUTTON, self.load_buttonClick)
        self.clear_button.Bind(wx.EVT_BUTTON, self.clear_buttonClick)
        self.sort_button.Bind(wx.EVT_BUTTON, self.sort_buttonClick)
        self.add_button.Bind(wx.EVT_BUTTON, self.add_buttonClick)
        # create an output widget
        s1 = "load the list box ...\n"
        s2 = "to select a single item left click on the item\n"
        s3 = "to select a range of items shift click items\n"
        s4 = "to select multiple items ctrl click on items"
        self.text_out = wx.TextCtrl(self, wx.ID_ANY,
            value=(s1+s2+s3+s4), size=(300, 95),
            style=wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY)

        sizer = wx.GridBagSizer(vgap=5, hgap=5)
        # pos=(row, column)  span=(rowspan, columnspan)
        # wx.ALL puts the specified border on all sides
        sizer.Add(self.load_button, pos=(0, 0), flag=wx.ALL, border=5)
        sizer.Add(self.add_button, pos=(0, 1), flag=wx.ALL, border=5)
        # listbox spans 6 rows and 2 columns
        sizer.Add(self.listbox, pos=(1, 0), span=(6, 2),
            flag=wx.ALL|wx.EXPAND, border=5)
        sizer.Add(self.clear_button, pos=(7, 1), flag=wx.ALL, border=5)
        sizer.Add(self.sort_button, pos=(7, 0), flag=wx.ALL, border=5)
        sizer.Add(self.text_out, pos=(8, 0), span=(2, 2),
            flag=wx.ALL, border=5)
        self.SetSizer(sizer)

        # size the frame so all the widgets fit
        self.Fit()

    def add_buttonClick(self, event):
        """add another item to the listbox"""
        text = wx.GetTextFromUser('Enter new item', 'Add to listbox')
        if text != '':
            self.listbox.Append(text)

    def load_buttonClick(self, event):
        """load the name list into the bistbox"""
        # use self.listbox.Set(self.name_list) or ...
        for name in self.name_list:
            self.listbox.Append(name)

    def clear_buttonClick(self, event):
        """clear all items from the listbox"""
        self.listbox.Clear()
        self.text_out.ChangeValue("")

    def sort_buttonClick(self, event):
        """sort the items in the listbox"""
        # GetItems() is new in wxPython2.8
        # puts the listbox items into a list
        name_list = self.listbox.GetItems()
        name_list.sort()
        # Set() clears and reloads the listbox
        self.listbox.Set(name_list)

    def listboxClick(self, event):
        """display the selected ListBox item(s)"""
        """
        # for single item select use this ...
        selected_item = self.listbox.GetStringSelection()
        s = "You selected " + selected_item
        self.label.SetLabel(s)
        """
        name_list = self.listbox.GetItems()
        # for multiple and single item select use this ...
        pos_tuple = self.listbox.GetSelections()
        selected_list = []
        for pos in pos_tuple:
            selected_list.append(name_list[pos])
        s = "You selected " + str(selected_list)
        self.text_out.ChangeValue(s)


name_list = [
"Erich",
"Udo",
"Jens",
"Bjorn",
"Heidrun",
"Klaus",
"Ulla",
"Volger",
"Helmut",
"Freja",
"Larry",
"Andreas",
"Harry"
]

app = wx.App(0)
# create the MyFrame instance and then show the frame
MyFrame(None, 'wx.ListBox ops', name_list).Show()
app.MainLoop()
HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

Just experimented putting red text in a listbox:

# load, sort, clear and add to wxPython's
# wx.ListBox(parent, id, pos, size, choices, style, name)
# choices is a list of strings
#
# style -->
# wx.LB_SINGLE  single-selection list (default)
# wx.LB_MULTIPLE  multiple-selection list, the user can toggle
#   multiple items on and off
# wx.LB_EXTENDED  extended-selection list, the user can select multiple
#  items using the SHIFT key, the mouse or special key combinations
# wx.LB_HSCROLL  create horizontal scrollbar if contents are too wide
#  (Windows only)
# wx.LB_ALWAYS_SB  always show a vertical scrollbar
# wx.LB_NEEDED_SB  Only create a vertical scrollbar if needed (default)
# wx.LB_SORT  The listbox contents are sorted in alphabetical order
# source from:  Sneekula 2008

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, mytitle, name_list):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle)
        self.SetBackgroundColour("brown")
        self.name_list = list(name_list)

        self.listbox = wx.ListBox(self, wx.ID_ANY, choices=[],
            style=wx.LB_EXTENDED)
        self.listbox.Bind(wx.EVT_LISTBOX, self.listboxClick)
        # optional text color for the list box
        self.listbox.SetForegroundColour("red")

        # create buttons
        self.load_button = wx.Button(self, wx.ID_ANY, "load ListBox")
        self.clear_button = wx.Button(self, wx.ID_ANY, "clear ListBox")
        self.sort_button = wx.Button(self, wx.ID_ANY, "sort ListBox")
        self.add_button = wx.Button(self, wx.ID_ANY, "add to ListBox")
        # bind mouse event to an action
        self.load_button.Bind(wx.EVT_BUTTON, self.load_buttonClick)
        self.clear_button.Bind(wx.EVT_BUTTON, self.clear_buttonClick)
        self.sort_button.Bind(wx.EVT_BUTTON, self.sort_buttonClick)
        self.add_button.Bind(wx.EVT_BUTTON, self.add_buttonClick)
        # create an output widget
        s1 = "load the list box ...\n"
        s2 = "to select a single item left click on the item\n"
        s3 = "to select a range of items shift click items\n"
        s4 = "to select multiple items ctrl click on items"
        self.text_out = wx.TextCtrl(self, wx.ID_ANY,
            value=(s1+s2+s3+s4), size=(300, 95),
            style=wx.TE_MULTILINE|wx.HSCROLL|wx.TE_READONLY)

        sizer = wx.GridBagSizer(vgap=5, hgap=5)
        # pos=(row, column)  span=(rowspan, columnspan)
        # wx.ALL puts the specified border on all sides
        sizer.Add(self.load_button, pos=(0, 0), flag=wx.ALL, border=5)
        sizer.Add(self.add_button, pos=(0, 1), flag=wx.ALL, border=5)
        # listbox spans 6 rows and 2 columns
        sizer.Add(self.listbox, pos=(1, 0), span=(6, 2),
            flag=wx.ALL|wx.EXPAND, border=5)
        sizer.Add(self.clear_button, pos=(7, 1), flag=wx.ALL, border=5)
        sizer.Add(self.sort_button, pos=(7, 0), flag=wx.ALL, border=5)
        sizer.Add(self.text_out, pos=(8, 0), span=(2, 2),
            flag=wx.ALL, border=5)
        self.SetSizer(sizer)

        # size the frame so all the widgets fit
        self.Fit()

    def add_buttonClick(self, event):
        """add another item to the listbox"""
        text = wx.GetTextFromUser('Enter new item', 'Add to listbox')
        if text != '':
            self.listbox.Append(text)

    def load_buttonClick(self, event):
        """load the name list into the bistbox"""
        # use self.listbox.Set(self.name_list) or ...
        for name in self.name_list:
            self.listbox.Append(name)

    def clear_buttonClick(self, event):
        """clear all items from the listbox"""
        self.listbox.Clear()
        self.text_out.ChangeValue("")

    def sort_buttonClick(self, event):
        """sort the items in the listbox"""
        # GetItems() is new in wxPython2.8
        # puts the listbox items into a list
        name_list = self.listbox.GetItems()
        name_list.sort()
        # Set() clears and reloads the listbox
        self.listbox.Set(name_list)

    def listboxClick(self, event):
        """display the selected ListBox item(s)"""
        """
        # for single item select use this ...
        selected_item = self.listbox.GetStringSelection()
        s = "You selected " + selected_item
        self.label.SetLabel(s)
        """
        name_list = self.listbox.GetItems()
        # for multiple and single item select use this ...
        pos_tuple = self.listbox.GetSelections()
        selected_list = []
        for pos in pos_tuple:
            selected_list.append(name_list[pos])
        s = "You selected " + str(selected_list)
        self.text_out.ChangeValue(s)


name_list = [
"Erich",
"Udo",
"Jens",
"Bjorn",
"Heidrun",
"Klaus",
"Ulla",
"Volger",
"Helmut",
"Freja",
"Larry",
"Andreas",
"Harry"
]

app = wx.App(0)
# create the MyFrame instance and then show the frame
MyFrame(None, 'wx.ListBox ops', name_list).Show()
app.MainLoop()

Oh darn, those accidental duplicate posts in DaniWeb!

HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

To get individual lines coloured, you need to use the wx.ListCtrl():

# exploring wxPython's
# wx.ListCtrl(parent, id, pos, size, style)
# a fancier list box with a lot of mix-in options
# some of the styles =
# wx.LC_REPORT  report mode
# wx.LC_HRULES  draws horizontal rules between rows in report mode
# wx.LC_VRULES  draws vertical rules between columns in report mode
# some methods =
# InsertColumn(col, heading, format=wx.LIST_FORMAT_LEFT, width=-1)
# Original Source: zoe
# explore SetItemTextColour(item, colour) to colour individual lines

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, data):
        # use default size and position
        wx.Frame.__init__(self, parent, wx.ID_ANY,
            'Test the wx.ListCtrl()',
            size=(400, 220))
        self.SetBackgroundColour("yellow")
        # make data available to the instance
        self.data = data

        # create the list control
        self.lc = wx.ListCtrl(self, wx.ID_ANY, size=(-1, 120),
             style=wx.LC_REPORT|wx.SUNKEN_BORDER|wx.LC_HRULES)
        # select an item (left mouse click on it) and bind to an action
        self.lc.Bind(wx.EVT_LIST_ITEM_SELECTED,self.onAction)
        
        self.loadList()

        # set text color of items/lines 1, 3, 5 in list to red
        # needs style wx.LC_REPORT
        # do this after the list is loaded
        self.lc.SetItemTextColour(1, 'red')
        self.lc.SetItemTextColour(3, 'red')
        self.lc.SetItemTextColour(5, 'red')

        # create an output widget
        self.label = wx.StaticText(self, wx.ID_ANY, "Select a name")

        # use a vertical boxsizer for the widget placement
        sizer_v = wx.BoxSizer(wx.VERTICAL)
        sizer_v.Add(self.lc, 1, flag=wx.ALL|wx.EXPAND, border=10)
        sizer_v.Add(self.label, 0, flag=wx.ALL|wx.EXPAND, border=10)
        self.SetSizer(sizer_v)

    def loadList(self):
        # first the columns with header titles
        self.lc.InsertColumn(col=0,heading="Name",width=200)
        #self.lc.SetColumnWidth(0, 200)
        self.lc.InsertColumn(col=1,heading="Age",format=wx.LIST_FORMAT_RIGHT)
        self.lc.InsertColumn(col=2,heading="Weight",format=wx.LIST_FORMAT_RIGHT)

        # now each data row
        for key, val in self.data.items():
            # set max_rows, change if need be
            max_rows = 1000
            # also sets/updates row index starting at 0
            index = self.lc.InsertStringItem(max_rows, val[0])
            self.lc.SetStringItem(index, 1, val[1])
            self.lc.SetStringItem(index, 2, val[2])
            # needed by GetItemData()
            self.lc.SetItemData(index, key)

    def onAction(self, event):
        """ some action code"""
        # -1 --> get the first item that matches the specified flags
        # wx.LIST_NEXT_ALL  search for subsequent item by index
        # wx.LIST_STATE_SELECTED  get the selected item
        ix_selected = self.lc.GetNextItem(item=-1,
            geometry=wx.LIST_NEXT_ALL,
            state=wx.LIST_STATE_SELECTED)
        # get the value of the key in dictionary self.data
        data_value = self.data[self.lc.GetItemData(ix_selected)]
        # pick the name (first item in the value tuple)
        name = ' --> ' + data_value[0]
        self.label.SetLabel(str(data_value) + name)
        # testing --> index and name only
        ix = self.lc.GetFirstSelected()
        print ix, self.lc.GetItemText(ix)


# data to load the listctrl in the form of a dictionary
# the header is ('Name', 'Age', 'Weight')
data = {
1 : ('Heidi Kalumpa', '36', '127'),
2 : ('Frank Maruco', '27', '234'),
3 : ('Larry Pestraus', '19', '315'),
4 : ('Serge Romanowski', '59', '147'),
5 : ('Carolus Arm', '94', '102'),
6 : ('Michel Sargnagel', '21', '175')
}

app = wx.App(0)
# create a MyFrame instance and show the frame
MyFrame(None, data).Show()
app.MainLoop()
HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

The wx.StyledTextCtrl allows for line numbering, code folding and syntax highlighting. Here is a simple example of this somewhat complex widget ...

# wxstc_basics1.py
# styled text using wxPython's
# wx.StyledTextCtrl(parent, id, pos, size, style, name)
# used the scintilla programming editor for guidance
# set up for line numbers, folding and Python code highlighting
# tested with Python26 and wxPython28 by vegaseat

import  wx
import  wx.stc  as  stc
import  keyword

if wx.Platform == '__WXMSW__':
    # for windows OS
    faces = { 
        'times': 'Times New Roman',
        'mono' : 'Courier New',
        'helv' : 'Courier New',
        # temporary switch
        #'helv' : 'Arial',
        'other': 'Comic Sans MS',
        'size' : 10,
        'size2': 8,
        }
else:
    faces = { 
        'times': 'Times',
        'mono' : 'Courier',
        'helv' : 'Helvetica',
        'other': 'new century schoolbook',
        'size' : 12,
        'size2': 10,
        }

class MySTC(stc.StyledTextCtrl):
    """
    set up for folding and Python code highlighting
    """
    def __init__(self, parent):
        stc.StyledTextCtrl.__init__(self, parent, wx.ID_ANY)

        self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
        self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)

        # use Python code highlighting
        self.SetLexer(stc.STC_LEX_PYTHON)
        self.SetKeyWords(0, " ".join(keyword.kwlist))

        self.SetProperty("fold", "1")
        #self.SetProperty("tab.timmy.whinge.level", "1")
        self.SetMargins(0, 0)

        self.SetViewWhiteSpace(False)
        #self.SetBufferedDraw(False)
        #self.SetViewEOL(True)
        #self.SetEOLMode(stc.STC_EOL_CRLF)
        #self.SetUseAntiAliasing(True)
        
        self.SetEdgeMode(stc.STC_EDGE_BACKGROUND)
        self.SetEdgeColumn(78)

        # setup a margin to hold fold markers
        #self.SetFoldFlags(16)
        self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
        self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
        self.SetMarginSensitive(2, True)
        self.SetMarginWidth(2, 12)
        
        # fold markers use square headers
        self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, 
            stc.STC_MARK_BOXMINUS, "white", "#808080")
        self.MarkerDefine(stc.STC_MARKNUM_FOLDER,
            stc.STC_MARK_BOXPLUS, "white", "#808080")
        self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB,
            stc.STC_MARK_VLINE, "white", "#808080")
        self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL,
            stc.STC_MARK_LCORNER, "white", "#808080")
        self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND,
            stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
        self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID,
            stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
        self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL,
            stc.STC_MARK_TCORNER, "white", "#808080")
        
        self.Bind(stc.EVT_STC_UPDATEUI, self.onUpdateUI)
        self.Bind(stc.EVT_STC_MARGINCLICK, self.onMarginClick)
        self.Bind(wx.EVT_KEY_DOWN, self.onKeyPressed)

        # make some general styles ...
        # the lexer defines what each style is used for 

        # global default styles for all languages
        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
            "face:%(helv)s,size:%(size)d" % faces)
        # reset all to be like the default
        self.StyleClearAll()  

        # global default styles for all languages
        self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
            "face:%(helv)s,size:%(size)d" % faces)
        self.StyleSetSpec(stc.STC_STYLE_LINENUMBER,
            "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
        self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR,
            "face:%(other)s" % faces)
        self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
            "fore:#FFFFFF,back:#0000FF,bold")
        self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
            "fore:#000000,back:#FF0000,bold")

        # make the Python styles ...
        # Default 
        self.StyleSetSpec(stc.STC_P_DEFAULT,
            "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
        # Comments
        self.StyleSetSpec(stc.STC_P_COMMENTLINE,
            "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
        # Number
        self.StyleSetSpec(stc.STC_P_NUMBER,
            "fore:#007F7F,size:%(size)d" % faces)
        # String
        self.StyleSetSpec(stc.STC_P_STRING,
            "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
        # Single quoted string
        self.StyleSetSpec(stc.STC_P_CHARACTER,
            "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
        # Keyword
        self.StyleSetSpec(stc.STC_P_WORD,
            "fore:#00007F,bold,size:%(size)d" % faces)
        # Triple quotes
        self.StyleSetSpec(stc.STC_P_TRIPLE,
            "fore:#7F0000,size:%(size)d" % faces)
        # Triple double quotes
        self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE,
            "fore:#7F0000,size:%(size)d" % faces)
        # Class name definition
        self.StyleSetSpec(stc.STC_P_CLASSNAME,
            "fore:#0000FF,bold,underline,size:%(size)d" % faces)
        # Function or method name definition
        self.StyleSetSpec(stc.STC_P_DEFNAME,
            "fore:#007F7F,bold,size:%(size)d" % faces)
        # Operators
        self.StyleSetSpec(stc.STC_P_OPERATOR,
            "bold,size:%(size)d" % faces)
        # Identifiers
        self.StyleSetSpec(stc.STC_P_IDENTIFIER,
            "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
        # Comment-blocks
        self.StyleSetSpec(stc.STC_P_COMMENTBLOCK,
            "fore:#7F7F7F,size:%(size)d" % faces)
        # End of line where string is not closed
        self.StyleSetSpec(stc.STC_P_STRINGEOL,
            "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d"\
                % faces)

        self.SetCaretForeground("BLUE")
        
        # register some images for use in the AutoComplete box
        self.RegisterImage(1, 
            wx.ArtProvider.GetBitmap(wx.ART_TIP, size=(16,16)))
        self.RegisterImage(2, 
            wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
        self.RegisterImage(3, 
            wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))

    def onKeyPressed(self, event):
        if self.CallTipActive():
            self.CallTipCancel()
        key = event.GetKeyCode()
        if key == 32 and event.ControlDown():
            pos = self.GetCurrentPos()
            # tips
            if event.ShiftDown():
                self.CallTipSetBackground("yellow")
                self.CallTipShow(pos, 
                    'lots of of text: blah, blah, blah\n\n'
                    'show some suff, maybe parameters..\n\n'
                    'fubar(param1, param2)')
            # code completion
            else:
                '''
                lst = []
                for x in range(50000):
                    lst.append('%05d' % x)
                st = " ".join(lst)
                print len(st)
                self.AutoCompShow(0, st)
                '''
                kw = keyword.kwlist[:]
                kw.append("zzzzzz?2")
                kw.append("aaaaa?2")
                kw.append("__init__?3")
                kw.append("zzaaaaa?2")
                kw.append("zzbaaaa?2")
                kw.append("this_is_a_longer_value")
                #kw.append("this_is_a_much_much_longer_value")

                # Python sorts are case sensitive
                kw.sort()
                # so this needs to match  
                self.AutoCompSetIgnoreCase(False)  

                # images are specified with a appended "?type"
                for i in range(len(kw)):
                    if kw[i] in keyword.kwlist:
                        kw[i] = kw[i] + "?1"

                self.AutoCompShow(0, " ".join(kw))
        else:
            event.Skip()

    def onUpdateUI(self, evt):
        # check for matching braces
        braceAtCaret = -1
        braceOpposite = -1
        charBefore = None
        caretPos = self.GetCurrentPos()

        if caretPos > 0:
            charBefore = self.GetCharAt(caretPos - 1)
            styleBefore = self.GetStyleAt(caretPos - 1)

        # check before
        if charBefore and chr(charBefore) in "[]{}()"\
                and styleBefore == stc.STC_P_OPERATOR:
            braceAtCaret = caretPos - 1

        # check after
        if braceAtCaret < 0:
            charAfter = self.GetCharAt(caretPos)
            styleAfter = self.GetStyleAt(caretPos)

            if charAfter and chr(charAfter) in "[]{}()"\
                    and styleAfter == stc.STC_P_OPERATOR:
                braceAtCaret = caretPos

        if braceAtCaret >= 0:
            braceOpposite = self.BraceMatch(braceAtCaret)

        if braceAtCaret != -1  and braceOpposite == -1:
            self.BraceBadLight(braceAtCaret)
        else:
            self.BraceHighlight(braceAtCaret, braceOpposite)
            #pt = self.PointFromPosition(braceOpposite)
            #self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
            #print pt
            #self.Refresh(False)

    def onMarginClick(self, evt):
        # fold and unfold as needed
        if evt.GetMargin() == 2:
            if evt.GetShift() and evt.GetControl():
                self.foldAll()
            else:
                lineClicked = self.LineFromPosition(evt.GetPosition())

                if self.GetFoldLevel(lineClicked) &\
                        stc.STC_FOLDLEVELHEADERFLAG:
                    if evt.GetShift():
                        self.SetFoldexpanded(lineClicked, True)
                        self.expand(lineClicked, True, True, 1)
                    elif evt.GetControl():
                        if self.GetFoldexpanded(lineClicked):
                            self.SetFoldexpanded(lineClicked, False)
                            self.expand(lineClicked, False, True, 0)
                        else:
                            self.SetFoldexpanded(lineClicked, True)
                            self.expand(lineClicked, True, True, 100)
                    else:
                        self.ToggleFold(lineClicked)

    def foldAll(self):
        lineCount = self.GetLineCount()
        expanding = True
        # find out if folding or unfolding
        for lineNum in range(lineCount):
            if self.GetFoldLevel(lineNum) &\
                    stc.STC_FOLDLEVELHEADERFLAG:
                expanding = not self.GetFoldexpanded(lineNum)
                break;
        lineNum = 0
        while lineNum < lineCount:
            level = self.GetFoldLevel(lineNum)
            if level & stc.STC_FOLDLEVELHEADERFLAG and \
               (level & stc.STC_FOLDLEVELNUMBERMASK) ==\
                    stc.STC_FOLDLEVELBASE:
                if expanding:
                    self.SetFoldexpanded(lineNum, True)
                    lineNum = self.expand(lineNum, True)
                    lineNum = lineNum - 1
                else:
                    lastChild = self.GetLastChild(lineNum, -1)
                    self.SetFoldexpanded(lineNum, False)
                    if lastChild > lineNum:
                        self.HideLines(lineNum+1, lastChild)
            lineNum = lineNum + 1

    def expand(self, line, doexpand, force=False, visLevels=0, level=-1):
        lastChild = self.GetLastChild(line, level)
        line = line + 1
        while line <= lastChild:
            if force:
                if visLevels > 0:
                    self.ShowLines(line, line)
                else:
                    self.HideLines(line, line)
            else:
                if doexpand:
                    self.ShowLines(line, line)
            if level == -1:
                level = self.GetFoldLevel(line)
            if level & stc.STC_FOLDLEVELHEADERFLAG:
                if force:
                    if visLevels > 1:
                        self.SetFoldexpanded(line, True)
                    else:
                        self.SetFoldexpanded(line, False)
                    line = self.expand(line, doexpand, force, visLevels-1)
                else:
                    if doexpand and self.GetFoldexpanded(line):
                        line = self.expand(line, True, force, visLevels-1)
                    else:
                        line = self.expand(line, False, force, visLevels-1)
            else:
                line = line + 1;
        return line


class MyFrame(wx.Frame):
    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle, size=mysize)
        
        stc_edit = MySTC(self)
        
        # open a Python code file you have in the working folder
        # or give full path name
        py_file = "wxstc_basics1.py"
        stc_edit.SetText(open(py_file).read())
        stc_edit.EmptyUndoBuffer()
        stc_edit.Colourise(0, -1)
        
        # line numbers in the margin
        stc_edit.SetMarginType(1, stc.STC_MARGIN_NUMBER)
        stc_edit.SetMarginWidth(1, 25)


app = wx.App(0)
# create a MyFrame instance and show the frame
mytitle = 'wx.StyledTextCtrl (rightclick for menu)'
MyFrame(None, mytitle, (800, 500)).Show()
app.MainLoop()
vegaseat
DaniWeb's Hypocrite
Moderator
6,475 posts since Oct 2004
Reputation Points: 1,447
Solved Threads: 1,611
Skill Endorsements: 36

I would like to suggest to change this class little:

Add import in beginning:

import sys

and define MyFrame:

class MyFrame(wx.Frame):
    def __init__(self, parent, mytitle, mysize, filename=None):
        wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle, size=mysize)
        
        stc_edit = MySTC(self)
        
        # open a Python code file you have in the working folder
        # or give full path name
        if not filename:    self.filename=sys.argv[0]
        else:               self.filename = filename
        stc_edit.SetText(open(self.filename).read())
        stc_edit.EmptyUndoBuffer()
        stc_edit.Colourise(0, -1)
        
        # line numbers in the margin
        stc_edit.SetMarginType(1, stc.STC_MARGIN_NUMBER)
        stc_edit.SetMarginWidth(1, 25)

Then it is not sensitive to filename the program is using, and it is possible to set the filename from programme.

pyTony
pyMod
Moderator
6,306 posts since Apr 2010
Reputation Points: 879
Solved Threads: 986
Skill Endorsements: 26

@tonyjv
Kind of poor to use commandline arguments in a GUI environment. If you want to swell the code given, it would be best to use wxPython's excellent wx.FileDialog widget.

HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

It is not using command line, only prevent hard coding of programs name by reading it from argv[0] instead of literal string.

pyTony
pyMod
Moderator
6,306 posts since Apr 2010
Reputation Points: 879
Solved Threads: 986
Skill Endorsements: 26

This is just a quick example of how i use empty wx.BoxSizer() to hold spaces for borders ect. It makes the layout much easier to controll the borders, widgets ect on multiple panels as the programs i design get much bigger and more complicated. There is probably a much easier, faster and simpler way to do this, but this is the method i came up with as i dont know any other.

import wx

class SpacerExample(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, title = "Spacer example", size = (350, 370))
            panel = wx.Panel(self)

            font = wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, "Mangal")
            title = wx.StaticText(panel, label = "Border using sizers", style = wx.ALIGN_CENTRE)
            title.SetFont(font)
            
            set1text = wx.StaticText(panel, label = "Please enter something")
            set1box = wx.TextCtrl(panel)

            set2text = wx.StaticText(panel , label = "Please enter something else")
            set2box = wx.TextCtrl(panel)

            set3text = wx.StaticText(panel, label = "Please enter something else again")
            set3box = wx.TextCtrl(panel)

            save = wx.Button(panel, label = "Save")
            cancel = wx.Button(panel, label = "Cancel")

            #these are my spaces in the main column
            topspace = wx.BoxSizer()
            vertspc1 = wx.BoxSizer()
            vertspc2 = wx.BoxSizer()
            vertspc3 = wx.BoxSizer()
            vertspc4 = wx.BoxSizer()
            vertspc5 = wx.BoxSizer()
            #these spacers are my right and left borders
            hzlspc1 = wx.BoxSizer()
            hzlspc2 = wx.BoxSizer()
            #this is the space between my buttons
            hzlspc3 = wx.BoxSizer()

            buttonarr = wx.BoxSizer()
            buttonarr.Add(cancel, proportion = 3, flag = wx.EXPAND)
            buttonarr.Add(hzlspc3, proportion = 1)
            buttonarr.Add(save, proportion = 3, flag = wx.EXPAND)
            #this organises the main column of my programme
            mainsizer = wx.BoxSizer(wx.VERTICAL)
            mainsizer.Add(topspace, proportion = 1)
            mainsizer.Add(title, proportion = 4, flag = wx.EXPAND)
            mainsizer.Add(vertspc1, proportion = 1)
            mainsizer.Add(set1text, proportion = 2)
            mainsizer.Add(set1box, proportion = 2, flag = wx.EXPAND)
            mainsizer.Add(vertspc2, proportion = 2)
            mainsizer.Add(set2text, proportion = 2)
            mainsizer.Add(set2box, proportion = 2, flag = wx.EXPAND)
            mainsizer.Add(vertspc3, proportion = 2)
            mainsizer.Add(set3text, proportion = 2)
            mainsizer.Add(set3box, proportion = 2, flag = wx.EXPAND)
            mainsizer.Add(vertspc4, proportion = 2)
            mainsizer.Add(buttonarr, proportion = 2, flag = wx.EXPAND)
            mainsizer.Add(vertspc5, proportion = 2)
            #this adds the left and right border
            layout = wx.BoxSizer()
            layout.Add(hzlspc1, proportion = 1)
            layout.Add(mainsizer, proportion = 8)
            layout.Add(hzlspc2, proportion = 1)
            #this sets the sizers in action, i only need to set the top one
            panel.SetSizer(layout)
            

app = wx.App(redirect=False)
window = SpacerExample()
window.Show()
app.MainLoop()

I like to keep my code minimalistic, and i will admit this way of doing things can get hectic when multiple panels/botton arrangements are involved but this is the only way i know how to do this and get my desired results, i hope this helps and i hope someone more experienced can show you the perfect method.

Archenemie
Junior Poster
136 posts since Nov 2009
Reputation Points: 12
Solved Threads: 3
Skill Endorsements: 0

Here is example of simple wx program using functions to set common options to widgets, see http://www.daniweb.com/forums/post1374954.html#post1374954

Program is missing the final action and progress bar part, it is exercise for the reader. Not so much comments in the program, also.

import os
import wx


class MyForm(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Remote Administrator v1.0", (500,500), (425,280))

        self.font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
                            wx.FONTWEIGHT_NORMAL, 0, 'Microsoft Sans Serif')
        self.dictcomputers={
            u"Atel": [(u'PC%i' % n) for n in range(1,1+12)],
            u"Sint-Andries": [(u'PC%i' % n) for n in range(1,1+8)],
            u"Permee": [(u'PC%i' % n) for n in range(1,1+5)] }

        self.panel = wx.Panel(self, wx.ID_ANY)
        self.listcomputers = wx.ListBox(self.panel, 1, (8,16), (120, 150),
                                        [], wx.LB_MULTIPLE)
        self.listcomputers.SetBackgroundColour(wx.Colour(255, 255, 255))
        self.font_and_cursor(self.listcomputers)
        self.listcomputers.Bind(wx.EVT_LISTBOX, self.onlistcomputers)

        start = wx.Button(self.panel, -1, 'Start', (8, 176), (75, 23))
        start.Bind(wx.EVT_BUTTON, self.onStart)

        self.timer = wx.Slider(self.panel, -1, 0, 0, 10,
                               (136, 48), (104, 45),
                               wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_BOTTOM |
                               wx.SL_RIGHT | wx.SL_LABELS)
        self.timer.Bind(wx.EVT_SLIDER, self.onAdjust)
        
        label = wx.StaticText(self.panel, -1, 'Timer:', (144,32), (100, 23))
        self.font_and_cursor(label)

        radios = (self.make_radio('Shutdown', 88), self.make_radio('Logoff', 112), self.make_radio('Reboot', 136))

        self.CreateStatusBar()
        
        loc = wx.ComboBox(self.panel, -1, 'Select Location',
                          (269, 21), (121, 21), self.dictcomputers.keys())
        loc.SetBackgroundColour(wx.Colour(255, 255, 255))
        self.font_and_cursor(loc)
        loc.Bind(wx.EVT_COMBOBOX, self.onLocation)
        
        self.progressbar = wx.Gauge(self.panel, -1, 100,
                                    (264, 128), (137, 17))
        self.font_and_cursor(self.progressbar)
        self.progressbar.SetValue(0)

    def font_and_cursor(self, widget):
        widget.SetFont(self.font)
        widget.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))


    def make_radio(self, label, pos):
        Radio = wx.RadioButton(self.panel, -1, label, (136, pos), (104, 24))
        Radio.SetFont(self.font)
        Radio.SetCursor(wx.StockCursor(wx.CURSOR_DEFAULT))
        Radio.SetValue(0)
        Radio.Bind(wx.EVT_RADIOBUTTON, self.onRadio)
        return Radio

    def onLocation(self, event):
        self.location = event.GetEventObject().GetValue()
        self.Hide()
        self.Update()
        self.Refresh()
        self.Show()      
        self.SetStatusText(self.location)
        self.listcomputers.Set(self.dictcomputers[self.location])
        self.pclst = []
       
    def onlistcomputers(self, event):
        self.pclst = [event.GetEventObject().GetItems()[pc] for pc in event.GetEventObject().GetSelections()]
        self.SetStatusText("Selected Computers: %s" % ', '.join(self.pclst))
        
    def onAdjust(self, event):
        self.SetStatusText("Timer set to: %s " % (event.GetEventObject().GetValue()))

    def onRadio(self, event):
        action = event.GetEventObject().GetLabel()
        self.action = action
        self.SetStatusText("Selected " + action)
               
    def onStart(self, event):
        if event.GetEventObject().GetLabel() == "Start":
            try:
                if not self.pclst[0]:
                    raise IndexError
                message = ("Doing %s %s at %s, computer%s: %s" %
                       (self.action,
                        'in %s seconds' % self.timer.GetValue() if self.timer.GetValue() else 'immediately',
                        self.location,
                        's' if len(self.pclst)>1 else '',
                        ', '.join(self.pclst) ) )
            except AttributeError:
                self.SetStatusText("Failed starting actions")
                wx.MessageBox('Not all required fields are filled in!\nPlease correct this and try again.', 'Error')
            except IndexError:
                self.SetStatusText("Failed starting actions")
                wx.MessageBox('No PC selected!\nPlease correct this and try again.', 'Error')
            else:
                self.SetStatusText(message)


if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()
pyTony
pyMod
Moderator
6,306 posts since Apr 2010
Reputation Points: 879
Solved Threads: 986
Skill Endorsements: 26

I like personally the wx.FlexGridSizer than all the sizers.
with FlexGridSizer and the normal wx.BoxSizer you can make layouts that you realy desire.
;)

richieking
Master Poster
789 posts since Jun 2009
Reputation Points: 58
Solved Threads: 156
Skill Endorsements: 0

One way to create a rainbow effect:

# explore wxPython's
# GradientFillLinear(rect, initialColour, destColour, nDirection=EAST)

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, mytitle, mysize):
        wx.Frame.__init__(self, parent, -1, mytitle, size=mysize)
        self.SetBackgroundColour('black')
        # bind the frame to the paint event canvas
        wx.EVT_PAINT(self, self.onPaint)

    def onPaint(self, event=None):
        # the wxPython drawing canvas
        dc = wx.PaintDC(self)

        # create rainbow effect in three adjoining sections
        # section1, color gradient from red to yellow
        dc.GradientFillLinear((10, 10, 200, 100), 'red', 'yellow')
        # section2, color gradient from yellow to green
        dc.GradientFillLinear((210, 10, 200, 100), 'yellow', 'green')
        # section3, color gradient from green to blue
        dc.GradientFillLinear((410, 10, 200, 100), 'green', 'blue')


app = wx.App(0)
mytitle = "GradientFillLinear() Rainbow"
width = 630
height = 155
MyFrame(None, mytitle, (width, height)).Show()
app.MainLoop()
HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

Creating a small LED clock with wxPython:

# wxPython's wx.gizmos.LEDNumberCtrl() widget
# can be used for an LED clock

import wx
import wx.gizmos
import time

class LedClock(wx.Frame):
    """
    create an LED clock showing the current time
    """
    def __init__(self, parent=None):
        wx.Frame.__init__(self, parent, -1, title='LED Clock',
            size=(320, 100))
        # default colors are green on black
        self.led = wx.gizmos.LEDNumberCtrl(self, -1,
            style=wx.gizmos.LED_ALIGN_CENTER)
        # set up a timer
        self.timer = wx.Timer(self, -1)
        # update clock digits every second (1000ms)
        self.timer.Start(1000)
        # bind the timer to a method
        self.Bind(wx.EVT_TIMER, self.update_clock)

    def update_clock(self, event):
        # get the current time tuple from the computer
        current = time.localtime(time.time())
        # time string can have characters 0..9, -, period, or space
        ts = time.strftime("%H %M %S", current)
        self.led.SetValue(ts)


app = wx.App(0)
LedClock().Show()
app.MainLoop()
HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

A moving image can be created this way with wxPython ...

# show a moving image using a wx.ClientDC() canvas on a panel
# tested with Python27 and wxPython28  by  vegaseat

import wx

class CanvasPanel(wx.Panel):
    """ create a panel with a canvas to draw on"""
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)
        # pick a small .jpg, .png, .gif, or .bmp image file
        # you have in the working folder or give full path
        image_file = 'Duck3.jpg'
        self.bmp = wx.Bitmap(image_file)
        # initial x position of image
        self.x = 0

        # this small delay may be  needed to 
        # allow initial loading of large images
        #wx.FutureCall(50, self.create_canvas)
        # now create the canvas
        wx.EVT_SIZE(self, self.create_canvas)

        self.timer = wx.Timer(self)
        # Start(int milliseconds, oneShot=False)
        # lower timer interval gives faster speed
        self.timer.Start(30)
        # bind EVT_TIMER event to self.onTimer()
        self.Bind(wx.EVT_TIMER, self.onTimer)

    def onTimer(self, event):
        self.canvas.Clear()
        # DrawBitmap(bitmap, x, y, bool transparent)
        # x, y are upper left corner coordinates of image location
        self.canvas.DrawBitmap(self.bmp, self.x, 10, True)
        # increment x to start moving
        self.x += 1
        # optional continuous movement
        # experiment with wrap around values
        if self.x > 500:
            self.x = -250
        # print(self.x)  # test

    def create_canvas(self, event=None):
        """create the paint canvas"""
        self.canvas = wx.ClientDC(self)


app = wx.App(0)
frame = wx.Frame(None, -1, "Watch the duck move", size=(500, 400))
# will fill the frame
CanvasPanel(frame)
frame.Show(True)
app.MainLoop()
Attachments Duck3.jpg 5.97KB
vegaseat
DaniWeb's Hypocrite
Moderator
6,475 posts since Oct 2004
Reputation Points: 1,447
Solved Threads: 1,611
Skill Endorsements: 36

This seems to be a relatively easy way to create a timed alert message in your wxPython program.

The wx.SplashScreen() widget takes is message as an image file, so let's create that first ...

# create an alert image for a wx.SplashScreen() 
# and safe it to an image file eg. alert007.jpg

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent=None, id=-1, title=None):
        wx.Frame.__init__(self, parent, id, title, size=(320, 200))
        self.draw_image()
        self.save_image()

    def draw_image(self):
        # select the width and height of the blank bitmap
        # should fit the client frame
        w, h = 280, 80
        # create the blank bitmap as a draw background
        draw_bmp = wx.EmptyBitmap(w, h)
        # create the canvas on top of the draw_bmp
        canvas_dc = wx.MemoryDC(draw_bmp)
        # make the canvas yellow
        canvas_dc.SetBackground(wx.Brush('yellow'))
        canvas_dc.Clear()

        face = u'Comic Sans MS'
        font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL, False, face)
        canvas_dc.SetFont(font)
        canvas_dc.SetTextForeground('red')
        s1 = 'The host name should be superman.'
        s2 = 'Closing this window in 3 seconds ...'
        canvas_dc.DrawText(s1, x=10, y=10)
        canvas_dc.DrawText(s2, x=10, y=40)

        self.stat_bmp = wx.StaticBitmap(self)
        # now put the canvas drawing into a bitmap to 
        # display and later save it to an image file
        # (remember the canvas is on top of draw_bmp)
        self.stat_bmp.SetBitmap(draw_bmp)

    def save_image(self):
        """save the drawing that is on the bitmap"""
        finished_image = self.stat_bmp.GetBitmap()
        finished_image.SaveFile("alert007.jpg", wx.BITMAP_TYPE_JPEG)


app = wx.App(0)
MyFrame(title='canvas draw text and save').Show()
app.MainLoop()

Now we can insert the splash scrren into the program, something like this will do ...

# using a wx.SplashScreen() to splash a timed alert message

import wx
import os

class Frame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400, 300)) 
        
        host = os.system('hostname')
        if host != 'superman':
            # pick a splash image file you have in the working folder
            image_file = 'alert007.jpg'
            bmp = wx.Bitmap(image_file)
            duration = 3000  # milliseconds
            # covers the parent frame self
            wx.SplashScreen(bmp, 
                wx.SPLASH_CENTRE_ON_PARENT|wx.SPLASH_TIMEOUT,
                duration, 
                self, 
                wx.ID_ANY)            
        else:
            self.Center()
            #self.Show()
            

app = wx.App(0)
frame = Frame(None, -1, 'Splash')
# for testing
frame.Show()
app.MainLoop()
Attachments alert007.jpg 5.69KB
vegaseat
DaniWeb's Hypocrite
Moderator
6,475 posts since Oct 2004
Reputation Points: 1,447
Solved Threads: 1,611
Skill Endorsements: 36

I am experimenting with overlapping transparent images using wxPython. Here is something I came up with (used one of vegaseat's images):

# use wx.Image() to create two overlapping transparent images

import wx

class ImagePanel(wx.Panel):

    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY)

        self.parent = parent
        # pick 2 image files you have in the working folder
        # (or give the full path)
        image_file1 = 'Duck_right.jpg'
        image_file2 = 'Duck_left.jpg'
        # default is type=wx.BITMAP_TYPE_ANY
        self.image1 = wx.Image(image_file1)
        self.image2 = wx.Image(image_file2)
        # need this ...
        self.image1.InitAlpha()
        self.image2.InitAlpha()
        # call on_paint() to create the canvas
        wx.EVT_PAINT(self, self.on_paint)

    def on_paint(self, event):
        dc = wx.PaintDC(self)
        # reduces flicker
        #dc = wx.BufferedDC(dc)
        # set the canvas background color to a light grey
        dc.SetBackground(wx.Brush("#D0D0D0"))
        #dc.SetBackground(wx.Brush("white"))  # if you like
        dc.Clear()

        # adjust r g b and alpha (transparency) of image
        # AdjustChannels(fr, fg, fb, fa)
        # adjust alphas from 0.0 to 1.0 to see the effects
        alpha1 = 0.5
        alpha2 = 0.7
        if self.image1.HasAlpha(): 
            image1 = self.image1.AdjustChannels(1.0, 1.0, 1.0, alpha1)
            image2 = self.image2.AdjustChannels(1.0, 1.0, 1.0, alpha2)
        else:
            image1 = self.image1
            image2 = self.image2
            self.parent.SetTitle("no alpha")

        # required to draw images on canvas
        bmp1 = wx.BitmapFromImage(image1)
        bmp2 = wx.BitmapFromImage(image2)
        # now draw the images
        dc.DrawBitmap(bmp2, 180, 10, True)
        dc.DrawBitmap(bmp1, 20, 70, True)
        

app = wx.App(0)
mytitle = "wx.Image transparent overlapping images"
mysize = (500, 400)
frame = wx.Frame(None, wx.ID_ANY, title=mytitle, size=mysize)
ImagePanel(frame)
frame.Show(True)
app.MainLoop()
Attachments Duck_left.jpg 6.17KB Duck_right.jpg 5.97KB
bumsfeld
Nearly a Posting Virtuoso
1,495 posts since Jul 2005
Reputation Points: 409
Solved Threads: 235
Skill Endorsements: 1

Shows you how to use the Python module threading with wxPython:

# -*- coding: utf-8 -*- 

###########################################################################
## Python code partially generated with wxFormBuilder (version Apr 10 2012)
## http://www.wxformbuilder.org/
###########################################################################

import wx
import threading
import time

class MyFrame( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"Seconds Counter", 
            pos = wx.DefaultPosition, size = wx.Size( 236,173 ), 
            style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        self.SetBackgroundColour( wx.Colour( 0, 0, 255 ) )

        bSizer1 = wx.BoxSizer( wx.VERTICAL )

        self.m_textCtrl = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, 
            wx.DefaultSize, 0 )
        self.m_textCtrl.SetFont( wx.Font( 20, 74, 90, 92, False, "Comic Sans MS" ) )

        bSizer1.Add( self.m_textCtrl, 0, wx.ALL, 5 )

        self.m_button_start = wx.Button( self, wx.ID_ANY, u"Start", wx.DefaultPosition, 
            wx.DefaultSize, 0 )
        bSizer1.Add( self.m_button_start, 0, wx.ALL, 5 )

        self.m_button_stop = wx.Button( self, wx.ID_ANY, u"Stop", wx.DefaultPosition, 
            wx.DefaultSize, 0 )
        bSizer1.Add( self.m_button_stop, 0, wx.ALL, 5 )

        self.SetSizer( bSizer1 )
        self.Layout()

        # Connect Events
        self.m_button_start.Bind( wx.EVT_LEFT_DOWN, self.m_button_startOnLeftDown )
        self.m_button_stop.Bind( wx.EVT_LEFT_DOWN, self.m_button_stopOnLeftDown )

    def m_button_startOnLeftDown( self, event ):
        self.counter = Counter(0, 1, self.m_textCtrl)
        self.counter.start()
        pass

    def m_button_stopOnLeftDown( self, event ):
        count = self.counter.finish()
        print(count)  # test
        pass


class Counter(threading.Thread):
    """
    create a thread object that will do the counting in a separate thread
    """
    def __init__(self, value, increment, display_widget):
        # init the thread
        threading.Thread.__init__(self)
        # initial value
        self.value = value
        # amount to increment
        self.increment = increment
        # controls the while loop in the run command
        self.alive = False
        # display widget
        self.display = display_widget

    def run(self):
        "this will run in a separate thread"
        self.alive = True
        while self.alive:
            # delay for 1 second
            time.sleep(1)
            self.value += self.increment
            print(self.value)  # test
            self.display.SetValue(str(self.value))

    def peek(self):
        "return the current value"
        return self.value

    def finish(self):
        "close the thread, return final value"
        # stop the while loop in 'run'
        self.alive = False
        return self.value



app = wx.App(0)
# create a MyFrame instance and show the frame
frame = MyFrame(None)
frame.Center()
frame.Show()
app.MainLoop()
Lardmeister
Posting Virtuoso
1,939 posts since Mar 2007
Reputation Points: 465
Solved Threads: 72
Skill Endorsements: 5
# set up your wx application this way
# allows you to check if same app instance is already running

import wx

class MyApp(wx.App):
    def OnInit(self):
        name = "SingleApp - %s" % (wx.GetUserId())
        self.instance = wx.SingleInstanceChecker(name)
        # create a title
        mytitle = name
        if self.instance.IsAnotherRunning():
            message = "Another instance of %s is running" % mytitle
            wx.MessageBox(message, "Error")
            return False        
        self.frame = wx.Frame(parent=None, id=-1, size=(400,300), 
            pos=(150,150), title=mytitle)
        self.frame.Show()
        self.SetTopWindow(self.frame)
        return True

if __name__ == '__main__':
    # error redirection=0 to console
    app = MyApp(0)
    app.MainLoop()
HiHe
Posting Whiz
332 posts since Oct 2008
Reputation Points: 177
Solved Threads: 34
Skill Endorsements: 4

This article has been dead for over three months: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
View similar articles that have also been tagged:
 
© 2013 DaniWeb® LLC
Page rendered in 0.1330 seconds using 2.85MB