Not quite as much physics involved here, just a bouncing ball within the Tkinter canvas ...

# an animated red ball bouncing within the Tkinter canvas
# tested with Python27 and Python32

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

root = tk.Tk()
root.title("Tkinter Bouncing Ball")

w = 420
h = 300
cv = tk.Canvas(root, width=w, height=h, bg='black')
cv.pack()

# 50x50 square box for the circle boundries
x1 = 10
y1 = 50
x2 = 60
y2 = 100
# set x, y increments
dx = 2
dy = 3
# create the ball object
# give it a tag name for reference
ball = cv.create_oval(x1,y1,x2,y2,fill="red", tag='red_ball')
# endless animation loop till window corner x is clicked
while True:
    # move the ball by given increments
    cv.move('red_ball', dx, dy)
    # 15 millisecond delay
    # higher value --> slower animation
    cv.after(15)
    cv.update()
    # change direction as ball touches canvas sides
    if x2 >= w:
        dx = -2
    if y2 >= h:
        dy = -3
    if x1 < 0:
        dx = 2
    if y1 < 0:
        dy = 3
    # increment circle box boundries to detect sides touch
    x1 += dx
    y1 += dy
    x2 += dx
    y2 += dy

root.mainloop()

Illustrates the use of tag names.

Just a little Tkinter drawing fun. You can create a triangle on the Tkinter canvas by using the canvas.create_polygon() method, and then animate it with canvas.move() ...

# Tkinter animate via canvas.move(obj, xAmount, yAmount)
# object is a triangle/polygon
# tested with Python32  by  vegaseat

import time
try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

# create the main window
root = tk.Tk()
root.title("move a canvas triangle/polygon")

# create the drawing canvas
canvas = tk.Canvas(root, width=500, height=450, bg='white')
canvas.pack()

# draw a triangle using a polygon
# endpoint of polygon is same as starting point
x1 = 20
y1 = 10
x2 = 10
y2 = 20
x3 = 30
y3 = 20
triangle = canvas.create_polygon(x1, y1, x2, y2, x3, y3, fill="red")

# increments for move
y = x = 2
for k in range(200):
    time.sleep(0.025)
    # move triangle by increments x, y
    canvas.move(triangle, x, y)
    canvas.update()

# start the GUI event loop
root.mainloop()

Tired of turtles? Here some clever German educators have added advanced options to the venerable Tkinter turtle module:

# frog is a somewhat advanced turtle graphics module
# get frog-1.0.1.zip from:
# http://www.zahlenfreund.de/python/frog.html
# see also:
# http://pypi.python.org/pypi/frog/1.0.0
# unzip and copy frog.py into the Python lib/site-packages folder
# or use it in the working folder
# to make frog.py work on Python32 change line 51 to
# from PIL import ImageGrab

import frog

def draw_square(side=50):
    """
    kermit draws a square
    starts at the center of the pond
    """
    for n in range(4):
        kermit.move(side)
        kermit.turn(90)

def draw_triangle(side=50):
    """
    kermit draws a square
    """
    for n in range(3):
        kermit.move(side)
        kermit.turn(120)

# pond forms the canvas
pond = frog.Pool(width = 400, height = 400)
pond.title = "Watch Kermit move and draw"
pond.bgcolor = "lightblue"
# kermit forms the drawing pen
kermit = frog.Frog(pond)
kermit.shape = "frog"
kermit.bodycolor = "green"

draw_square(100)
# turn kermit 160 degrees
kermit.turn(180)
draw_square(100)

kermit.turn(90)
draw_triangle(100)

kermit.turn(180)
draw_triangle(100)

try:
    # use a wave sound file you have
    kermit.sing("boing.wav")
except:
    print("no soundfile")

s = "Kermit has moved a total of %0.1f pixels" % kermit.way
pen = frog.Frog(pond, visible=False)
pen.jumpto(-170, 140)
pen.color = "red"
pen.font = "Arial",8,"bold"
pen.write(s)

pond.ready()

A revisit.

Using those Tkinter tags:

# which widget has been clicked?

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

def clicked(event):
    """display the clicked oval's name"""
    # 'current' matches the item under the mouse pointer
    root.title( widget_list[cv.find_withtag('current')[0]-1] )


root = tk.Tk()
root.title('Click on ovals')

cv = tk.Canvas()
cv.pack()

oval1 = cv.create_oval(10, 30, 40, 50, fill='red', tags='click')
oval2 = cv.create_oval(50, 70, 80, 90, fill='blue', tags='click')
oval3 = cv.create_oval(90, 110, 120, 130, fill='green', tags='click')

# in order of creation
widget_list = ['oval1', 'oval2', 'oval3']

# left mouse click = '<1>'
cv.tag_bind('click', '<1>', clicked)

root.mainloop()

Not sure if this is new?

commented: different approach +15

You can also create GUI programs using the GUI toolkit that comes with Java. Java is normally installed on just about any computer. Instead of the usual Python (actually C based Python) you use Jython (Java based Python). Jython is easy to install on Windows and Unix systems. Here is a short example ...

"""jy_Table1.py
create a swing JTable widget using Jython
load it with a list of tuples

download file jython_installer-2.5.2.jar 
from http://www.jython.org/downloads.html

on Windows just double click the .jar file
and Java will install the Jython program
into a directory called jython252

to run on Windows use  Jython.bat jy_Table1.py

tested with jython2.5.2  by  vegaseat
"""

