This page intentionally left blank Python for Software Design



tải về 1.38 Mb.
Chế độ xem pdf
trang76/83
Chuyển đổi dữ liệu13.08.2023
Kích1.38 Mb.
#55046
1   ...   72   73   74   75   76   77   78   79   ...   83
- Python for Software Design How to Think Like a Computer Scientist-Cambridge University Press (2009)

(200, 100):
canvas.rectangle([[0, 0], [200, 100]],
fill='blue', outline='orange', width=10)
This way of specifying corners is called a bounding box because the two points bound
the rectangle.
oval
takes a bounding box and draws an oval within the specified rectangle:
canvas.oval([[0, 0], [200, 100]], outline='orange', width=10)
line
takes a sequence of coordinates and draws a line that connects the points. This
example draws two legs of a triangle:
canvas.line([[0, 100], [100, 200], [200, 100]], width=10)
polygon
takes the same arguments, but it draws the last leg of the polygon (if
necessary) and fills it in:
canvas.polygon([[0, 100], [100, 200], [200, 100]],
fill='red', outline='orange', width=10)
19.5
MORE WIDGETS
Tkinter provides two widgets that let users type text: an Entry, which is a single line,
and a Text widget, which has multiple lines.
en
creates a new Entry:
entry = g.en(text='Default text.')
The text option allows you to put text into the entry when it is created. The get
method returns the contents of the Entry (which may have been changed by the
user):
>>> entry.get()
'Default text.'


19.5 More Widgets
219
te
creates a Text widget:
text = g.te(width=100, height=5)
width
and height are the dimensions of the widget in characters and lines.
insert
puts text into the Text widget:
text.insert(END, 'A line of text.')
END
is a special index that indicates the last character in the Text widget.
You can also specify a character using a dotted index, like 1.1, which has the line
number before the dot and the column number after. The following example adds
the letters 'nother' after the first character of the first line.
>>> text.insert(1.1, 'nother')
The get method reads the text in the widget; it takes a start and end index as argu-
ments. The following example returns all the text in the widget, including the newline
character:
>>> text.get(0.0, END)
'Another line of text.\n'
The delete method removes text from the widget; the following example deletes all
but the first two characters:
>>> text.delete(1.2, END)
>>> text.get(0.0, END)
'An\n'
Exercise 19.3
Modify your solution to Exercise 19.2 by adding an Entry widget and a second button.
When the user presses the second button, it should read a color name from the Entry
and use it to change the fill color of the circle. Use config to modify the existing
circle; don’t create a new one.
Your program should handle the case where the user tries to change the color of a
circle that hasn’t been created, and the case where the color name is invalid.
You can see my solution at thinkpython.com/code/circle_demo.py.


220
Case Study: Tkinter
19.6
PACKING WIDGETS
So far we have been stacking widgets in a single column, but in most GUIs the layout
is more complicated. For example, here is a slightly simplified version of TurtleWorld
(see Chapter 4).
This section presents the code that creates this GUI, broken into a series of
steps. You can download the complete example from thinkpython.com/code/
SimpleTurtleWorld.py
.
At the top level, this GUI contains two widgets – a Canvas and a Frame – arranged
in a row. So the first step is to create the row.
class SimpleTurtleWorld(TurtleWorld):
"""This class is identical to TurtleWorld, but the code that
lays out the GUI is simplified for explanatory purposes."""
def setup(self):
self.row()
...
setup
is the function that creates and arranges the widgets. Arranging widgets in a
GUI is called packing.


