1

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.

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()

Edited by pyTony: n/a

2

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.
;)

2

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()
Votes + Comments
nice approach
2

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()
3

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()

Edited by vegaseat: attach image

Votes + Comments
works very well
nice find
Attachments Duck3.jpg 5.97 KB
1

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()

Edited by vegaseat: new

Attachments alert007.jpg 5.69 KB
1

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.17 KB Duck_right.jpg 5.97 KB
0

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()
0
# 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()
0

Yes, project Phoenix does rewrite all the wxPython code to make it work with Python2 and Python3.

For old time sake, some fun with colors:

# color a wxPython panel every 2.5 seconds with a random color

import wx
import random
from wx.lib.colourdb import *

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(600, 450))

        self.panel = wx.Panel(self, -1)
        # create a list of wx colors (from wx.lib.colourdb)
        self.colors = getColourList()
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        # milliseconds
        self.timer.Start(2500)
        self.Center()

    def OnTimer(self, event):
        self.panel.SetBackgroundColour(wx.RED)
        # pick a random color from the list
        color = random.choice(self.colors)
        self.panel.SetBackgroundColour(color)
        self.panel.Refresh()
        self.SetTitle(color)


app = wx.App(0)
# contains all the wx color names (from wx.lib.colourdb)
updateColourDB()
# create the frame instance
frame = MyFrame(None, -1, 'randomcolours.py')
frame.Show(True)
app.SetTopWindow(frame)
app.MainLoop()
0

here is a sample of basic combo box code that prints the chioice selected by the user:

import wx

########################################################################
class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
        panel = wx.Panel(self, wx.ID_ANY)

        self.ct = 0
        self.phaseSelection = ""
        self.opSelection = ""
        self.instSelection = ""
        self.orgSelection = ""

        phasesList = ["preOperations", "inOperations", "postOperations"]

        self.combo = wx.ComboBox(panel, choices=phasesList)
        self.combo.Bind(wx.EVT_COMBOBOX, self.onCombo)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.combo)
        panel.SetSizer(sizer)

    #----------------------------------------------------------------------
    def onCombo(self, event):
        """
        """
        self.phaseSelection = self.combo.GetValue()
        print self.phaseSelection

#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()
0

The Phoenix project has now gone to using the wheel approach.
A wheel is a ZIP-format archive with a specially formatted filename and the .whl extension.

Edited by HiHe

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.