# import needed Java libraries
# swing is the Java GUI toolkit
from javax.swing import *
from java.awt import *
from javax.swing.table import DefaultTableModel

class JTableView:

    def __init__(self, data_list, header):
        frame = JFrame("Jython JTable View")
        frame.setSize(400, 150)
        frame.setLocation(100, 100)
        frame.setLayout(BorderLayout())

        # use a list of lists/tuples
        self.tableData = data_list
        colNames = header
        dataModel = DefaultTableModel(self.tableData, colNames)
        self.table = JTable(dataModel)

        scrollPane = JScrollPane()
        scrollPane.setPreferredSize(Dimension(300, 100))
        scrollPane.getViewport().setView((self.table))

        panel = JPanel()
        panel.add(scrollPane)

        frame.add(panel, BorderLayout.CENTER)
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
        frame.setVisible(True)


header = ['First Name', 'Last Name', 'Age', 'Weight']
# a list of (firstname, lastname, age, weight) tuples
data_list = [
('Mary', 'Munchki', '17', '112'),
('Heidi', 'Kalumpa', '36', '127'),
('Frank', 'Maruco', '27', '234'),
('Larry', 'Pestraus', '19', '315'),
('Serge', 'Romanowski', '59', '147'),
('Carolus', 'Arm', '94', '102'),
('Michel', 'Sargnagel', '21', '175'),
('Fred', 'Ferkel', '52', '278')
]

# test it ...
JTableView(data_list, header)
commented: nice example +12
commented: helpful +11

If you want to play around with Java based Jython, here is a simple way to test some of the widgets in the Java GUI toolkit swing ...

"""
jy_Button_test1.py
"""

# pawt will find module swing on your computer
from pawt import swing

s = 'Click me!'

# default size fits the text s, you can change it
swing_button = swing.JButton(text=s, preferredSize=(200, 20))

# a simple way to show/test the button widget
swing.test(swing_button)
"""
jy_Button_test2.py
"""

# pawt will find module swing on your computer
from pawt import swing

def click(event):
    print('Clicked!')
    swing_button.text = 'Clicked!'

s = 'Click me!'

swing_button = swing.JButton()
swing_button.text = s
swing_button.actionPerformed = click
# default size fits the text s, change it
swing_button.preferredSize = (200, 20)

# a simple way to show/test the button widget
swing.test(swing_button)
""" 
jy_List_test1.py
"""

# pawt will find module swing on your computer
from pawt import swing

text = 'Fred Ann Bob Joe Moe Zack Paul Egon Helga Jean Roger Beth' 
mylist = text.split()

swing_list = swing.JList(mylist)

# a simple way to show/test the list widget
swing.test(swing_list)
""" 
jy_List_test2.py
"""

# pawt will find module swing on your computer
from pawt import swing

text = 'Fred Ann Bob Joe Moe Zack Paul Egon Helga Jean Roger Beth' 
mylist = text.split()

# adds scrolling to the list
swing_list = swing.JScrollPane(swing.JList(mylist))

# a simple way to show/test the list widget
swing.test(swing_list)

The '99 bottles of beer' Jython code is located at:
http://www.daniweb.com/software-development/java/threads/366459

Hello all,

I have created a page of sample TKinter projects that might be of good use to anybody learning Python and Tk. Please take a look at my page, and let me know what you think of my work.

http://sites.google.com/site/pythonprojects0/

Thanks,

Tom

I show this Tkinter code because it has a nice approach to OOP (Object Oriented Programming) and some basic trigonometric calculations to make an analog clock. I added enough comments to help you along ...

# a Tkinter analog clock experiment
# modified/corrected code from: 
# http://stackoverflow.com/questions/6161816/
# tested with Python27 and Python32  by vegaseat

import time
from math import cos, sin, pi
try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

class MyApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        # the root will be self 
        tk.Tk.__init__(self, *args, **kwargs)

        # used in hand calculations
        self.size=300

        self.title("Analog Clock")
        self.cv = tk.Canvas(self, width=320, height=320, bg='yellow', 
                           relief='raised', border=10)
        self.cv.pack()

        # these will be the clock hands
        # correct lines will be drawn during update_clock()
        self.cv.create_line(0,0,0,0, fill='black', tags='hour', 
                            arrow='last')
        self.cv.create_line(0,0,0,0, fill='blue', tags='minute', 
                            arrow='last')
        self.cv.create_line(0,0,0,0, fill='red', tags='second')

        # create at least 4 hour labels
        # you could make it all 12
        tk.Label(self, text="12", bg='yellow').place(x=160, y=13)
        tk.Label(self, text="6", bg='yellow').place(x=160, y=303)
        tk.Label(self, text="3", bg='yellow').place(x=310, y=160)
        tk.Label(self, text="9", bg='yellow').place(x=11, y=160)

        # optional date/time label
        self.time_label = tk.Label(self, text="")
        self.time_label.pack()

        # get the clock updated every second
        self.update_clock()

    def update_clock(self):
        self.time_label['text'] = time.ctime()
        
        # get present time tuple
        s = time.localtime()[5]
        m = time.localtime()[4]
        h = time.localtime()[3]

        # now on to some basic sin/cos trigonometry
        # to set the line coordinates for second hand
        # moves 6 degrees per second (360/60)
        degrees = s * 6
        # angle needs to be in radians
        angle = degrees*pi*2/360
        # center coordinates cx, cy
        cx = 165
        cy = 170
        # find proper endpoint coordinates for the line
        # 0.45 gives longest hand
        x = cx + self.size*sin(angle)*0.45
        y = cy - self.size*cos(angle)*0.45
        self.cv.coords('second', (cx, cy, x, y))

        # update minute hand
        degrees1 = m * 6
        angle1 = degrees1*pi*2/360
        cx1 = 165
        cy1 = 170
        x1 = cx1 + self.size*sin(angle1)*0.4
        y1 = cy1 - self.size*cos(angle1)*0.4
        self.cv.coords('minute', (cx1, cy1, x1, y1))

        # update hour hand
        # moves 30 degrees per hour (360/12)
        degrees2 = h * 30
        angle2 = degrees2*pi*2/360
        cx2 = 165
        cy2 = 170
        x2 = cx2 + self.size*sin(angle2)*0.3
        y2 = cy2 - self.size*cos(angle2)*0.3
        self.cv.coords('hour',(cx2, cy2, x2, y2))

        # update again every 1000 ms = 1 second
        self.after(1000, self.update_clock)