19.6 Packing Widgets
221
row
creates a row Frame and makes it the “current Frame.” Until this Frame is closed
or another Frame is created, all subsequent widgets are packed in a row.
Here is the code that creates the Canvas and the column Frame that hold the other
widgets:
self.canvas = self.ca(width=400, height=400, bg='white')
self.col()
The first widget in the column is a grid Frame, which contains four buttons arranged
two-by-two:
self.gr(cols=2)
self.bu(text='Print canvas', command=self.canvas.dump)
self.bu(text='Quit', command=self.quit)
self.bu(text='Make Turtle', command=self.make_turtle)
self.bu(text='Clear', command=self.clear)
self.endgr()
gr
creates the grid; the argument is the number of columns. Widgets in the grid are
layed out left-to-right, top-to-bottom.
The first button uses self.canvas.dump as a callback; the second uses self.quit.
These are bound methods, which means they are associated with a particular object.
When they are invoked, they are invoked on the object.
The next widget in the column is a row Frame that contains a Button and an
Entry:
self.row([0,1], pady=30)
self.bu(text='Run file', command=self.run_file)
self.en_file = self.en(text='snowflake.py', width=5)
self.endrow()
The first argument to row is a list of weights that determines how extra space is
allocated between widgets. The list [0,1] means that all extra space is allocated to
the second widget, which is the Entry. If you run this code and resize the window,
you will see that the Entry grows and the Button doesn’t.
The option pady “pads” this row in the direction, adding 30 pixels of space above
and below.


222
Case Study: Tkinter
endrow
ends this row of widgets, so subsequent widgets are packed in the column
Frame. Gui.py keeps a stack of Frames:

When you use row, col, or gr to create a Frame, it goes on top of the stack and
becomes the current Frame.

When you use endrow, endcol, or endgr to close a Frame, it gets popped off the
stack and the previous Frame on the stack becomes the current Frame.
The method run_file reads the contents of the Entry, uses it as a filename, reads the
contents and passes it to run_code. self.inter is an Interpreter object that knows
how to take a string and execute it as Python code.
def run_file(self):
filename = self.en_file.get()
fp = open(filename)
source = fp.read()
self.inter.run_code(source, filename)
The last two widgets are a Text widget and a Button:
self.te_code = self.te(width=25, height=10)
self.te_code.insert(END, 'world.clear()\n')
self.te_code.insert(END, 'bob = Turtle(world)\n')
self.bu(text='Run code', command=self.run_text)
run_text
is similar to run_file except that it takes the code from the Text widget
instead of from a file:
def run_text(self):
source = self.te_code.get(1.0, END)
self.inter.run_code(source, '')
Unfortunately, the details of widget layout are different in other languages, and
in different Python modules. Tkinter alone provides three different mechanisms
for arranging widgets. These mechanisms are called geometry managers. The one I
demonstrated in this section is the “grid” geometry manager; the others are called
“pack” and “place.”
Fortunately, most of the concepts in this section apply to other GUI modules and
other languages.


19.8 Binding
223
19.7
MENUS AND CALLABLES
A Menubutton is a widget that looks like a button, but when pressed it pops up a
menu. After the user selects an item, the menu disappears.
Here is code that creates a color selection Menubutton (you can download it from
thinkpython.com/code/menubutton_demo.py
):
g = Gui()
g.la('Select a color:')
colors = ['red', 'green', 'blue']
mb = g.mb(text=colors[0])
mb
creates the Menubutton. Initially, the text on the button is the name of the default
color. The following loop creates one menu item for each color:
for color in colors:
g.mi(mb, text=color, command=Callable(set_color, color))
The first argument of mi is the Menubutton these items are associated with.
The command option is a Callable object, which is something new. So far we have seen
functions and bound methods used as callbacks, which works fine if you don’t have
to pass any arguments to the function. Otherwise you have to construct a Callable
object that contains a function, like set_color, and its arguments, like color.
The Callable object stores a reference to the function and the arguments as attributes.
Later, when the user clicks on a menu item, the callback calls the function and passes
the stored arguments.
Here is what set_color might look like:
def set_color(color):
mb.config(text=color)
print color
When the user selects a menu item and set_color is called, it configures the
Menubutton to display the newly selected color. It also prints the color; if you try
this example, you can confirm that set_color is called when you select an item (and
not called when you create the Callable object).

tải về 1.38 Mb.

Chia sẻ với bạn bè của bạn:
1   ...   72   73   74   75   76   77   78   79   ...   83




Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2024
được sử dụng cho việc quản lý

    Quê hương