Example PPEGui TourGridgridpy

# 2d table of input fields from Tkinter import *

rows = [] for i in range(5): cols = [] for j in range(4):

e = Entry(relief=RIDGE) e.grid(row=i, column=j, sticky=NSEW) e.insert(END, '%d.%d' % (i, j)) cols.append(e) rows.append(cols)

def onPress():

for row in rows:

for col in row:

print col.get(), print

Button(text='Fetch', command=onPress).grid() mainloop()

When run, this script creates the window in Figure 8-31, and saves away all the grid's entry field widgets in a two-dimensional list of lists. When its Fetch button is pressed, the script steps through the saved list of lists of entry widgets, to fetch and display all the current values in the grid. Here is the output of two Fetch presses -one before I made input field changes, and one after:

C:\...\PP2E\Gui\Tour\Grid>python grid5.py

Figure 8-31. A larger grid of input fields

*

JTTrl y\

|ac

01

CM >—<

l.D

1.1

I 2

¿3

2.0

2?.

10

31

32

A.'i

VI

■1 2

id

Fetch |

Now that we know how to build and step through arrays of input fields, let's add a few more useful buttons. Example 8-24 adds another row to display column sums, and buttons to clear all fields to zero and calculate column sums.

Example 8-24. PP2E\Gui\Tour\Grid\grid5b.py

# add column sums, clearing from Tkinter import *

for j in range(numcol):

e = Entry(relief=RIDGE) e.grid(row=i, column=j, sticky=NSEW) e.insert(END, '%d.%d' % (i, j)) cols.append(e) rows.append(cols)

for i in range(numcol):

l = Label(text='?', relief=SUNKEN) l.grid(row=numrow, col=i, sticky=NSEW) sums.append(l)

def onPrint():

for row in rows:

for col in row:

print col.get(), print print def onSum():

for j in range(numrow):

t[i]= t[i] + eval(rows[j][i].get()) for i in range(numcol):

def onClear():

for row in rows:

for col in row:

col.delete('0', END) col.insert(END, '0.0') for sum in sums:

import sys

Button(text='Sum',

Button(text='Print',

Button(text='Clear',

Button(text='Quit', mainloop()

command=onSum).grid(row=numrow+1, column=0) command=onPrint).grid(row=numrow+1, column=1) command=onClear).grid(row=numrow+1, column=2) command=sys.exit).grid(row=numrow+1, column=3)

Figure 8-32 shows this script at work summing up four columns of numbers; to get a different size table, change the numrow and numcol variables at the top of the script.

Figure 8-32. Adding column sums

tk

Mill

|ao

01

_JQZ

|[QL3

1.0

1.1

I 2

1.3

2D

71

13

?0

31

32

3.3

s.O

+.1

4.2

-1.3

1D.0

1

1 OL 5

1

no

1

11 5

Sunn 1

Prrt I

ÛCDf 1

frur 1

And finally, Example 8-25 is one last extension that is coded as a class for reusability, and adds a button to load the table from a data file. Data files are assumed to be coded as one line per row, with whitespace (spaces or tabs) between each column within a row line. Loading a file of data automatically resizes the table GUI to accommodate the number of columns in the table.

Example 8-25. PP2E\Gui\Tour\Grid\grid5c.py

# recode as an embeddable class from Tkinter import *

from PP2E.Gui.Tour.quitter import Quitter # reuse, pack, and grid class SumGrid(Frame):

def init (self, parent=None, numrow: Frame. init (self, parent) self.numrow = numrow container self.numcol = numcol grids me self.makeWidgets(numrow, numcol)

one way

# caller packs or

# else only usable def makeWidgets(self, numrow, numcol): self.rows = [] for i in range(numrow): cols = []

for j in range(numcol):

e = Entry(self, relief=RIDGE) e.grid(row=i+1, column=j, sticky=NSEW) e.insert(END, '%d.%d' % (i, j)) cols.append(e) self.rows.append(cols)

for i in range(numcol):

l = Label(self, text='?', relief=SUNKEN) l.grid(row=numrow+1, col=i, sticky=NSEW) self.sums.append(l)

Button(self, text='Sum', command=self.onSum).grid(row=0, column=0)

Button(self, text='Print', command=self.onPrint).grid(row=0, column=1)

Button(self, text='Clear', command=self.onClear).grid(row=0, column=2)

Button(self, text='Load', command=self.onLoad).grid(row=0, column=3)

Quitter(self).pack()

def onPrint(self):

for row in self.rows: for col in row:

print col.get(), print print def onSum(self):

for j in range(self.numrow):

t[i]= t[i] + eval(self.rows[j][i].get()) for i in range(self.numcol):

def onClear(self):

for row in self.rows: for col in row:

Quitter(self).grid(row=0, column=4) # fails:

for sum in self.sums:

def onLoad(self): import string from tkFileDialog import * file = askopenfilename() if file:

for r in self.rows:

for c in r: c.grid forget() for s in self.sums: s.grid forget() filelines = open(file, 'r').readlines() self.numrow = len(filelines)

self.numcol = len(string.split(filelines[0])) self.makeWidgets(self.numrow, self.numcol) row = 0

for line in filelines:

fields = string.split(line) for col in range(self.numcol):

self.rows[row][col].delete('0', END) self.rows[row][col].insert(END, fields[col]) row = row+1

SumGrid(root).pack() # .grid() works here too else:

rows, cols = eval(sys.argv[1]), eval(sys.argv[2]) SumGrid(root, rows, cols).pack() mainloop()

Notice that this module's sumGrid class is careful not to either grid or pack itself. In order to be attachable to containers where other widgets are being gridded or packed, it leaves its own geometry management ambiguous, and requires callers to pack or grid its instances. It's okay for containers to pick either scheme for their own children, because they effectively seal off the pack-or-grid choice. But attachable component classes that aim to be reused under both geometry managers cannot manage themselves, because they cannot predict their parent's policy.

This is a fairly long example that doesn't say much else about gridding or widgets in general, so I'll leave most of it as suggested reading and just show what it does. Figure 8-33 shows the initial window created by this script after changing the last column and requesting a sum.

Was this article helpful?

+1 0

Post a comment