app = MyApp()
app.mainloop()
commented: was looking for that +13

This would be the basic experiment to set up a functioning analog clock with the Tkinter GUI toolkit ...

# explore a Tkinter analog clock
# using Canvas(), canvas line and Spinbox()

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk
import time
import math

def click_hour():
    h = sb_hour.get()
    size = int(cv['width'])
    # get the spinbox value
    h = int(sb_hour.get())
    # set the line coordinates for hour hand
    # moves 30 degrees per hour (360/12)
    degrees = h * 30 
    # angle needs to be in radians
    angle = degrees*math.pi*2/360
    # center coordinates cx, cy
    cx = size/2
    cy = size/2
    # find proper endpoint coordinates for the line
    # multiplier of 0.32 makes hour hand shortest
    x = cx + size*math.sin(angle)*0.32
    y = cy - size*math.cos(angle)*0.32
    cv.coords('hour', (cx, cy, x, y))

def click_minute():
    size = int(cv['width'])
    # get the spinbox value
    m = int(sb_minute.get())
    # set the line coordinates for minute hand
    # moves 6 degrees per minute (360/60)
    degrees = m * 6
    # angle needs to be in radians
    angle = degrees*math.pi*2/360
    # center coordinates cx, cy
    cx = size/2
    cy = size/2
    # find proper endpoint coordinates for the line
    x = cx + size*math.sin(angle)*0.40
    y = cy - size*math.cos(angle)*0.40
    cv.coords('minute', (cx, cy, x, y))

def click_second():
    size = int(cv['width'])
    # get the spinbox value
    s = int(sb_second.get())
    # set the line coordinates for second hand
    # moves 6 degrees per second (360/60)
    degrees = s * 6
    # angle needs to be in radians
    angle = degrees*math.pi*2/360
    # center coordinates cx, cy
    cx = size/2
    cy = size/2
    # find proper endpoint coordinates for the line
    x = cx + size*math.sin(angle)*0.45
    y = cy - size*math.cos(angle)*0.45
    cv.coords('second', (cx, cy, x, y))


root = tk.Tk()
root.title("Analog clock test")

cv = tk.Canvas(root, width=320, height=320)
cv.pack()
# x1, y1, x2, y2 coordinates will be set later
cv.create_line(0,0,0,0, fill='black', tags='hour', arrow='last')
cv.create_line(0,0,0,0, fill='blue', tags='minute', arrow='last')
cv.create_line(0,0,0,0, fill='red', tags='second', arrow='last')

tk.Label(root, text='set hour:').pack(side='left', pady=5)
sb_hour = tk.Spinbox(root, from_=0, to=12, increment=1, width=4, 
                     command=click_hour)
sb_hour.pack(side='left', padx=4, pady=5)

tk.Label(root, text='set minute:').pack(side='left', pady=5)
sb_minute = tk.Spinbox(root, from_=0, to=60, increment=1, width=4, 
                       command=click_minute)
sb_minute.pack(side='left', padx=4, pady=5)

tk.Label(root, text='set second:').pack(side='left', pady=5)
sb_second = tk.Spinbox(root, from_=0, to=60, increment=1, width=4, 
                       command=click_second)
sb_second.pack(side='left', padx=4, pady=5)

# show something to start with
click_second()

root.mainloop()
commented: nice conclusion +13

Pyside is the open source PyQT GUI toolkit and follows PyQT code pretty well. If you want to explore the large number of widgets, here is one simple widget tester:

# very simple template to test PySide widgets
# used the Windows self-extracting installer
# PySide-1.0.0qt472.win32-py2.7.exe
# from:
# http://developer.qt.nokia.com/wiki/PySide_Binaries_Windows

from PySide.QtCore import *
from PySide.QtGui import *

app = QApplication([])  # no need to import sys

# ----- put your widget code here ----- 

frame = QFrame()
frame.setLineWidth(3)

# test different styles
#frame.setFrameStyle(QFrame.Box|QFrame.Sunken)
# or
frame.setFrameStyle(QFrame.Box|QFrame.Raised)

frame.show()

# ----- end of widget code -----

app.exec_()
commented: helpful stuff +15

Hey Henri, very nice widget tester for Pyside (for PyQt change imports). I just wanted to know if the list box would add a scroll-bar automatically for a long list. It does ...

# test PySide widgets
# load a list box

from PySide.QtCore import *
from PySide.QtGui import *

app = QApplication([])

# ----- start your widget test code ----

# Fnames.txt is a file of names, one each line
with open("Fnames.txt", "r") as fin:
    # remove trailing newline characters
    name_list = [name.strip() for name in fin]

# automatically adds vertical scrollbar for this long list
listbox = QListWidget()
listbox.addItems(name_list)

listbox.show()

# ---- end of widget test code -----

app.exec_()

Some more explorations with Jython ...

"""
view an image with Jython using the Java swing GUI toolkit
get the image from a webpage URL or any image file
tested with jython2.5.2  by  vegaseat
"""

from pawt import swing
from java import net

def view_image(image):
    frame = swing.JFrame("Jython Image Viewer") 
    # allows frame corner x to exit properly
    frame.defaultCloseOperation = swing.JFrame.EXIT_ON_CLOSE
    frame.visible = True
    frame.setSize(500, 688)
    # show the image in a label
    frame.getContentPane().add(swing.JLabel(swing.ImageIcon(image)))
    frame.show()

# get a URL based image from the internet
# the url was very long so I split it in half
part1 = "http://uploads.neatorama.com/wp-content/"
part2 = "uploads/2011/05/cogtrain-500x688.jpg"
url = part1 + part2
# now that is sweet ...
image = net.URL(url)
view_image(image)

I coded the above Jython Image Viewer program with Python27 and PyQt, a little bit more complex ...

"""
view an image with Python using the PyQt GUI toolkit
get the image from a webpage URL or any image file

note: urllib2 has changed in Python3

tested with Python27 and PyQt48
"""

from PyQt4.QtCore import *
from PyQt4.QtGui import *
# Python2
import urllib2

app = QApplication([])
# create the window/frame
win = QWidget()
win.setGeometry(100, 50, 500, 688)
win.setWindowTitle("PyQt Image Viewer")

# get a URL based image from the internet
# the url was very long so I split it in half
part1 = "http://uploads.neatorama.com/wp-content/"
part2 = "uploads/2011/05/cogtrain-500x688.jpg"
url = part1 + part2
picture = urllib2.build_opener().open(url).read()

# save the image as a file
fname = "cogtrain-500x688.jpg"
fout = open(fname, "wb")
fout.write(picture)
fout.close()

# load the picture back in a form PyQt can process
image = QPixmap(fname)

# use a label to display the image in
label = QLabel(win)
label.setPixmap(image)

win.show()

app.exec_()

To allow for comparisons, here is the URL image viewer using Tkinter and PIL ...

"""
view an image with Python using the Tkinter GUI toolkit
get the image from a webpage URL

note: urllib2 has changed in Python3

tested with Python 2.7 and PIL 1.1.7
"""

import Tkinter as tk
from PIL import ImageTk
# Python2
import urllib2

root = tk.Tk()
root.title("Tkinter URL Image Viewer")

# get a URL based image from the internet
# the url was very long so I split it in half
part1 = "http://uploads.neatorama.com/wp-content/"
part2 = "uploads/2011/05/cogtrain-500x688.jpg"
url = part1 + part2
picture = urllib2.build_opener().open(url).read()

# use PIL to convert to a format Tkinter can handle
image_tk = ImageTk.PhotoImage(data=picture)

# put the image on a typical widget
label = tk.Label(root, image=image_tk)
label.pack(padx=5, pady=5)

root.mainloop()
commented: great code, thank you +8

The popular plotting module matplotlib works very well within Tkinter ...

"""
embedding module matplotlib in a Tkinter GUI application
tested with Python 2.7 and matplotlib 1.0.1
"""

import matplotlib
matplotlib.use('TkAgg')

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import math
import Tkinter as tk

root = tk.Tk()
root.wm_title("Embedding matplotlib in Tkinter")


fig = Figure(figsize=(6, 5), dpi=100)
myplot = fig.add_subplot(111)

# brew up a simple sample plot
# create a list of floating point numbers
# this will be the x-axis data
float_list = [x/100.0 for x in range(300)]
# now create a list of sine values
# this will be the y-axis data
sine_list = [math.sin(2*math.pi*y) for y in float_list]
# optional labels
myplot.set_xlabel('x')
myplot.set_ylabel('y = sin(x)')
# then plot the two list's data in red
myplot.plot(float_list, sine_list, 'r')


# create a tk.DrawingArea
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.show()
canvas.get_tk_widget().pack(side='top', fill='both', expand=1)

toolbar = NavigationToolbar2TkAgg( canvas, root )
toolbar.update()
canvas._tkcanvas.pack(side='top', fill='both', expand=1)

root.mainloop()
commented: thanks +13

Since we are talking about plotting, often overlooked is VPython, that has quite a nice plotting feature. It is fairly simple to use, here is an example ...

""" vp_plot_bars1.py

use VPython to draw a bar chart

module visual (aka VPython) comes in Windows, Linux and Mac flavors

Windows download website:
http://vpython.org/contents/download_windows.html
pick the download for your version of Python
I used installer VPython-Win-Py2.7-5.41.exe
"""

import visual.graph as vg

# set up the plot display
# if xmax, xmin, ymax, ymin are not specified, 
# then the default is auto scale
myplot = vg.gdisplay(x=80, y=50, width=680, height=350,
    title = 'widgets sold each day',
    xtitle='day', 
    ytitle='widgets sold',
    foreground=vg.color.black,
    background=vg.color.white)

draw_bars = vg.gvbars(delta=0.5, color=vg.color.red)

# list of data to be graphed
data = [30, 45, 80, 150, 220, 180, 110, 75, 50, 35, 20, 15, 10, 10]

for day, units in enumerate(data):
    draw_bars.plot(pos=(day+1, units))

You can use the Tkinter Entry() widget to enter a valid function_of_x string, evaluate it with eval(), and then plot it with VPython. Here is an example ...

"""tk_vp_plotting.py
using Tkinter to get the function of x input for a VPython plot
(console raw_input() does not work with VPython)
you can plot several functions, hence the random curve colors 
tested with Python27  by  vegaseat
"""

import Tkinter as tk
import visual.graph as vg
import random
from math import *

class MyApp(tk.Tk):
    def __init__(self, prompt):
        # the root will be self
        tk.Tk.__init__(self)
        self.title("Tkinter plotting with VPython")
        # set tk window x, y position below visual window
        self.geometry("+15+420")
        self.prompt = prompt
        self.v = tk.StringVar()
        # set some initial functionx string
        self.v.set("cos(x)")
        self.createWidgets()
        
    def visual_plot(self):
        # optionally make curve color random
        color_list = [vg.color.cyan, vg.color.yellow, vg.color.green]
        curve_color = random.choice(color_list)
        curve = vg.gcurve(color=curve_color)
        for x, fx in self.plot_data:
            curve.plot(pos=(x, fx))
    
    def get_data(self, functionx):
        plot_data = []
        # create a range of x values from 0 to 9 in steps of 0.1
        # this might have to be changed via user entry
        for x in vg.arange(0, 9.1, 0.1):
            # evaluate string function of x
            fx = eval(functionx)
            #print(x, fx)  # test
            plot_data.append((x, fx))
        return plot_data
    
    def createWidgets(self):
        self.label = tk.Label(self, text=self.prompt)
        self.label.grid(row=0, column=0, padx=10, pady=1)
        self.enter = tk.Entry(self, textvariable=self.v, bg='yellow')
        self.enter.grid(row=1, column=0, padx=10, pady=1)
        self.button = tk.Button(self, text="plot the function of x",
            command=self.action)
        self.button.grid(row=2, column=0, padx=10, pady=1)

    def action(self):
        # function of x string from entry widget
        functionx = self.v.get()
        self.plot_data = self.get_data(functionx)
        self.visual_plot()
        #self['bg'] = 'green'  # test


prompt = """\
Please input a valid mathematical function of x
like 
sin(2*x) * exp(0.5*x)
or
sqrt(x) + pi"""

app = MyApp(prompt)
app.mainloop()
commented: without threading too +12

PyQt, or in this case PySide, allows you to look at a given web page via PySide.QtWebKit.QWebView() ...

# PySide is the official LGPL-licensed version of PyQT
# You can download and use the Windows self-extracting installer
# PySide-1.0.0qt472.win32-py2.7.exe
# from: http://developer.qt.nokia.com/wiki/PySide_Binaries_Windows
# modified example from:
# http://www.pyside.org/docs/pyside/PySide/QtWebKit/
# tested with pyside472 and Python27
 
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import *
 
# create a Qt application
app = QApplication([])

# create a PySide.QtWebKit.QWebView() to display a web page
# (your computer needs to be connected to the internet)
view = QWebView()
url = "http://qt.nokia.com/"
view.load(QUrl(url))
view.show()

# run the application event loop
app.exec_()

What about an example of using the webbrowser as the frontend? I use some pen-testing suites that use html as the GUI.

Here is an example, kind of ugly since it is just to demonstrate what you can do.
Also, I am no web developer so the html was mostly pulled from w3schools.com.

Example:

import socket, webbrowser
#setup our socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#set socket to reuse address, if you don't you will eventually get
#socket errors with repetitive access
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
#bind socket to localhost and port 44444
s.bind(('',44444))


#I am not a web developer and most of this was from
#w3schools.com
page = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>

<h1>GUI via web page</h1>

<p>Some examples of using html for a GUI</p>

<ol>
<li>Element 1</li>
<li>Element 2</li>
<li>So on..</li>
<li>And so on.</li>
</ol>


<form name="input" action="html_form_action.asp" method="get">
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" /><br />

Password: <input type="password" name="pwd" /><br />

<input type="radio" name="sex" value="male" /> Male<br />
<input type="radio" name="sex" value="female" /> Female<br />

<input type="checkbox" name="vehicle" value="Bike" /> I have a bike<br />
<input type="checkbox" name="vehicle" value="Car" /> I have a car<br />

Username: <input type="text" name="user" /><br />

<input type="submit" value="Submit" />
</form>

</body>

</html>"""

car_page = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<body>

<h1>
Car
</h1>

<p>
I have a car too, it is a Scion tC!
</p>

</body>

</html>
"""

bike_page = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<body>

<h1>
Bike
</h1>

<p>
I don't have a bike....
</p>

</body>

</html>
"""

loggedin_page = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>

<body>

<h1>
Logged in
</h1>

<p>
You are now logged in, welcome.
</p>

</body>

</html>
"""

started = 0

while 1:
    #listen for connection
    s.listen(1)
    #check an see if this is the first time running
    #if so, open the default browser to our server
    #not needed, added for convince 
    if started == 0:
        webbrowser.open_new("http://localhost:44444")
        started = 1
    else:
        #accept connection and create objects to handle it
        conn, addr = s.accept()
        #get data from browser
        data = conn.recv(10000)
        print data
        #check and see if the browser POSTed data to us
        if "html_form_action.asp?" in data:
            #look for stuff from forms and send appropreate page
            if "Bike" in data:
                conn.send(bike_page)
            elif "Car" in data:
                conn.send(car_page)
            else:
                conn.send(loggedin_page)
        else:
            conn.send(page)
        #close connection so we can get more data if sent
        conn.close()

PySide is out for Python32, here is a little test program ...

# explore multiple QFrame() in a QGridLayout()
# also change the color of the frames
# tested with PySide 474 and Python32

from PySide.QtCore import *
from PySide.QtGui import *

class FrameTester(QWidget):
    def __init__(self, title, width, height, parent=None):
        # create the window (this will be instance self)
        QWidget.__init__(self, parent)
        # setGeometry(x_pos, y_pos, width, height)
        self.setGeometry(100, 150, width, height)
        self.setWindowTitle(title)
        self.make_frame()
    
    def make_frame(self):
        self.frame1 = QFrame(self)
        self.frame1.setLineWidth(3)
        self.frame1.setFrameStyle(QFrame.Box|QFrame.Sunken)
        
        self.frame2 = QFrame(self)
        self.frame2.setLineWidth(3)
        self.frame2.setFrameStyle(QFrame.Box|QFrame.Sunken)        

        self.frame3 = QFrame(self)
        self.frame3.setLineWidth(3)
        self.frame3.setFrameStyle(QFrame.Box|QFrame.Sunken)
        
        grid = QGridLayout()
        grid.setSpacing(10)
        # addWidget(QWidget, row, column, rowSpan, columnSpan)
        # span 2 rows and 1 column each
        grid.addWidget(self.frame1, 1, 1, 2, 1)
        grid.addWidget(self.frame2, 1, 2, 2, 1)
        # span 1 row and 2 columns
        # note that you occupy row 3 now
        grid.addWidget(self.frame3, 3, 1, 1, 2)
       
        self.setLayout(grid)
        
        # put a button on frame1
        self.button = QPushButton("Change colors", self.frame1)
        self.button.resize(150, 30)  # alternate size
        self.button.move(20, 20)
        # bind the button click
        self.button.clicked.connect(self.changeFrameColor)
        
    def changeFrameColor(self):
        # color is a string in #RRGGBB format
        red = "#ff0000"
        blue = "#0000ff"
        yellow = "#ffff00"        
        style_str = "QFrame {background-color: %s}"            
        # use style sheet to set background colors of frames
        self.frame1.setStyleSheet(style_str % yellow)
        self.frame2.setStyleSheet(style_str % red)
        self.frame3.setStyleSheet(style_str % blue)        

# create the Qt Application
app = QApplication([])

title = "3 frames in a grid layout"
width = 800
height = 600
tester = FrameTester(title, width, height)
tester.show()

# run the main Qt event loop
app.exec_()

A test code for a PySide button with an image and text next to it:

# test PySide widgets
# button with image and text

from PySide.QtCore import *
from PySide.QtGui import *

app = QApplication([])

# ----- start your widget test code ----

# the image file can be a .jpg, .png, ,gif, .bmp image file
# if not in the working directory, give the full path
image_file = "down.gif"
image = QPixmap(image_file)

text = "my down arrow"
# put an image and a text on the button
button = QPushButton(image, text)
button.show()

# ---- end of widget test code -----

app.exec_()

This shows you how simple it is to use PySide to display an image:

# test PySide widgets
# label with an image on it

from PySide.QtCore import *
from PySide.QtGui import *

app = QApplication([])

# ----- start your widget test code ----

# the image file can be a .jpg, .png, ,gif, .bmp image file
# if not in the working directory, give the full path
image_file = "PorscheBoxster.jpg"
image = QPixmap(image_file)

label = QLabel()
label.setPixmap(image)
label.show()

# ---- end of widget test code -----

app.exec_()

Just playing around with PySide and the QT Designer. The example is a popular program that matches words with words on a list as you type. Rewritten using the Designer's XML .ui file and a Python ui-loader program:

'''
run_ps_listview_match2.py

example using PySide's QListView and QAbstractListModel
to match a partially typed word to words in a list

the visible GUI part was generated with PySide's Designer
the Designer's XML file was saved as "ps_listview_match2.ui"

it contains a QWidget form with a QLabel, a QLineEdit and
a QListView stacked into a QVBoxLayout()

this program is a simple loader for the .ui XML file and also
does the connection of the widget's signals

PySide is the official LGPL-licensed version of PyQT
I downloaded the 32 bit version for Python 2.7 from:
http://qt-project.org/wiki/PySide_Binaries_Windows
The Windows self installer is called:
PySide-1.1.0qt474.win32-py2.7.exe
this also installs the Designer program
'''


from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtUiTools import QUiLoader

class MyWindow():
    def __init__(self, words, *args):
        # create the ui loader
        loader = QUiLoader()
        # and load the form's ui file created by Designer
        self.widget = loader.load("ps_listview_match2.ui")
        self.widget.show()

        # create the label, edit and list objects
        # (for correct names check the .ui file)
        self.label = self.widget.findChild(QLabel, 'label')
        self.edit = self.widget.findChild(QLineEdit, 'lineEdit')
        self.lview = self.widget.findChild(QListView, 'listView')

        # create model objects
        # words is a list of words
        self.lmodel = MyListModel(self.widget, words)
        self.lview.setModel(self.lmodel)

        self.words = words

        # act on the key pressed in edit
        self.widget.connect(self.edit,
            SIGNAL("textChanged(QString)"),
            self.update)

    def update(self):
        """
        updates the list of possible completions each time key
        is pressed, use lower() to make things case insensitive
        """
        p = str(self.edit.text()).lower()
        new_list = [w for w in self.words if w.lower().find(p)==0]
        self.lmodel.setAllData(new_list)


class MyListModel(QAbstractListModel):
    def __init__(self, parent, words, *args):
        QAbstractListModel.__init__(self, parent, *args)
        # words is a list of words
        self.words = words

    def rowCount(self, parent=QModelIndex()):
        return len(self.words)

    def data(self, index, role):
        if index.isValid() and role == Qt.DisplayRole:
            return self.words[index.row()]
        else:
            return None

    def setAllData(self, new_list):
        """replace old list with new list"""
        self.words = new_list
        self.reset()


# just a test list of words
state_list = [
'Mississippi', 'Oklahoma', 'Delaware', 'Minnesota',
'Arkansas', 'New Mexico', 'Indiana', 'Louisiana',
'Texas', 'Wisconsin', 'Kansas', 'Connecticut',
'California', 'West Virginia', 'Georgia', 'North Dakota',
'Pennsylvania', 'Alaska', 'Missouri', 'South Dakota',
'Colorado', 'New Jersey', 'Washington', 'New York',
'Nevada', 'Maryland', 'Idaho', 'Wyoming', 'Maine',
'Arizona', 'Iowa', 'Michigan', 'Utah', 'Illinois',
'Virginia', 'Oregon', 'Montana', 'New Hampshire',
'Massachusetts', 'South Carolina', 'Vermont', 'Florida',
'Hawaii', 'Kentucky', 'Rhode Island', 'Nebraska',
'Ohio', 'Alabama', 'North Carolina', 'Tennessee'
]

app = QApplication([])
win = MyWindow(state_list)
# run the application event loop
app.exec_()

For those of you who are curious, here is the XML code file "ps_listview_match2.ui" the Designer generated:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Match words with a list</string>
  </property>
  <widget class="QWidget" name="verticalLayoutWidget">
   <property name="geometry">
    <rect>
     <x>9</x>
     <y>9</y>
     <width>361</width>
     <height>281</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QLabel" name="label">
      <property name="text">
       <string>Start typing to match words in list:</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLineEdit" name="lineEdit"/>
    </item>
    <item>
     <widget class="QListView" name="listView"/>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

Select multiple items from a Tkinter list box:

# a simple Tkinter Listbox example
# press the shift or ctrl key to select multiple items

try:
    # for Python2
    import Tkinter as tk
except ImportError:
    # for Python3
    import tkinter as tk


def get_list():
    """
    function to read the listbox selection(s)
    (mutliple lines can be selected)
    and put the result(s) in a label
    """
    # tuple of line index(es)
    sel = listbox.curselection()
    # get the text, might be multi-line
    seltext = '\n'.join([listbox.get(x) for x in sel])
    label_text.set(seltext)

root = tk.Tk()
# used for label text
label_text = tk.StringVar(root)

# extended mode allows CTRL or SHIFT mouse selections
listbox = tk.Listbox(root, selectmode=tk.EXTENDED)
listbox.pack()

# click the button to show the selection(s)
button = tk.Button(root, text="Get Selection(s)", command=get_list)
button.pack()

# used to display selection(s)
label = tk.Label(root, textvariable=label_text)
label.pack()

# load some datalines into the listbox
items = ["one", "two", "three", "four", "five", "six"]
for item in items:
    listbox.insert(tk.END, item)

# highlight/preselect line 3 of listbox (starts with zero)
# lb.selection_set(first, last=None) can preselect more than 1 line
listbox.selection_set(3)

root.mainloop()

Thanks for sharing, only how listbox(3) chooses third if the lines are numbered 0 based as per comment?

You can use PyQT or PySide to do a similar thing:

# explore the PyQT or PySide QListWidget

from PySide.QtCore import *
from PySide.QtGui import *

class MyWindow(QWidget):
    def __init__(self, title, width, height, parent=None):
        # create the window (this will be instance self)
        QWidget.__init__(self, parent)
        # setGeometry(x_pos, y_pos, width, height)
        self.setGeometry(100, 150, width, height)
        self.setWindowTitle(title)

        # create a test list of characters 'a' to 'z'
        test_list = [chr(p) for p in range(0x0061,  0x007b)]
        # create the listbox and position and size it
        self.listbox = QListWidget(self)
        self.listbox.setGeometry(20, 10, 200, 200)
        # load the listbox with the test list
        # automatically adds vertical scrollbar if list is long
        self.listbox.addItems(test_list)
        # now show the listbox
        self.listbox.show()
        # new connect style, needs PyQt 4.5+
        self.listbox.clicked.connect(self.on_select)

    def on_select(self):
        """an item in the listbox has been clicked/selected"""
        selected_item = self.listbox.currentItem().text()
        self.setWindowTitle(selected_item)


# create the Qt Application
app = QApplication([])

title = "select listbox item"
width = 240
height = 220
window = MyWindow(title, width, height)
window.show()

# run the main Qt event loop
app.exec_()

Tkinter is still refreshingly simple to use:

# display GMT time with Tkinter

import time
try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

def update_gmt():
    gmt_string.set(time.strftime("%H:%M:%S", time.gmtime()))
    # update every second recursively
    app.after(1000, update_gmt)

def main():
    myfont = ('times', 48, 'bold')
    gmt_label = tk.Label(app, textvariable=gmt_string,
        font=myfont, fg='red', bg='yellow')
    gmt_label.grid()
    update_gmt()

app = tk.Tk()
app.title("GMT")

gmt_string = tk.StringVar()

main()

app.mainloop()

Nice, only to correct after call comment, that is not recursive call, as after setting the timed call the function exits and function is not running until the timer fires the scheduled call.

So, I would call it scheduled call.

A little more involved, and shows how to draw lines on an image with the mouse pointer. The picture is in an earlier post if you want to use it.

'''ps_image_drawlines1.py
draw lines across an image

PySide is the official LGPL-licensed version of PyQT
downloaded and used the Windows self-extracting installer
PySide-1.1.0qt474.win32-py2.7.exe
from: http://developer.qt.nokia.com/wiki/PySide_Binaries_Windows
tested with pyside474 and Python27
'''

from PySide.QtCore import *
from PySide.QtGui import *

class MyQGraphicsView(QGraphicsView):
    def __init__(self,scene, parent=None):
        super(MyQGraphicsView, self).__init__(scene, parent=parent)
        self.parent = parent
        self.scene  = scene
        self.startPunkt = None
        self.endPunkt = None

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
          self.endPunkt = event.pos()
          self.paintme()

    def mousePressEvent(self, event):
        if (event.buttons() & Qt.LeftButton):
          self.startPunkt = event.pos()

    def paintme(self):
        if self.endPunkt and self.startPunkt:
            pen = QPen()
            # set pen color
            pen.setColor(Qt.yellow)
            self.startPunkt = self.mapToScene(QPoint(self.startPunkt.x(),
                self.startPunkt.y()))
            self.endPunkt = self.mapToScene(QPoint(self.endPunkt.x(),
                self.endPunkt.y()))
            self.scene.addLine(self.startPunkt.x(),self.startPunkt.y(),
                self.endPunkt.x(),self.endPunkt.y(),pen)
            self.startPunkt = None
            self.endPunkt = None


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle('draw lines on an image (click/drag pointer)')
        # setGeometry(x_pos, y_pos, width, height)
        self.setGeometry(100, 100, 800, 500)
        self.setup_ui()
        self.show()

    def setup_ui(self):
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, 800, 500)

        loaded_image = QImage()
        # pick an image file you have in the working folder or give full path
        image_file = "PorscheBoxster.jpg"
        load_error = "%s not found!" % image_file
        if not loaded_image.load(image_file):
            self.setWindowTitle(load_error)
        self.image = loaded_image
        self.scene.addPixmap(QPixmap.fromImage(self.image))

        self.view = MyQGraphicsView(self.scene, self)
        self.setCentralWidget(self.view)

    def paintEvent(self, event):
        self.view.paintme()


app = QApplication([])
win = MainWindow()
app.exec_()

A little pygame code to show you how to create the effect of soap bubbles floating:

'''pg_Bubbles1.py
make bubble circles float up the screen

exploring the Python module pygame
pygame free from: http://www.pygame.org/
or: http://www.lfd.uci.edu/~gohlke/pythonlibs/
pygame is available for Python27 or Python32
'''

import pygame as pg
import random

def draw(screen, background, width, height):
    # create a few random values
    x = random.randint(10, width)
    y = random.randint(100, height)
    radius = random.randint(20, 50)
    # random (r, g, b) color, avoid black (0, 0, 0)
    r = random.randint(20, 255)
    g = random.randint(20, 255)
    b = random.randint(20, 255)
    # bubble up until circle center (x, y) reaches top
    while y > 0:
        background.fill(pg.color.Color('black'))
        # draw.circle(Surface, color, pos, radius, width)
        # width of 0 (default) fills the circle
        pg.draw.circle(background, (r, g, b), (x, y), radius, 3)
        y -= 1
        # put the circle on the screen
        screen.blit(background, (0, 0))
        # update screen
        pg.display.flip()

def main():
    pg.init()
    # create the pg window, give it a caption and bg color
    width = 680
    height = 460
    screen = pg.display.set_mode((width, height))
    pg.display.set_caption(' random bubbles')
    background = pg.Surface(screen.get_size())
    background.fill(pg.color.Color('black'))
    clock = pg.time.Clock()
    # the pg event loop ...
    while True:
        # quit when window corner x is clicked
        # there is a small delay
        for event in pg.event.get():
            if event.type == pg.QUIT:
                raise SystemExit
        draw(screen, background, width, height)
        # use a frame rate of 30 to avoid flickering
        clock.tick(30)
    pg.quit()

if __name__ == "__main__":
    main()
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.