Learning Perl/Tk [1 ed.] 1565923146, 9781565923140

Learning Perl/Tk is a tutorial for Perl/Tk, the extension to Perl for creating graphical user interfaces. With Tk, Perl

557 70 36MB

English Pages 373 [390] Year 1999

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Learning Perl/Tk [1 ed.]
 1565923146, 9781565923140

Citation preview

Graphical User Interfaces with Perl

O'REILLY

Nancy Walsh

n^v^icT AivSU^s

3-

Learning Perl/Tk

Learning Perl/Tk

Nancy Walsh

O'REILLY^ Beijing



Cambridge



Famham



Koln



Paris



Sebastopol



Taipei



Tokyo

Learning Perl/Tk

by Nancy Walsh Copyright

©

1999 O'Reilly

&

Associates, Inc. All rights reserved.

Printed in the United States of America.

Published by O'Reilly fd/tor; Linda

& Associates,

Inc.,

101 Morris Street, Sebastopol,

CA

95472.

Mui

Editorial and Production Services:

Production Editor:

Ellie

Fountain

tips— Technical

Publishing, Inc.

Maden

Printing History:

Nutshell

January 1999:

First Edition.

March

Minor corrections.

1999:

Handbook, the Nutshell Handbook logo, and the O'Reilly logo are registered trademarks & Associates. The use of an emu image in association with Perl/Tk is a trademark of & Associates, Inc. Permission may be granted for non-commercial use; please inquire by

of O'Reilly O'Reilly

sending mail to [email protected].

Many

of the designations used by manufacturers and sellers to distinguish their products are

claimed as trademarks. Where those designations appear in this book, and O'Reilly & Associates, Inc. was aware of a trademark claim, the designations have been printed in caps or initial caps.

While every precaution has been taken

book, the publisher assumes no from the use of the information

in the preparation of this

responsibility for errors or omissions, or for

damages

resulting

contained herein.

@ This book O'Reilly

&

is

85% recycled content, 15% post-consumer waste. committed to using paper with the highest recycled content available

printed on acid-free paper with

Associates

is

consistent with high quality.

ISBN:

1-56592-314-6

[5/99]

Table of Contents

xi

Preface 1.

Introduction to Perl/Tk

A

Bit of History

About

Perl

Perl/Tk for Both Unix and

Why Why

Use a Graphical

1

(and Tk)

Windows 95/NT

Interface?

Use Perl/Tk?

Installing the

Tk Module

5 6

Style

8

Displaying a Widget

9 9

Coding

The Anatomy of an Event Loop Hello World Example

Using

exit

10

Versus Using destroy

Naming Conventions

for

Widget Types

Using print for Diagnostic/Debugging Purposes Designing Your

Windows (A

Short Lecture)

Geometry Management

12 12 13

14

15

Pack

16

Grid

Geometry Management Summary

34 47 56

The Basic Button

37

The Button Widget

57 80

Place

3.

2 3

Creating Widgets

2.

1

2

Some Fun Things

to Try

V

Table of Contents

4.

Checkbuttons and Radiobuttons

81

The Checkbutton Widget

81

The Radiobutton Widget Fun Things 5.

6.

Label

to Try

and Entry Widgets

102

The Label Widget

102

The Entry Widget

108

Fun Things

123

to Try

124

Scrollbars Defining Scrollbar Parts

124

The

Scrolled

Method

126

The

Scrollbar

Widget

128

Examples

137

Fun Things 7.

93 101

140

to Try

The Listbox Widget

141

Creating and Filling a Listbox

141

Listbox Options

142

Modes

144

Selection

145

Colors Listbox Style

146

Configuring a Listbox

147

Inserting Items

147

Deleting Items

148

Retrieving Elements

148

Selection

Moving

Methods

to a Specific

149 Index

130

Translating Indexes

130

Counting Items

130

Active Versus Selected

130

Bounding Box

131

Finding an Index by Scrolling

Listbox

Methods

Example

Fun Things

to Try

Y

Coordinate

131 131

132 133

Table of Contents

8.

154

Text Widget Options

155

A

160

Short Break for a Simple Example

Text Indexes

161

Text Tags

164

Inserting Text

171

Deleting Text

172

Retrieving Text

172

Translating Index Values

172

Comparing Index Values

173

Showing an Index

175

Getting the Size of a Character

173

Getting Line Information

173

Searching the Contents of a Text Widget

174

Scrolling

175

Marks

175

Embedding Widgets

176

Internal

Debug

Fun Things 9.

154

The TextWidget Creating and Using a Text Widget

179

Flag

180

to Try

The Canvas Widget

181

Creating a Canvas

181

Coordinate System

182

The

Scrollable Region

183

Using Bind with a Canvas

184

Canvas Options

184

Creating Items in a Canvas

188

Configuring the Canvas Widget

198

Configuring Items in the Canvas Widget

199

Tags

199 202

Retrieving

Bounding Box Coordinates

Translating Coordinates

202

Moving Items Around

202

Changing the Display

List

203

Deleting Items

203

Deleting Tags

204 204 204

Determining Item Type Set

Keyboard Focus

via

10.

Table of Contents

Rendering the Canvas as PostScript

204

Scaling the Canvas

205

Scanning

206 206 209

A Drawing

Program Example

Fun Things

to Try

The Scale Widget

210

Assigning a Callback

213

Orientation

213

Minimum and Maximum Values

213

Displayed Versus Stored Value

Displaying Value Increments

214 214 214

Adding a Label Changing the Size of the Scale

215

Options You'll Probably Never Need

215

Configuring a Scale

216 216 216 216 216 217

Getting the Value of a Scale Setting the Value of a Scale

Determining Coordinates Identifying Parts of a Scale

Fun Things 11.

to Try

218

Menus Different

Types of Menus

The Menubutton Widget Complete Menubutton Examples

The Menu Widget

Optionmenu Widget Fun Things 12.

210

Creating a Scale

to Try

236 238 248 250

251

Frames Creating a Frame

Frame

218 220

251

253

Style

Frames Aren't

Interactive

255

Colormap Complications

255

Frame Methods

256 256

Fun Things

to Try

Table of Contents

13.

257

Toplevel Widgets

257 260 269 269

Creating a Toplevel Widget

Toplevel Methods

Review

Fun Things 14.

to Try

Binding Events

270

The bind Method

270

Arguments Sent

272

to the Callback

Defining Event Sequences

273 278

Event Information Bailing

Out of

a Callback Created with

bind

The bindtags Method

Ways 15.

to

Use bind

281

Composite Widgets Looking

at

282

an Example Sideways

Location of Files Creating a Composite Widget Based

Toplevel-Based Composite Widgets 16.

Methods for Any Widget

279 280 280

on Frame

283 284

289

290

Color-Related Methods

290 292

Option Databases

293

Building a Family Tree

The

Application's

Name

Widget Existence Is

the Widget

Mapped?

Converting Screen Distances Size of

Widget

Widget Position Screen Information

Atom Methods Ringing a Bell

Clipboard Methods Selection

Methods

Destroying a Widget

Focus Methods

Grab Methods Interapplication

Communication

295

295 295 295

296 297 298 300 300 300 301

302 302 303 304

X

Table of Contents

Waiting for Events to Parsing

Happen

304 306 306

Command-Line Options

Time Delays

and cget

309

A.

Configuring Widgets with configure

B.

Operating System Differences

331

C.

Fonts

334

Index

341

Preface

Perl

is

a great language for

file

processing, connecting to databases, and

do manually. For many command-line interface. The Tk

years,

programs were limited

interface

to a

many

however, Perl

other tasks that are too tedious to

changed

all

that.

The Tk extension

to Perl allows

you

to create graphical interfaces for

your pro-

grams. Using the modules included with the distribution of Tk, you can create

windows with

buttons,

lists,

text,

and other types of widgets

to help

your user

navigate within your application.

What You Should Already Know To

get the

book, you should already know the basics of Perl (speYou should be familiar enough with Perl to be able to at some code and know what the code is doing. You don't have to be a

most out of

cifically, Perl

least

read

version

this

5).

Perl guru or Perl hacker to learn Perl/Tk, but

with the language. Here's the laundry hashes, arrays, subroutines, and their

list

it

will

of things

anonymous

help

if

you

feel

you should at $_ and

versions,

Perl/Tk utilizes the object-oriented features available in Perl

5,

least recognize:

©_.

so even

completely understand them, you should be able to recognize them them. The only other thing you'll need

is

comfortable

if

you don't

when you

see

your prior knowledge of other graphical

user interfaces (GUIs) and what you did and did not like about them. This helps

when

deciding what features to include in your

own

applications.

Take

a look at

word processor you use on your PC, your web browser, or any program has buttons and scrollbars and accepts both mouse and keyboard input.

the

that

xt

xii

Preface

Those applications are

and build up from

pretty major ones; we'll start with

there. We'll

ated options in detail. You'll learn it

how

to look. You'll also learn

much

simpler examples

be covering each basic widget and to

how

all

its

associ-

make a window look the way you want make a window user-friendly and attractive. to

you want to know more about Perl in general, you should read Learning Perl, Programming Perl, Advanced Perl Programming, and Perl Cookbook, which are also published by O'Reilly & Associates, Inc. There are also numerous FAQs and documents available on the 'Web. This book's focus is the Tk extension to Perl, which is a fairly specific portion of Perl. If

Whafs Chapter

1

,

in This

Book

Introduction to Perl/Tk

The

first

ule.

It

chapter contains

some

you out with

starts

and the Tk modWorld program and gives a short

interesting history about Perl

a simple Hello

introduction to event-driven programs. 2, Geometry Management Geometry management is probably the most important concept in using Perl/Tk. It determines how your widgets are to be drawn on the screen (or, in some cases, how not to be drawn on the screen). The three geometry managers ^pack, grid, and place are covered here. Most examples in the book

Chapter





use pack.

Chapter

3,

The Basic Button

The button

is

the

are also tons of

first

widget

we

cover and there are

manipulate and mutilate the button widget. here are

Chapter

4,

lots

of details here. There

code snippets and screen shots showing

common among

Checkbuttons

Many

different

ways

to

of the options discussed

the other standard widgets.

and Radiobuttons

Checkbuttons and radiobuttons are similar to the standard button, but they look different and are usually programmed differently.

Chapter

5,

Label

and Entry

Widgets

The label is the simplest widget of all. It is usually used with an entry widget, which is why they are included in the same chapter. The entry widget will let you get input from your user. Chapter

6,

Scrollbars

Certain widgets in Perl/Tk can be scrolled,

more information than you can see on

which means they can contain

the screen. Scrollbars are used to navi-

gate the data inside these widgets. Chapter 6

tells

you how

scrollbars

commu-

nicate with each widget and what you need to do to create and use them.

Preface

xiii

Chapter

A

The List box Widget

7,

any

listbox can contain

sort of data, but

from which the user can listbox,

fill

from the Chapter

some

with

items,

it

Chapter

usually contains a 7, you'll

learn

and change the way the user

of options

list

how

to create the

selects the items

list.

The Text Widget

8,

The

it

select. In

text

widget

is

a versatile

many purposes

widget you can use for

besides

Chapter 8 covers the different things you can put inside a

just

displaying

text

widget (such as text or other widgets) and

text.

how

to get the best use out of

them.

Chapter

A

The Canvas Widget

9,

canvas can display objects such as

widgets. Chapter 9 covers

all

circles, rectangles, text,

the options and

and even other

and how

to

numbers from which

to

methods

available

use them.

Chapter

10,

The

The Scale Widget

scale widget

select so there

is

is

great for giving the user a range of

no

possibility of a user typing in a

accidentally typing in letters. Chapter 10 includes get

and covers

all

the

11, Menus Once an application

methods available

for setting

number out

of range or

examples of the scale widit

up and using

it.

Chapter

gets

complex enough, you

will

need

Chapter 11 shows different ways to create menus and

used

in

to put a

how

menu

in

it.

they can best be

an application.

12, Frames The frame widget is used for organizing your other widgets on the screen to get the look you want. Chapter 12 shows how you can use frames in coordination with a geometry manager (covered in Chapter 2) to make your windows look the way you want them to.

Chapter

Chapter

An

13, Toplevel

Widgets

more than one window in it. You can use a toplevel widget to create a second window. In Chapter 13 you'll learn how to create one and display it. We also cover the numerous methods available for application often needs

manipulating toplevel widgets.

Chapter

One

14,

Binding Events

of the best

ways

to

add

functionality to

your application

tional bindings to the widgets. This chapter tells

how

to create

one and use

it.

you what

is

to

add addi-

a binding

is

and

xiv

Preface

Chapter

Composite Widgets

15,

You can combine widgets to make a much more useful, Many of the additional widgets you can use with Perl/Tk are

reusable widget. created this way.

Chapter 15 includes an example of a composite widget and gives you some ideas for creating your own.

Chapter

16,

Methods for Any Widget

There are several methods available for in

Chapter 16 and show you

how

all

widgets in Perl/Tk.

We

cover them

to use them.

Appendix A, Configuring Widgets with configure and cget Appendix A explains the configure and cget methods, which are used with every widget. It also includes a table that shows the options and defaults for each widget option.

Appendix B, Operating System Differences Appendix B covers the differences you'll encounter when you use Perl/Tk on different operating systems, specifically, Unix and Win32.

Appendix C, Fonts Appendix C covers covers the

new

font usage for Tk, for both

Unix and Win32 systems.

It

also

font syntax in Tk8.

Reading Order This

new

book was designed and written with two major audiences and those who have experience with it.

in

mind: people

to Perl/Tk

Perl/Tk Novices If

you have no idea where

to start, start at the beginning. This

book

designed to

is

lead you into topics by building a foundation of knowledge. We'll

with the button widget in Chapter plicated widgets. Using Perl/Tk

basic fundamentals of

how

it

is

3,

The Basic Button,

and move up

start

to

simple

more com-

not really that hard once you understand the

works.

Somewhat Experienced to Gurus Okay, so you've written a ton of programs with Perl/Tk and think you to

do

it.

I

things.

Chances are you have found

recommend reading through Chapter

complete understanding of to the widget sections

you are

code (and sometimes

full

gets in different ways.

The

all

how

those pesky options and

2,

"way

interested

know how

and have stuck with Geometry Management, so you have a that works,"

the geometry managers work.

programs) list

a

in.

I

Then

skip around

have included useful snippets of

that will give

you ideas on how

to use

wid-

of options for each widget are helpful reminders of

how

they affect each widget.

xu

Preface

Typographical Conventions The following typographical conventions

are used in this book:

Italic

command names,

is

used

is

used to identify replaceable values.

for filenames,

URLs, and emphasis. In syntax

lines,

it

Constant Width used for function and method names and

is

code

eral

their

arguments, and to

show

lit-

in text.

Bold is

used to show default values

in syntax lines.

We'd Like to Hear from You We

have tested and verified the information

may

but you Please

find that features

us

let

know

O'Reilly

&

about any errors you

by writing

future editions,

in this

book

to the best of

have changed (which may

in fact

find, as well as

our

ability,

resemble bugs).

your suggestions for

to:

Associates, Inc.

101 Morris Street Sebastopol,

CA

95472

1-800-998-9938 (in U.S. or Canada) 1 -707-829-05 1 5

(international/local)

1-707-829-0104 (fax)

You can

also

send us messages

request a catalog, send email

electronically.

To be put on our

mailing

list

or

to:

info@oreilly. com

To ask

technical questions or

comment on

the book, send email

to:

bookquestions@oreilly. com

We

have a

tions.

Here

able for

web

where

we'll

list

errata

you'll also find all the source

code

for

programs from the book

site for

the book,

download so you

don't have to type

http://www. oreilly. com/catalog/lperltk

it

all in.

and plans

for future ediavail-

xvi

Preface

Acknowledgments quite a bit of time out of my life, and would like to thank who helped make possible and put up with me while was off writfirst, my husband Mike, who helped out in so many little ways is impossito list them all; our dogs. Brandy and Theo, for keeping my feet warm; our

This

book has taken

I

the people ing ble

I

it

it

it:

cats,

Thumper and

Sasha, for keeping the monitor

desk (any typos are completely gested

this

whole crazy

idea;

their fault);

and

my

editor,

my

and keyboard anchored

co-worker, Kreg Webb,

to the

who

sug-

Linda Mui, for always coming up with

positive things to say in addition to the not-so-good things. I'd also like to

Achim

thank

all

the reviewers of the book.

They

include: Stephen Lidie,

Bohnet, Peter Prymmer, Nick Ing-Simmons, and Phivu Nguyen.

Introduction to Perl/Tk

There are many different modules available This

book

add

a graphical interface

Perl great. Instead of requiring a

on the command

mand and

that

extend the

functionalit\- of Perl.

on the Tk module. The Tk module allows us to easily to our Perl scripts and still use all the features that make

will concentrate

line,

command

typed

your program

is

with

some options

or user input

invoked with an icon or a simple com-

the interface handles ever\ihing from there.

The Tk extension to Perl doesn't come with the standard distribution of Perl.* need to get it separately from a CPAN site and install it. After you install the Tk module, you simply add use Tk; to the top of your Perl scripts.

You'll

A Bit of History About Perl (and Tk) was

Originally. Perl

with his

way

v^Titten as a "quick-fLx" to a

job. Typical of all self-admittedly lazy

problem

Larr\"

Wall was ha\'ing

people, he found a better and eas-

was bom. It has since evolved into a widespread and well-used language. Perl has been made available for numerous different platforms, has been well documented, and best of all. is license-fee free. Hopefully the reason you're looking at this book is because you're already com-erted to the wayier

of-Perl

to

do

and thus

it.

and want

to

The Tk extension

Perl

know how

to utilize

it

to the fullest.

and whatsits that comwas ported by Nick Ing-Simmons from Tcl/Tk for use with Perl. A common misconception is that you need Tel Tk installed in addition to Perl and Tk for the whole thing to v^ork. but all you really need is Perl bine to

make

to Perl handles

all

a graphical interface.

the widgets, whodads.

It

Unless you get the Win32 binar\' from CPAN, or another pre-built distribution such as Acti\ eState

Perl.

Chapter

and

Tk

its

tedly lazy people like in less

me

Introduction to Perl/Tk

a lot of other people, self-admit-

can download the binary for the machine they have and

than 10 minutes (download time not included).

install

it

pile

from source for your machine.

it

work by

extension. Thanks to a lot of

1:

You can

also

com-

and Windows 95/

Perl/Tk for Both Unix

NT was

book and cursing the fact that I didn't have enough machines at home to write this book with MS Word and test code examples on my Linux machine without booting back and forth from OS to OS, a miracle was happening. The Tk extension for Perl was ported to Windows. By Windows, I mean the overly-large, overly-influencing OS that is the default on most PCs nowadays, Microsoft Windows. Most people don't have C compilers for their Windows machines, but thanks to the work of Gurasamy Sarathy, there's a great binary distribution of Perl and a good selection of the Perl extensions, including Tk. You simply download the binary, run the install, and you're ready to go.

As

I

writing this

way you

There are no differences between the

write Perl/Tk applications

on

a

Unix machine and the way you write them on a Windows machine. You can use any simple

text editor

on

either system.

There

a small difference in the

is

run them; see Appendix B, Operating System Differences, for just

say that

I

3) rather than

prefer to run

Windows

my

Perl applications

details.

on Windows NT

way you

For now,

4.0 (Service

I'll

Pack

95.

Versions when

and greatest versions of Perl and Tk were Win32 version of the Tk module has been developed and released. Perl has also had some changes. Right before the book was going to print, the port of Tk800.007 was in beta and Perl was up to 5.004_68 (also I

started writing this book, the latest

5.003 and 400.202. Since

beta).

have made every

I

version of

Tk and

Perl

then, a

effort to include information that

and

certain instances (fonts, for

added

in the

new

I

is

relevant to the

new

examples with the new versions. There are

example) where some

version of Tk.

apply, but for the most part,

Why

to test the

have

tried to

you don't have

to

been where they

significant functionality has

note

all

the changes

worry about which version you have.

Use a Graphical Interface?

book (or are considering it in the bookstore) because you have some idea of why you might want to use a graphical interface for one or more of your scripts. Just in case you don't, read on.... Hopefully, you bought this

Why

Use Perl/Tk?

Because you are familiar with writing Perl can get information ing/writing

files,

and out of one.

in

and

input,

fed to

it

from

Do you want can

up

set

a

such as an

others,

I

)

installation script, require constant information

to create this directory?

Do you want

the help

bunch of

be nice

A GUI

adds a

interface

the keyboard to gather

button to execute

when

I

overwrite this DLL?

files?

Sometimes you

little flair

all

all

and waiting

for the next question to

that information

up

front

and then have

the steps after the decisions

and professionalism

to

were made?

an application. However,

would be overkill to add a GUI to a script. If all you are file, munging a bit with no user input, and spitting out GUI would be silly and unnecessary. GUI interfaces work best where

there are times

it

reading in one

another, a

you require a lot of decisions and input from the example in the preceding paragraph. Here are some examples of good uses

A

Can

defaults so the user just has to press return to say yes, but

sitting at it

Go



in or out at application

or . Certain applications can run with

file?

up. Wouldn't

is

(

to install this

the user press a

doing

usually involves a combination of read-

Do you want

the user:

then they are stuck

come

you understand the ways you

command-line options, and possibly, data

runtime (STDIN/STDOUT, using pipes

no

It

scripts,

mini

web

client that

user,

such as our

installation

for a graphical user interface:

connects to a dictionary server and

lets

you look up

words. •

An application that takes a regular expression map graphically in a scrollable window.



An

A

and displays the

and displays query what the data is.

application that interfaces with a database

several widgets, with labels to indicate •

as input

state

results in

mail reader that interfaces with your inbox and can also send out mail

messages. •

Sometimes your boss says "make a

wrapper around a

script or

it

easy to use!" and that usually means either

an interface that makes

it

easy for users to under-

stand the decisions they have to make. Your users also might be used to a graphical interface rather than a command-line interface.

Why

Use Perl/Tk?

Have you ever tried to draw a window using so-called "native" facilities? If you do it in C, you'll end up with about 100 lines of code just to create a Hello World program, whether you use MS Windows or X Windows. This doesn't even include an Exit button that would allow you to quit the application nicely. I

have used several different methods

tions throughout

my programming

life.

to

draw windows and

Using the basic

create

X Windows

GUI

applica-

routines (such

Chapter

X_Create_Line_from_x_to_y)

as

trol

over every

Sometimes

me

to

I

little

like

know

details of the

it

did.

Introduction to Perl/Tk

basically a drag. True,

is

you have

but then again, you have to control every

detail,

not knowing exactly

that

1:

how

combustion engine.

I

little detail.

enough for and don't exactly understand the intricate

drive a car,

(I

con-

total

the button got drawn;

like that

it is

can turn the key and succeed in

I

my

mission of driving to work.)

You have probably seen

several books on Tcl/Tk. The problem with Tel is that program within the constraints of the Tel language. I much prefer using a language that I already know really well and adding on to it.

you have

to

Perl/Tk provides you with It

hang

the annoying

3D edges on your

handles drawing the

talking about,

all

in there;

I'll

explain

"

(

)

complex widget types

in

all

Something" ->pack

In addition, because of the wonderful different

buttons

which

Perl language to "place a button here," $rr[w->Button -text =>

it

little

details. (if

due

It

handles the event loop.

you're not quite sure what I'm time).

You can simply use

( )

;

community

available for use.

Perl has, there are multitudes of If

you

own by

using a combination of

wid-

can't find the perfect

get (such as a multi-listbox-selection-thingy with associated canvas), ple to create your

the

translates to real Perl as:

some

it

is fairly

sim-

basic and/or not so basic

widgets and constructs.

From

a programmer's

view the bottom

line

is

that using Perl/Tk to write a

GUI

is

programming high. With just a few lines of code, you can instantly display a button and several other widgets that look like a full-blown application. Of course, it takes a bit more time to code the guts behind fun!

it,

It

but

is

it's

the best instant-gratification

almost as

As you go through

much this

fun.

book, the best

way

to understand

what

is

going on

is

to try

lots

of different examples. There are tons of working code snippets included for

this

very reason.

to the button as

your very Also,

own

with the basic Hello World program and change the options you go through Chapters 2 and 3- See what the results are on

Start

screen.

you might want

to

check out these tools (which

we

don't cover in this book,

but they are fun to use): tkpsh and ptksh (new in Tk800.007, the

Tk

for Perl).

You

latest

version of

can download them from http://www.monmouth.com/~beller.

Both programs allow you to type statement (similar to wish).

in

code on STDIN and have

it

evaluate each

Installing the

Tk Module

Installing the Tk Before

we go

into

more

Module on using

details

we

Perl/Tk,

should cover

There are many different ways to get Perl and Tk and

it.

machine.

You can

get the source

and compile

Windows), or you can get a binary

may

distributions

not have

you read any README

sure

The two major binary

all

the

files

how

to install

them on your

(easy in Unix; not so easy in

MS

and install that. Some of the binary components you want in it though, so make

distribution

included with the package.

distributions for Perl

ihttp://www.activestate.com) and

it

install

CPAN

on Win32

are available from ActiveState

{http://www.perl.coni).

tion

on CPAN includes the Tk module, so

First

you need

that's the

one

I'll

The binary

distribu-

cover here.

to get Perl installed:

You can test to see if you already have mand (both Unix and Win32):

Tk module

the

installed

by using

this

com-

perl -e 'use Tk' If

you don't

get an error, you're ready to go.

If

you do get one, the

error will look

like this:

Can't locate Tk.pm in @INC (©INC contains: C:\PERL\lib\site C:\PERL\lib c:\ .) at rayscript line 1.

perlMib c:\perl\lib\site c:\perl\lib\site You'll

need

to find the

Tk module on

a

CPAN

site.

Try starting with

http://

www.perl.com/CPAN/modules/by-module/Tk/. From that directory, find the following

Tk*readme and Tk*tar.gz (always

files:

for the version

systems a

number). Be careful

rename the extension and

try to

.tar.gz

README

make

file it

try to

to .tar. tar. Simply

will

grab the

when you download

latest versions; the

the .gz

rename the

file

file

*

is

because some

back so

that

it

has

unzip properly. Follow the instructions in the

you have the right version of Perl already. After downloading Tk*tar.gz, you need to uncompress it using WinZip for MS Windows or gunzip and tar -xvffor Unix. Follow the instructions in the Install file once you

have

Run

it

file

to

unpacked.

It is

sure that

very similar to installing Perl

itself.

the test

perl -e 'use Tk'

again to make sure it all worked correctly. (Note: Windows users will need to use perl -e "use Tk"). For both MS Windows and Unix, make sure your perl/bin directory is in your PATH environment variable. You can then use the widget demo to see what types of widgets are available.

;

Chapter

1:

Introduction to Perl/Tk

Creating Widgets same

All widgets are created in the

track of

while

it

it

to

exists in the application.

have a central window

few exceptions. created and keep

basic fashion, with only a

Each widget must have a parent widget

watch over

When you

as

it

it

is

create an application, you'll

that will contain other widgets. Usually, that

window

will

and any other windows you create in your application. You are creating an order to the widgets so the communication between child and parent widgets can happen automatically without any intervention from you once you set it all up. be the parent of

all

the widgets inside

$parent widget already Widget type is as follows:

Assuming

that the

ate widget

$child = $parent->Widgettype

Note

it

-option => value,

[

(

generic usage

exists, the

.

.

.

]

when you

cre-

)

that the variables that store the widgets are scalars. Actually, they are refer-

know that right now. If you aren't programming in Perl, using the -> between the $parent and Widgettype invokes the method Widgettype, from the $parent object. It makes the $parent related to the child $child. As you might guess, the $parent becomes the parent of the widget being created. A parent can have many children, but a child can only have one parent. That's pretty much all there ences to widget objects, but you don't need to

familiar with the object-oriented

is

to assigning children to their parents.

When you

invoke the Widgettype method, there are usually configuration param-

to set up the widget and interactions within the application. The configuration parameters will occur in pairs: an option and associated value.

you send

eters that

You

-text, -state, or -variable. Notice that the

will see options similar to

options

all start

with a dash. Even with the dash, they are really

labels to indicate the next value to

come

in the

list.

Usually,

put quotation marks around the options because Perl nize

them

as strings.

However,

about an option that options

all

are always

the time to avoid all

if

you are using the -w

is

not

this,

but

thinks

it

text. it

You can

is

it

just strings that are is

not necessary to

smart enough to recog-

switch, Perl

stick

may complain

quotes around

all

your

The option names which are noted as we

shouldn't be necessary.

lowercase (except in a few very rare cases,

cover them).

Options are specified

in

(-option -> value,

list

form

like this:

-option => value,

-option => value)

Don't be fooled by the funny-looking =>;

"comma."

In fact,

(-option,

you could use

value,

-option,

just

value,

the

it

is

just

commas and

-option, value)

a different

way

of saying

not the => notation, that

is:

Creating Widgets

However,

much

it's

harder to

which are the option/value

tell

Consider the

pairs.

following syntactically equal statements (which each create a button widget that

word

10 pixels by 10 pixels, displays the

when

ting the application

and performs the action of

is

quit-

pressed):

$bttn = $parent->Button(-text, -height,

"Exit,"

"Exit",

sub

-conunand,

{

exit

-width,

},

10,

10);

$bttn = $parent->Button(-text 10, -height => 10)

==>

"Exit",

-command => sub

{

exit

-width =>

},

In the second line, it is much more obvious which arguments are paired together. The option must be directly before the value associated with it: -text is paired with "Exit," -command has the value sub { exit }, and -width and -height

both have values of

10.

Congratulations, we're not even

know how

done with the

first

chapter yet, and you already

to read a typical line of Perl/Tk code!

Quick Definitions ofToplevel, MainWindow, and

Frame Widgets The next chapter covers geometry management, and widgets you don't

know

anything about

several of the

examples use

Most of the widgets are easy

yet.

to fig-

ure out, but a few require a short introduction.

A MainWindow widget is a special version of a toplevel widget. Both MainWindow and toplevel are the windows that contains other widgets. The only difference between a toplevel and a MainWindow

window you

is

that the

MainWindow

is

the

first

create in your application. Both of these widgets are covered in

greater detail in a later chapter (Chapter 13, Toplevel Widgets).

The other type of widget you need

to

know

container that can also contain other widgets.

about It is

a

is

frame widget.

usually invisible

arrange the widgets as desired. The frame widget

A

and

frame

just

also discussed in

is

is

a

used to its

own

chapter (Chapter 12, Frames).

Here

is

what each widget's creation code looks

like:

$mw = new MainWindow; # or $mw = MainWindow->new() $top = $raw->Toplevel $frame = $raw->Frame -borderwidth => 2, -relief => "groove"); ;

( )

(

For now,

just

frame widgets.

keep

in

mind

the general meanings of

MainWindow,

toplevel,

and

;

,

;

,

Chapter

Coding The code of

lines in a Perl/Tk script

ways

are several

can get quite cumbersome and clunky because

Most

"edit-ability").

code

to format the

involve adding extra spaces or tabs to line

just

get used and unwieldy.

quite so mysterious

I

use

to seeing the code,

$bttn = $parent->Button(-text => "my text", -command => sub { exit -width => 10, -height => 10)

With

this

value

is

type of coding

lines (this

is

my

per-

the time):

all

it

some cases, up different

won't appear to be

it

each option/value pair on separate

style places

sonal favorite, and

and configuring each widget. There

to deal with readability (and in

Once you

portions of code.

One coding

Introduction to Perl/Tk

Style

the option/value pairs used in defining

all

1:

style,

it

is

}

extremely obvious what the pairs are and what

associated with which option. (You could also go to the extreme of align-

ing each

=>

to

make nice columns, depending on how much Some people like to start the option/value

press the space bar.) line

and put the ending

pair,

which

retains the

)

on

;

comma

$bttn = $parent->Button( -text => "Exit", -command => sub { exit -width => 10, -height => 10,

its

own

separate

line, after

time you have to pairs

on the next

the last option/value

for formatting ease:

}

);

This makes the code easier to

on each

line

edit;

an option/value pair can be added or deleted

without having to mess with parentheses, semicolons or commas.

also keeps the next lines closer to the

Sometimes,

if

all

there are only

on

side of the

you don't end up with code

indentation levels,

leave them

left

the

same

quite so

one or two option/value

line

and conserve a

page so

deep

pairs,

little bit

to the right. it

just

come up with

and the way you

edit

throughout your scripts

code

(it

a style that

works

makes sense

to

of space:

$bttn = $parent->Button(-text => "my text", -command => sub

Eventually you'll

It

you have several

if

{

exit

}

)

way you

read the code

just try to

be consistent

for the

it.

Whichever way you choose,

in

case someone else takes over the maintenance of your

could even be you a year or more

down

the road).

The Anatomy of an Event Loop

Displaying a Widget You use two

separate

commands

command.

In the

examples so

button, but nothing

is

widget and display

to create a

times they are squished into the same far,

line,

it,

although some-

which makes them look

like the

same

we've used the Button method to create the

displayed by using that method alone. Instead you have to

use a geometry manager to cause the widget to be displayed

in

its

parent widget

The most commonly used geometry manager is pack, and simply call the pack method on the widget object like this: you

or in another widget.

use

it,

to

( )

$widget->pack

{ )

For example: $button->pack

( )

There are arguments that can be sent to the pack method, but we'll cover those Chapter

2,

not necessary to invoke the

It is

be added

in

Geometry Management.

pack method on

a separate line.

The ->pack can

to the creation of the widget:

$parent->Button(-text => "Bye!", -command => sub

{

exit })->pack();

The other geometry managers available are grid and place. All three behave differently, and which one you use often depends on the look you are trying to get in your application. Again, look for information on the geometry managers in Chapter

2.

The Anatomy of an Event Loop When you

are

programming an application

than a textual interface, there are a

lot

that uses a graphical interface rather

of different things to consider. In a text-

based application, you can read from standard input (STDIN), use command-line options, read

files,

or

prompt the user

your only avenue of input from the those places, but as a

"close"

Although

it

our job more

The keyboard

is

GUI, input can not only come from

window manager (such mwm. or MS Windows).

can also come from the mouse and the

from a window manager

directive

this extra

for specific information.

user. In a

input allows

difficult.

As long as

more

we

flexibility in

tell

it

what

like

our applications,

it

also

to do, Perl/Tk helps us

makes

handle

all

that extra input gracefully.

Input in a

GUI

is

defined by events. Events are typically different combinations of

mouse at the same or different times. If the user pushes mouse button on button "B", that is one type of event. Pushing the right mouse button on button "C" would be another event. Typing the letter "a" would

using the keyboard and the

left

10

Chapter

1:

Introduction to Perl/Tk

be another event. Yet another event would be holding down the Control key and clicking with the middle mouse button. You get the idea. Events are processed during an event loop. This event loop does

name



says

it

handles events during a loop.

It

based on what type of event happened. Here

just

what

determines what subroutines to

is

a

its

call

pseudo-code event loop:

while (1) { ge t_even t_info

if event is left-mouse-click call process_left_mouse_click else if event is right-mouse-click call process_right_mouse_click else if event is keyboard- input call type_it else handle events for redrawing, resizing etc }

very simplistic approach to an event loop, yet

Obviously,

this is a

basic idea.

The event loop

input

was given

is

a

it still

shows the

weeding-out process to determine what type of

to the application. For example, the subroutine

process_lef t_

inouse_click might determine where the pointer was when the mouse occurred and then

call

In Perl/Tk, the event loop

we

If

happen

initiated

is

thing prior to this statement will not

is

until after the

forget to include the

MainLoop

calling a routine called

up

GUI has been

MainLoop

windows, buttons, or widgets occurs after calling

by

just setting

and then go

things for a while

click

other subroutines based on that information.

right will

is

the interface. exited

to the

be drawn

at

that the interface

after this call

by using $itiw->destroy.*

statement, the

back

MainLoop. Any-

Any code

program

will think

about

command prompt. None of the all. One of the first things that is

drawn and

the event loop

is

started.

Before

we

much

get too

further into the event loop

you need to do so it works right), let's look at World. (You were expecting something else?)

and what it does (and what working program. Hello

a real, live,

Hello World Example Every programming language goes through the Hello World example.

example because

*

shows how

it

Throughout the book,

I

will

use

the beginning of the application.

$mw

It is

a

good

to do something very simple but useful. In our

to indicate the variable that refers to the

main window created

at

Hello World

Example

11

Hello World example, we'll have the

title

window

of our

say "Hello World" and

create a button that will dismiss the application: # /usr /bin/perl use Tk; my $inw = MainWindow->new; $mw->title( "Hello World"); !

$iiiw->Button(-text => "Done",

-command => sub

{

exit

}

)

->pack;

MainLoop

Despite only being six lines long, there

gram. The

first line,

as

is

quite a bit going

Win32 you have to type perl hello.pl to invoke Perl that we would like to use the Tk module. The

on

in

our

little

pro-

any Perl programmer knows, invokes Perl (only on Unix; the program).

The second

in

line tells

third line

my $mw

=

how we

MainWindow->new;

window. The window will have the same basic window manager decorations as all your other windows. In a Unix environment, it will look like all your other windows, and if it were in MS Windows, it would look like those windows. is

create a

window

The

title

this

method, the

of our

is

changed by using the title method.

text across the top of the

If

window would be

we

the

hadn't used

same

as the

name of the file containing the code. For instance, if my code were stored in a file named hello_world, the string "Hello_world" would appear across the title bar of

my

application (Tk automatically capitalizes the

title method

Any

is

not required, but

makes

character for you). Using the

first

the application look

more

polished.

we put as an argument becomes the title. If wanted the title to be "Hey! my great program!" this would be the place. This is akin to using the -title when starting up any standard X Windows application. There are more meth-

string

Look

I

at

option

ods for a MainWindow

The next Chapter

3,

starts

only what will exit.

object,

line creates a

which

will

all

"Done" and

to display the text

Finally, the last item of

told

it

to do:

If



will all

Chapters 12 and

13-

it.

(See

to

concern

perform the Perl is

the

command

MainLoop command. will do

and from then on the application

the user clicks

Anything else the user does

applications

later in

available configuration options.)

the event handler in motion,

we have

be covered

Button widget, sets basic properties, and packs

The Basic Button, for

The button is set up exit when pushed. This

it

on the

—minimizing,

button, the application

resizing,

changing to other

be processed by the window manager and ignored by our

application. See Figure 1-1 for a picture of the Hello

World window.

12

Chapter

Figure 1-1. Hello World

1:

Introduction to Perl/Tk

window

Using exit Versus Using destroy In

all

of the examples in this

book you

will see

sub

exit;

{

}

used to quit the

use Tk; in the own exit routine

Perl/Tk application. This works fine as long as you have done a

same file that contains the sub { exit }. Perl/Tk defines which does some cleanup and various other things that Another way to quit the Tk portion of the application

its

are important to Tk.

to call $itiw->destroy (),

is

which destroys the main window and returns to the code listed after MainLoop. The code after MainLoop will not be executed even if you use sub { exit }. Keep this in mind if you are going to be doing anything after the GUI portion is done.

Naming Conventions for Widget Types Naming conventions?

we

How

boring! Well, sometimes our programs get so large

and

$button variable was pointing to. If there are over 10 buttons in our program, we would be hard-pressed to figure out which button was $button3 without digging through a bunch of code. unwieldy

that

remember what

can't

that stupid

I'm merely going to suggest a naming convention, and If

not, either

For buttons,

come up with your own, like to

I

or

if

hope you have

you

like

a really

it,

please use

use _b, _bttn, or Button as a type of qualifier to the

able name. For instance,

I

would name my button

it!

good memory.

in the Hello

vari-

World example

$done_b, $done_bttn, or $doneButton.

A

specialized widget type

dow method.

I

always use

is

the very

$itiw

first

programs use $main or $inainwindow as Table

1-1 contains a

list

window we create with name for this. You

as the variable

the

MainWin-

will see other

well.

of widget types and

my

suggested naming conventions for

them. Replace "blah" with a sensible description of the widget's purpose exit).

If

you use

working with.

this

convention, you'll always

know

(e.g.,

what type of widget you're

Using print for Diagnostic/Debugging Purposes

Naming conventions by

Table 1-1.

Widget Type

Suggested

Button

$blah_b

13

widget type

Name

Examples $exit_b, $apply_b, $newBut-

$blah_bttn, $blah-

(or

ton

Button)

$blahCanvas

Canvas

$blah_canvas

Checkbutton

$blah_cb

Entry

$blah_e or $blahEntrY

Frame

$blah_f or $blahFrame

or

$inain_canvas, $tinyCanvas

$blahCheckbutton

or

$uppercase_cb, $lowercaseCheckbutton $name_e, $addressEntry $main_f, $left_f, $canvas-

Frame Label

$blah._l or $blahLabel

Listbox

$blah_lb

Menu

$blah_m

Radiobutton

$blah_rb

$blahListbox

or

or

$name_l, $addressLabel $teaiTis_lb,

$blahMenu

$blahRadiobutton

or

$teamsListbox

$file_irv $edit_m,

$helpMenu

$blue_rb, $grey_rb, $redRa-

diobutton

I

Scale

$blah._scale or $blahScale

$age_scale, $incoineScale

Scrollbar

$blah_scroll $blahScroll

$x_scroll, $yScroll

Text

$blah_t

(or

$blahText)

Toplevel

$blah_w

or

$blahWindow

admit

me

use

are

two

I

don't follow

just

$button

in the

honor?) to use

(or $blah._sbar) or

my own in

rules

$file_txt, $commentText

all

example code.

$main_w, $fileopenWindow the time. Throughout this book, you'll see

use $buttonl and $button2

I'll

example. Anything larger than

my own

convention.

type of widget I'm referring

I

will

just a

few

always use a

lines,

name

I

if

there

will try (scout's

that indicates

what

to.

Using print for Diagnostic/Debugging Purposes Normally, you'll run your Perl/Tk program by typing the program

command %

name

at

the

prompt:

hello world

or C:\>perl hello_world

When you printf)

is

this way, any output created by using a print (or window. Sometimes, you won't see the information

invoke the program to that terminal

actually printed until

you

quit the program. This

is

probably because you didn't

put a \n on the end of the string to be printed, which causes an automatic flushing of output. During your application processing,

print statement when you should

be,

make

sure

if

a

you think you aren't seeing a is on the print statement.

\n

14

Chapter

Introduction to Perl/Tk

1:

Designing Your Windows (A Short Lecture) Before you decide what events to handle, sketching out a few

it is worthwhile to spend some time windows on paper and deciding what should happen (from

when you

the user's perspective)

One

of the most important things to keep in

windows

tion's

A GUI

nothing happens

that

is

MainLoop

prior to the call to

a

click a button or

is

just

mind when you design your event loop

until that

\

item.

applica-

up. Everything

starts

preparation for the event loop.

makes the application look much more polished and purposeful than command-line interface does. Also, it is often much easier to manipulate many

Here are some things look

through a GUI.

to consider

when you

what the GUI should

are deciding

like:



Every widget should have a purpose.



Think about the way



Don't



Don't always

try to separate

application

so simple that one

try to

a user will use

is

on using

cation

It

should be

color, allow

intuitive

is

accordingly.

doing into one window.

everything into different windows. Sometimes the

window

it

to

lot

is all

you need.

of color-blind people out there.

be customized

via a

their job better than others do.

file

If

you

or through the appli-

Use the

right job. it

it

itself.

Some widgets do

That's

and informative.

an application and design

cram everything your application

Colors are great, but there are a insist



menu

often

different kinds of user input



invoke a

for the lecture.

Now,

get ready to learn the ropes.

right

widget for the

Geometry

Management To

on the

display widgets

must be passed

screen, they

geometry manager controls the position and

to a

geometry manager. The

size of the widgets in the display win-

dow. There are several geometry managers available with Perl/Tk: pack, place,

and grid. geometry managers are invoked as methods on the widget, but they

All three

have

their

own

gets are put

$widgetl->pack

When you ( )

it

,

( )

$widget2->place

;

( )

;

$widget3->grid

organize the widgets in your window,

is difficult

to

out grouping them in

window

inside a

We

create our

form of

the wid-

screen:

groups of widgets to get a certain look and

pack

how

methodologies and arguments to change where and

on the

all

or

first

it

feel.

( )

often necessary to separate

is

when you

For instance,

have widgets stacked both horizontally and

some

We

fashion.

group widgets by using

by using another window

window by

a toplevel widget. For

calling

more

use

vertically with-

widget

a frame

(a toplevel widget).

MainWindow. The MainWindow

detailed information

on how

a special

is

to create/config-

ure frames and toplevel widgets, see Chapter 12, Frames, and Chapter 13, Toplevel Widgets.

Because of the differences between the three geometry managers, (not entirely impossible, but definitely not

geometry manager within the same widgets, but

if I

using

start

pack

widgets contained directly in

grid

( )

gets,

we

.

Because

could use

use

a

pack

gridO

$inw.

window can ( )

to

to

( )

I

,

area. In I

recommended) our $mw,

I

to use

can display

should continue to use pack

it

is

difficult

more than one

many ( )

on

types of all

of the

wouldn't want to switch in the middle to using

contain a frame, which in turn contains other wid-

pack the frame inside the main window and then

manage

the widgets inside the frame. See Figure

we

2-1.

15

16

Chapter 2: Geometry Management

Regioni: Contains several widgets and a frame

managed by

all

pack()

Widget A Widget A Frame: Placed inside

Figure 2-1.

in it

window by pack(), but widgets managed by grid().

are

Frame within a window

that uses

a

different geometry

Although the different geometry managers have

most commonly used

their

manager

own

and weak-

strengths

pack so I'll discuss it first and in the most detail. The gridO geometry manager was under development as I was writing this book, grid has been improved greatly with the release of Tk 8.0 and subsequent porting to Perl. The place geometry manager is the most tedious to use nesses, the

is

(

( )

,

)

because you have to determine exact coordinates for every single widget.

Pack Remember when you were the puzzle had exactly laps allowed 'With the

between

and you had those wooden puzzles on them. Each piece

a small child

put together? They often had cute

little

pictures of animals

one place where

it

pieces.

are similar to the

because widgets cannot overlap or cover each other If

a button

is

ton (or any widget) will

our windows

will

in

could go, and there weren't any over-

pack geometry manager, our windows

Figure 2-2.

to

wooden

puzzle

(partially or completely).

See

packed in a certain space on the window, the next buthave to move around the already packed button. Luckily,

only be dealing with rectangular shapes instead of funny-shaped

puzzle pieces.

The order in which you pack your widgets is very important because it directly affects what you see on the screen. Each frame or toplevel maintains a list of items that are displayed within

it.

before widget B, then widget

This

A

go through some examples. You

dow

just

by packing the widgets

list

has an order to

it;

if

will get preference. This will

will often get a

widget

A

become

is

packed

clear as

we

very different look to your win-

in a different order.

Pack

17

Widget

A

Widget B Figure 2-2. Overlap error If you don't care what the window looks like and how the widgets are put in it, with no arguments and skip the rest of this chapter. Here it is you can use pack ( )

again:

$widget->pack

( )

To make your window look are arguments that can

arranged in

pairs.

$widget->pack(

Here

is

be sent

window

widgets and the

nicer

in this

pack method

As with anything

that will

friendly), there

change the way the

in Perl/Tk, the

arguments are

So the more sophisticated usage would be: [

option => value,

the code to create a

used

to the

looks.

Figure 2-3 shows the resulting gets

and more manageable (and user

window window

);

]

that doesn't

know we

(I

example, but hang in there,

it's

use any options to pack ( ) haven't covered

all

the wid-

pretty simple).

# /usr /bin/perl -w use Tk; !

my

$rnw =

MainWindow->new;

$inw->title "Bad Window" ; $rnw->Label (-text => "This is an example of a window that looks bad\nwhen you don't send any options to pack" ->pack; (

)

)

$mw->Checkbutton(-text => "I like it!")->pack; $mw->Checkbutton(-text -> "I hate it " ->pack; $mw->Checkbutton(-text => "I don't care" ->pack; $mw->Button(-text => "Exit", -command => sub { exit } ->pack; MainLoop; !

)

)

)

;

18

Chapter

^

2:

;

Geometry Management

**^*»!3

Bad WfcKtow

an example of a window Uiat looks bad when you don't send any options to pack

This

is

J J

J

i

1

like

it!

liiateil!

don't care Exit

Figure 2-3-

Window

managed by pack

with widgets

We

can

will

make our window look much

alter the

preceding code and add some options to the pack() nicer:

# /usr/bin/perl -w use Tk; !

my $mw

= MainWindow->new;

$inw->title "Good Window" $inw->Label (-text => "This window looks much more organized, and less (

)

;

haphazardXnbecause we used some options to make it look nice" ->pack; )

$mw->Button(-text => "Exit", -command => sub

->pack(-side => 'bottom', -expand => 1, -fill => 'x'); $mw->Checkbutton(-text => "I like it! " ->pack(-side => 'left', -expand => 1) $mw->Checkbutton(-text => "I hate it " ->pack(-side => 'left', -expand => 1 $mw->Checkbutton(-text => "I don't care" ->pack( -side => 'left', -expand => 1) MainLoop; {

exit

)

}

)

!

)

)

)

Figure 2-4 shows the

much more

organized window.

Good Window This

J;

window looks much more organized, and less haphazard because we used some options to make it look nice I

like

it!

^

I

hate

it!

_j

I

don't care

Exit

Figure 2-4.

Window

with widgets

managed by pack

using some options

calls that

Pack

19

Using pack(

allows you to control:

)

window

relative to the

window

or frame edges



Position in the



Size of widgets, relative to other widgets or absolute



Spacing between widgets



Position in the

The

options, values,

window's or frame's widget and defaults are

listed

list

and discussed

in the

following section.

Pack Options This are

list

shows

shown

in

all

when you

the options available

bold (which indicates

if

pack

call

you don't use

( )

.

The

default values

that option, you'll get the

effects of that value for that option).

-side => 'left'

|

'right'

'top'

|

'bottom'

|

Puts the widget against the specified side of the

-fill => 'none'

|

'x'

Causes the widget to

-expand =>

1

'y'

|

fill

the allocation rectangle in the specified direction

|

fill

the remaining space available in the win-

or frame

-anchor => center '

or frame

'both'

|

Causes the allocation rectangle to

dow

window

'n'

|

'ne'

|

'e'

|

'se'

|

's'

|

'sw'

|

'w'

|

'nw'

|

'

Anchors the widget inside the allocation rectangle

-after => $otherwidget Puts $widget after $otherwidget

in

-before => $otherwidget Puts $widget before $otherwidget

packing order

in

packing order

-in => $otherwindow Packs $widget inside of $othe2rwindow which is the default

rather than the parent of $widget,

-ipadx => amount Increases the size of the widget horizontally by

amount x

-ipady => amount Increases the size of the widget vertically

by amount X

-padx => amount Places padding

on the

left

and

right of the

widget

-pady => amount Places padding

on the top and bottom of the widget

2

2

))

'

20

Chapter 2: Geometry Management

Positioning Widgets Each window (or frame) has four sides to

it:

top, bottom,

left,

and

right.

packer uses these sides as points of reference for widgets. By default,

The

packO

places the widgets against the top of the toplevel or frame.

You can

control

-side =>

For example,

what

'left' if

side a widget '

right

we would

'

' |

like

is

top

placed against by using the -side option: 'bottom'

our button against the

left

edge of the window,

we

can specify -side => 'left'.

Using our Hello World example as a base,

pack our button against the

->pack

different sides.

let's

look

The only

part of the Button creation line. We'll also

string in the

$inw->title

command

to easily

show

what happens when we we will change is the change the "Hello World"

at

line

the

new

options to pack.

$itiw->Button(-text => 'Done',

-command => sub { exit ->pack(-side => 'top');

})

OR $mw->Button(-text => 'Done', -command => sub { exit }) ->pack;

$mw->Button(-text => 'Done', -command => sub { exit } ->pack(-side => 'bottom');

sp ^^We =>

bottom'

h|j

Done

$mw->Button(-text => 'Done', -command => sub { exit } ->pack(-side => 'left');

-Side

Done

«>

left'

J

21

Pack

$inw->Button(-text => 'Done', -command => siob { exit } ->pack -side => right (

'

'

)

The windows shown here have been made a bit larger to emphasize the difference that using alternative values for -side makes. Normally, the window will be only as large as required to show the button. When you are deciding which way to place widgets in a window, it is always a good idea to see what happens when you make the window both larger and smaller. Make sure the behavior you get is what you want. So

far,

packO seems

what if you want to put more than one What happens when we simply add more buttons?

pretty simple, but

button in your application?

$rnw->Button(-text => 'Donel', $I^w->Button(-text => 'Done2', $mw->Button(-text => 'Done3', $iTiw->Button(-text => 'Done4',

-coinmand => sub -coinmand => sub

-command => sub -coinmand => sub

exit } ->pack; exit } ->pack; exit })->pack; exit })->pack; )

{

)

{

{ {

-side is top, we would expect them to all be mushed up window, right? Sort of. The packer allocates space for each widget and then manipulates the widget inside that space and the space inside the window. Since the default

against the top of the

Figure 2-5 shows what the

window

with the four

next section explains why.

_.

Buttim

>

Donel

DoneZ Done3

Done4

Figure 2-5- Four buttons packed with default settings

J

Done

buttons looks

like;

the

22

Chapter 2: Geometry Management

Allocation Rectangles When tom,

given an item to pack, the packer

right,

or

to use.

left)

looks to see which side (top, bot-

first

then sets aside an invisible rectangular area across the

It

length of that side for use only

by

that widget.

empty window

In Figure 2-6, the solid-line rectangle represents our

and the dotted-line rectangle the

first

button.

window, but

It

actually

make

to

it

tall

all

set aside

as the

way across the width shown a little indented.

the

it's

by packer when using -side =>

on the

window

Our examples so

it.

is

as

wide

For the right and

the width of the button.

If

we

in

and

-side

=>

'left'

we'll call the allocation rectangle,

as the

which the

fit

both the top and

window and

left sides,

but only as wide as required to

have used buttons

far

which

or height of the

'top'

size of the requesting widget. For

sides, the allocation rectangle

the widget to be placed in as

does go

for the dotted-line box,

are calculated based

bottom

(or frame),

the rectangular area that the packer sets aside for

easier to see,

Figure 2-6. Rectangular areas

The dimensions

is

only as

tall

the allocation rectangle

as is

the widget.

text of the button

create a button with the text

"Done" on

determines it

and one

it," the second button is going to be much two buttons are placed up against either the right or left side of the window, the second button would have a wider allocation rectangle than the first. If we placed those same two buttons against the top and the bottom, the allocation rectangles would be the same height and width because the

with the text "Done, Finished, That's

wider than the

width

is

first.

When

these

determined by the window, not the widget.

After the size of the allocation rectangle

is

determined, the widget

is

placed within

the allocation rectangle according to other options passed and/or the default val-

ues of those options. cation rectangle

Once

the

first

I

will

go over those options and

how

they can affect the allo-

later.

widget has been placed

in the

able for subsequent allocation rectangles rectangle has used

some

is

window, the amount of area smaller because the

of the space (see Figure 2-7).

first

avail-

allocation

Pack

23

Buttont Allocation Rectangle

New

Allocation Rectangle

Figure 2-7. Second allocation rectangle

When more

than one button

the results will vary

is

when

default side

buttons right and

used

placed against different sides in the same window,

depending on the order used.

by placing one button along the

We'll start

'top' is

one along the bottom, and then

top,

left:

$iTTW->Button(-text => "TOP",

-command => sub

exit

{

})

->pack(-side => 'top');

$mw->Button -text => "BOTTOM", -command => sub ->pack(-side => 'bottom'); (

$mw->Button(-text => "RIGHT", -command => sub ->pack(-side -> 'right'); $mKV->Button(-text => "LEFT", ->pack(-side => 'left');

The

allocation

rectangles

for

-command => sub

this

{

{

exit

{

exit

exit

})

})

})

window would look

like

the

diagram

in

Figure 2-8.

Allocation rectangle for

1

Allocation rectangle for

TOP

1

1

Allocation rectangle

LEFT

for

i

RIGHT

Allocation rectangle for BOTTOIVI

Figure 2-8. Allocation rectangles forfour buttons

Figure 2-9

so

it's

shows what the

a bit larger.

actual

window

looks

like,

both normal size and resized

;

;

24

Chapter

gj

Btmons

''4

j

~

4aiiwii!s

-.j

TOP

yJ3i

Geometry Management

2:

rr

Jl

,

TOP LEFT

LEFT

RIGHT

1

BOTTOM

RIGHT

,

BOTTOM ' ,

,



,j

window

Figure 2-9- Four buttons placed around the sides of the

Filling the Allocation Rectangle Normally, the widget

is

left at

the default size, which

allocation rectangle created for resize itself to

fill

If

it.

the

usually smaller than the

is

-fill option

used, the widget will

is

the allocation rectangle according to the value given.

The

possi-

ble values are: -fill => 'none'

'x'

Using the value 'x'

'both'

'Y'

will resize the

widget

x

in the

cause the widget to resize in the y direction. Using -fill =>

way

to see exactly

what

size

'y' will

direction. Likewise,

and placement was given

'both'

is

a

good

to the allocation rectangle

both x and y directions. Using our four-button example again, we'll specify -fill => 'both'.

because 'both' resizes the widget

in

$iTiw->Button(-text => "TOP", -command => sub ->pack(-side => 'top', -fill => 'both');

exit

{

$raw->Button(-text => "BOTTOM", -command => sub ->pack(-side => 'bottom', -fill => 'both'

{

})

exit

})

)

$mw->Button(-text => "RIGHT", -command => sub ->pack(-side => 'right', -fill => 'both'

{

exit

})

)

$mw->Button(-text => "LEFT", -command => sub ->pack(-side => 'left', -fill => 'both');

{

exit

})

Figure 2-10 shows the resulting window. If

we

switch the button

Figure 2-11

we

create

was created by packing

first,

we

get a different result.

the widgets in this order:

The window

left, right,

in

top, bottom.

Figure 2-12 demonstrates yet another order, which really shows that the allocation rectangles change size depending

on what

gets

packed

first.

25

Pack

^

side and

fiU(t, b, r .1)

1

^J

TOP RIGHT

LEFT

BOTTOM Figure 2-10. Four buttons packed to each side using

side and fM

-.

(r,

1,

-fill

b)

t,

=>

j

'both

J

.

TOP RIGHT

LEFT

BOTTOM ^

Figure 2-11. Four buttons packed to each side in a different order using

d

4Buttons (U,b,l)

1

.

-fill

=>

'both

J

TOP

LEFT

RIGHT

BOTTOM Figure 2-12. Four buttons packed in order of top,

A common

use of -fill

is

on widgets with

Usually, the scrollbars are along the

box box

to

fill

more

bottom,

and left

scrollbars: listbox, canvas,

and

edge of the window, and you want the

the remaining area. See Chapter

Widget, for

right,

6,

Scrollbars,

and Chapter

7,

The

text. list-

List-

information.

Expanding the Allocation Rectangle The -expand option manipulates the allocation rectangle and not inside it. The value associated with -expand is a boolean value. -expand =>

1

the widget

.

26

Chapter 2: Geometry Management

Given a true value, the allocation rectangle left

over in the

expand

will

window depending on which

into

side the widget

any available space

was packed.

Widgets packed with side

right or left will expand in the horizontal direction. Widpacked with side top or bottom will expand in the vertical direction. If more than one widget is packed with -expand turned on, the extra space in the win-

gets

dow

is

divided evenly

among

In Figure 2-9 or 2-10,

the

window

you saw

that wasn't

add -expand =>

window

the allocation rectangles that want

all

was some space

that there

occupied by any widget.

1 to the

list

left in

we change

If

it.

the center of the code and

of pack options for each button, the result

is

the

in Figure 2-13-

1

4ButtDns

-_(

1

J

-

TOP 1

>

RIGHT

LEFT

BOTTOM 1

Figure 2-13- Four buttons using the -expand => 1

Note the

that Figure 2-13 left the

-fill option, the buttons

(which are

invisible) take

-fill =>

and

=>

-fill

'both' options

'both' option

in the code. If

we

omit

stay their original size, but the allocation rectangles

over the extra space in the

(see Figure 2-14).

|.|J

4Buttons

^i

window

TOP

LEFT

^

RIGHT

BOTTOM

Figure 2-14. Four buttons using -expand => 1

and -fill =>

'none'

In Figure 2-14, the buttons are centered in their allocation rectangles

the default value of the

-anchor

option,

which

is

'

center

'

because of

27

Pack

Anchoring a Widget in

Its Allocation

Rectangle

The anchor option manipulates the widget inside the allocation rectangle by anchoring it to the place indicated by the value passed in. It uses the points of a compass as a reference. -anchor

'e'

'n'

'w'

'ne'

's'

'nw'

'se'

'center'

'sw'

Figure 2-15 shows those locations in an example allocation rectangle.

Figure 2-15- Allocation rectangle with -anchor points labeled

center which keeps the widget in the center of its -expand option is set to a true value, this won't seem to change much of anything in the window. As seen in Figure 2-16, which shows the result of using the -expand => 1 option, it is obvious that the widget

The

default for

-anchor

is

'

'

,

allocation rectangle. Unless the

sticks to that center position

when

the

window

is

resized.

Figure 2-16. Default behavior of -anchor with -expand set to

1

other defaults are used to pack the widget, Figure 2-17 shows what -anchor => 'e' and -anchor => 'w' does.

If all

Remember is

packed

that the allocation rectangle

against, so certain

is

combinations

created based will

on which

side the widget

appear to have not had any

For example: $inw->Button(-text => "Done", -coinmand => sub ->pack(-side => 'top', -anchor -> 'n');

{

exit

})

effect.

28

Chapter 2: Geometry Management

-aichor «>

J_

'e'

1-i^

Done

Done ^

1

Figure 2-1

7.

Examples of -anchor =>

'e'

and -anchor =>

'w'

This code fragment will leave the widget exactly where

it

was

if

-anchor

the

option had not been specified because the allocation rectangle does not change size at

all.

resized, the

's'

If

the

-expand option

widget would

had been

specified,

the south side of the

also specified, then

is

when

the

window

is

resized,

when

the

window

is

-anchor => the widget would stick to

stick to the north side of the

window.

If

window.

The -anchor option is more often used to line up several widgets Figure 2-18 and Figure 2-19 show two common examples.

-^ ex|

in a row.

^i|i

Done Done Done

Figure 2-18.

Window

with three buttons all packed with -side =>

Figure 2-19. Windows with three buttons

Sometimes,

all packed with -side

when -side and -anchor

be what you would expect cation rectangle and

how

it

'left',

-anchor =>

'w'

-anchor =>

are used together, the results don't

at first glance.

affects

=>

'top',

Always keep

what you see on the

in

mind

screen.

'n'

seem

to

that invisible allo-

29

Pack

Widget Order in the

Window

Each window

that has widgets packed into it keeps track of those widgets in an The order of this list is normally determined by the order in which the widgets were packed. The last item packed is the last item in the list. Using the -after option, you can change the default order by specifying which widget should be placed after your new widget. On the opposite end, if you use the -before option, you can put the new widget before a previously packed widget:

ordered

list.

-after => $otherwidget -before => $otherwidget

As an example,

buttons

four

create

let's

$widget4) and only pack three

$widget2,

($widgetl,

to begin with.

The pack command

$widget3,

$widget4

for

might then be: $widget4->pack( -after => $widgetl)

shows two windows: one before $widget4

Figure 2-20

$widget4

is

Figure 2-20. with

If

Done4

Done2

1

On

left:

label

we want

the

J

Done3

|

window

$widget4

:

ex»n|rie

Done4

Donel

-after

1^

Done2

On

with three buttons packed in order.

was packed using

to put



'U

exusnirie

Donel

after

packed.

^ .

packed and one

is

Done3

right: the

J J

button

=> $widgetl

in front of

$widgetl,

we

use

this

command, and see

the results in Figure 2-21. $widget4->pack{ -before => $widgetl)

exm^

d :

Figure 2-21. Button with

Done4

Done4

Donel

label

^

A

^

DoneZ

was packed using

Done3

-before

J 1

=> Sdonel

Padding the Size of the Widget The The

final

way

first set

to force

pack

to size the

widget

is

of padding options affects the widget

size. Different

amounts can be added

in the

to use the itself

padding options.

by adding to

its

default

x and y direction, or they can be

1

30

Chapter 2: Geometry Management

To specify how much padding should occur -ipadx option:

the same. the

x direction, use

in the

-ipac3x => amount

Specify padding for the y direction like

this:

-ipady => amount

The amount is

a

number

that

a valid screen distance.

is

I'll

discuss the definition of

a valid screen distance in the next section.

Both the -ipadx and -ipady options change the allocation rectangle right

and

left

is

size of the

widget before the

-ipadx adds the amount specified to both the widget. The overall width of the widget would increase

calculated,

sides of the

X amount), -ipady adds to the top and bottom of the widget, causing the overall height of the widget to increase by (2 x amount). Figure 2-22 shows how

by

the

(2

-ipadx and -ipady options

affect a button.

1

examine

7-1

Done2

^Ij Done3

Donel

|

Figure 2-22. The Donel button was created with options: -ipadx => 10, -ipady => 10

The other kind of padding

is

between the edge of the widget and the done with the -padx and -pady options:

inserted

edge of the allocation rectangle and

is

-padx => amount -pady => amount

Using -padx and -pady does not the size of the allocation rectangle. ing

it

affect the size of the widget, It

acts as a buffer

but

it

does

affect

around the widget, protect-

from having to touch other widgets. Figure 2-23 shows the

effects of using

-padx and -pady.



example .._..._

_

...±\

Done3

Ji ;

Donel

Figure 2-23. The

A good way the

"i"

to

Donel button was created with

remember

options -padx => 10, -pady => 10

the difference between

-ipadx/y and -padx/y

stands for "inside the widget" or "internal padding."

is

that

Pack

31

Valid screen distances

Many

times you'll see options that require values specified in screen units (or what

The options -ipadx and -ipady are examples Always check to see what value the option actually requires.

called a valid screen distance).

is

of this type of option.

A

screen unit

no

number followed by

a

is

a designation for the unit to use. If there

designation, the units are in pixels. Table 2-1

shows

all

is

the possibilities.

Table 2-1. Valid screen units

Designator

Meaning

Examples

(none)

Pixels (default)

20, 30, "20", "40"

c

Centimeters

'3c', '4c', "3c"

i

Inches

'2i', "3i"

m

Millimeters

'4in',

P

Printer points (1/72 inch)

"72p", '40p'

To use

these designators,

necessary to use quotes (either single or double)

is

it

"4m"

around the value. Here are some examples: $button->pack( -ipadx $button->pack -ipadx $button->pack( -ipadx $button->pack -ipadx $button->pack( -ipadx $button->pack( -ipadx (

(

Remember

ommend

=> => => => => =>

#20

pixels Also 20 pixels # 1 inch # 1 millimeter # 1 pixel #20 printer points

20) '

20

#

'

"li") 'Im') 1)

"20p");

that a "p" designator

does not stand for

pixels, but printer points.

I

rec-

always using pixels as your unit of measure. Different screens display

different resolutions;

one screen might display an

and another might

actual inch

display something else.

Displaying in a Parent Other Than Your By

default,

Sometimes

when it

is

a widget

is

packed,

it

Own

packed inside the region

is

that created

it.

necessary to display a widget inside a different region. Use the -in

option to do so: -in => $otherwindow It

puts the

displays

it

new

widget

at

the

end of the packing order

for the

accordingly. All other options specified in the

pack

$otherwindow and ( )

call still

apply.

Methods Associated with Pack There are a few methods

that are

used

in conjunction

with the

pack geometry

manager. They allow the programmer to get information about either the widget that has

been packed or the parent widget

in

which other widgets are packed.

;

;

;

Chapter 2: Geometry Manageme nt

52

Unpacking a widget

To unpack

window

widget from a

a

$widget->packForget

(

or frame, use the

packForget method:

)

packForget makes it look like the widget disappears. The widget is not destroyed, but it is no longer managed by pack. The widget is removed from the packing order, so if it were repacked later, it would appear at the end of the packing order.

Retrieving pack information

To

return a

list

containing

all

the pack-configuration information about a widget,

use packinf o: ©list = $widget->packlnf o

The format of the current

( )

The first pair in the list is -in and $widget (usually also the parent). This is an information returned from packinf o:

the

list is

window

example of the

in option/value pairs.

that contains

-in MainWindow=HASH(0x818dcf4) -anchor n -expand -padx 10 -pady 10 -side left

From

this,

we

can

than a frame. Since the result

a

from packinf o

we packed

that

tell

list

-fill none -ipadx

our $widget into the main

has a "paired" quality to

it,

we

-ipady

window

rather

could easily store the

hash and reference the different option values by using

in a

key to the hash: %packinfo = $widget->packInfo; print "Side used: ", $packinfo{-side}

Disabling

and enabling automatic

,

"\n";

resizing

When you

put a widget inside a window, the window (or frame) will resize itself accommodate the widget. If you are dynamically placing widgets inside your window while the program is running, the window will seem to bounce from size to size. You can turn off this behavior by using packPropagate on the frame or to

toplevel widget:

$widget->packPropagate

(

)

'off, packPropagate changes the behavior of the widget so that it accommodate items packed inside of it. When a false value is sent to packPropagate before widgets are placed inside it, this automatic resizing doesn't happen, so you can't see any of the widgets placed inside the parent until it is manually resized. If you call packPropogate after the widgets have If set

to

or

doesn't resize to

been placed widgets.

inside

it,

the widget will ignore any size changes from

its

child

Pack

33

Listing widgets

You can determine

the widgets your frame or toplevel holds with the

packSlaves

method: @list = $parentwidget->pack;Slaves

packSlaves

returns an ordered

$parentwidget. An empty

;

of

the widgets that

all

empty

string (or

list)

is

were packed

returned

if

into the

no widgets were

$parentwidget.

packed

into

The

returned from

list

list

( )

packSlaves looks

like this:

Tk: :Button=HASH{0x81b2970) Tk: :Button=HASH(0x8116ccc) Tk: :Button=HASH(0x81bcdd4)

Each item

is

a reference to a

packed widget and can be used

to configure

it.

For

example, you can increase the size of each widget by 20 in both the x and y directions by looping through it and "packing" it with new information. Using our good

window example tine that uses

in Figure 2-4,

we

can add a button that

will contain a

subrou-

packSlaves:

$rnw->Button{-text => "Enlarge", -command => \&repack_kids) ->pack(-side => 'bottom', -anchor => center '

'

)

sub repack_kids { m/ @kids - $mM->packSlaves; f oreach @kids { $_->pack(-ipadx => 20, -ipady => 20); {

)

}

}

Figure 2-24 shows the resulting window.

i^

much more organized, and less haphazard used some options to make it look nice

This windov/ looks

because

J

1

like

we

it!

J

1

hate

it!

j

1

don't care

Exit

EtAar^e

Window

Figure 2-24.

Let's

look

at

Figure 2-25,

before pressing Enlarge button

what happens when we press the Enlarge button. As shown the widgets are

all

now

repacked with additional parameters of

-ipady => 20. These new options are in addition to any other widgets were packed with before. If an option is repeated, the last

-ipadx => 20, parameters the

in

one specified overrides the previous ones.

;

;

,

34

.

Chapter

Good

This

J

looks

we

like

Geometry Management

WMow

AA

much more organized, and less haphazard used some options to make it look nice

window because

I

2:

J

it!

I

hate

J

It!

I

don't care

Exit

Enlarge

Figure 2-25.

Window after pressing Enlarge

button

The window is suddenly huge! Subsequent presses of the Enlarge button will do nothing more to the window because all the widgets already have an -ipadx and -ipady of 20. If we wanted to always add 20 to the values of -ipadx and -ipady, we would have to request the current values and add 20 to them. Here's the code for that: sub repack_kids { my @kids - $inw->packSlaves; @kids { f oreach %packinf o = $_->packInf o $_->pack( -ipadx => 20 + $packinfo{ "-ipadx" -ipady => 20 t $packinfo{ "-ipady" (

)

( )

}

})

} }

We

use packlnfo to get the current configuration and add 20 to that value.

Grid The grid geometry manager

umns and rows sample

into a grid

composed

of col-

upper left-hand corner. Figure 2-26 shows

a

grid.

Rather than using the sides of a screen into columns and rows.

widget

window

divides the

starting at 0,0 in the

is

assigned a grid

cell

window It

as reference points,

looks a

lot like a

grid{) divides the

spreadsheet doesn't

using the options available to

grid

( )

it?

Each

Grid

35

Column

0,

RowO

Column

1,

RowO

Column

2,

RowO

Column

0,

Rowl

Column

1,

Row

1

Column

2,

Row

Column

0,

Row

2

Column

1,

Row

2

Column

2,

Row

2

Column

0,

Row

3

Column

1,

Row

3

Column

2,

Row

3

Figure 2-26. Diagram showing

The grid

method

( )

takes a

get at a time.* Here

is

$widgetl->grid(

[

A

window divided list

1

into grid

of widgets instead of operating

on only one wid-

the generic usage: $widget2,

.

7

.

/

option => value,

]

);

specific example:

$widgetl->grid($widget2, $widget3)

you can use one gridO call to display all three widgets. You can also invoke grid() on each widget independently just as Each call to grid will create another row in the window. So you can pack in our example, $widgetl, $widget2, and $widget3 will be placed in the first row. Another call to grid would create a second row. This is what happens when you do not specify any additional options to the grid call. Instead of using three separate

( )

calls,

( )

.

( )

For greater control, you can specify explicit -row and -column options for each

widget in the window.

I

will

cover these options

later.

These assumptions are made when additional options are not

The



first

widget

in the

grid

ple) invokes the •

All

( )

row (for example, $widgetl command.

( )

preceding exam-

command.



Each additional



Special characters can

call to

grid

( )

be used

will

to

add another row

to the display.

change the -columnspan and -rowspan of

the widget without using -columnspan or -rowspan

few examples

row, so

in the

remaining widgets for that row will be specified as arguments to the

grid

A

specified:

will

we know we

help demonstrate. Each

have two rows

call to

in the following

explicitly.

gridO

will create

another

example:

Create two rows, each with four widgets $widgetl->grid($widget2, $widget3, $widget4) $widget5->grid($widget6, $widget7, $widget8) #

*

Several people have told

not

how pack

is

me

that

normally used.

pack can

also take a

list

of widgets.

I

didn't cover this

because

it

is

)

;

36

Chapter 2: Geometry Management

we

In this example,

have created four rows and there

is

only one widget in each

row: Create four rows, each with one widget $widgetl->grid( $widget2 ->grid $widget3 ->grid $widget4->grid #

(

(

(

We

can also create widgets as

we

go:

$rnw->Button(-text => 'Buttonl', -command => $mw->Button(-text => 'Button2', $raw->Button(-text => 'Button3', $mw->Button(-text => 'Button4',

\&calll) ->grid( -command => \&call2), -command => \&call3), -command => \&call4)

)

third, and fourth calls to Button are All four of the buttons will be placed in the first row. If grid same exact command again, the new widgets would be placed in

Pay careful attention because the second, inside the call to

we

executed the

( )

.

the next row.

Special Characters There are several special characters that can be used to are gridded in the that indicates "

-

"

window. Each

what

to

do with

way

alter the

the widgets

special character serves as a type of placeholder

that position in the grid:

minus sign)

(a

Tells grid that the this

column

widget specified

as well.

get position to span.

right before this

one

To span more than one column,

A

"-"

may

in the

place a

"

should span

list

-

"

in

each wid-

not follow a "^" or an "x".

"X" Effectively leaves a blank space II

/S

where

a widget

would otherwise be

placed.

II

A

the II

x will span row x and jc + 1 when this character is placed grid command for row jc + 1 in that row/column position. The number

of

row

x.

widget in row -^

••

characters must match the

Similar to "-", but goes

The following

number

down, not

sections include

of columns the widget spans in

in

across.*

some examples

that illustrate

what the

special char-

acters do.



so

'"'" with Tk4.002, I got I used the special character you get this error also, check which version you have.

when if

a nasty core

dump. This

is

fixed in TkS.O,

37

Grid

Spanning columns

The following bit of code creates three rows of buttons. The first two rows are normal, and in the third, the second button spans three columns. Each "-" character adds one to the number of columns the button uses, and the default is 1. So the original column and two hyphens ("-"/•-") indicate that there are three columns to span. The -sticky option is necessary for the widgets to stick to the sides of the cells it spans. If the -sticky option had been left out, the button would be centered across the three cells it spans. $mw->Button(-text => ($mw->Button(-text $mw->Button(-text $mw->Button(-text

"Buttonl", -command => => "Button2", -command => "ButtonS", -command => "Button4", -command

sub

$mw->Button(-text => ($mw->Button(-text $mw->Button(-text $mw->Button(-text

"ButtonS", -command => => "Button6", -command => "Button?", -command => "ButtonS", -command

sub { exit } ->grid => sub { exit }), => sub { exit }), => sub { exit }));

exit } ->grid exit }), { exit }), { exit } { )

{

=> sub => sub => sub

)

)

)

$mw->Button(-text => "Button9", -command => sub { exit } ->grid $raw->Button -text => "ButtonlO", -command => sub { exit }), "-", "-", -sticky => "nsew"); )

(

(

The

resulting

window

is

shown

in Figure 2-27.

Buttonl

Buttons

Buttons

1

ButtonZ

Button3

Button4

Buttons

Button?

ButtonB


"nsew" •;

(

(

)

^

€Mf Buttonl

ButtonZ

Buttons

^tton€

E)Biimite

,

Hi J

Buttons

BultWl4

Button?

Buttona 1

Figure 2-32. grid -padx

and -pady example

Specifying a Different Parent The -in option works the same way it does in pack(). The $widgec wiii be placed in $ot±ierwindow and not in the default parent of $widget. Here is the usage: -in => $otherwindow

Configuring Columns

and Rows

As with any of the geometry managers, grid has a few methods ated with

it.

Each method

screen by using

group of

is

Sometimes it grid makes up your grid.

cells that

( )

.

that are associ-

invoked via a widget that has been placed on the is

necessary to change the options of the

Grid

43

control resizing and the minimum size of a cell with the gridColumnconfigure and gridRowconfigure methods. Each takes a column or a row number as its first argument and then takes some optional arguments that will change the configuration of that column or row.

You can

Both gridColuranconfigure and gridRowconfigure work very similar to the

configure method used with

configure method used with and command. The options you gridRowconfigure cannot be used with the grid can use with gridColiomnconfigure and gridRowconfigure are -weight, widgets. Unlike the

widgets, however, the options you can specif}^ with gridCol\jinnconf igure ( )

-ininsize, and -pad. If

you send only

a

row

or

column number, an

array

is

returned with the current

options and their values for that method: @column_configs = $mw->gridColuiTinconf igure(O) @row_configs = $inw->gridRowconfigure(0) In this example,

and the

first

are getting the options

and

their values for the

first

row. The results of using the default values would look like

-minsize -minsize

You can

we

;

-pad -pad

column

this:

-weight -weight

get the value of only

one of the options by sending

that option as the

second argument: print $inw->gridColiiiTinconfigure(0, -weight), "\n"; print $rnw->gridRowconfigure(0, -weight), "\n";

The

results

To change

would

be:

the value of the options, use the option and then the value

associated with

it

immediately

after the option; for

-weight => $inw->gridRowconfigure(0, -weight => 1) $rnw->gridColuinnconfigure(0,

You can

also specify multiple options in

1)

you want

example:

;

;

one

call:

-weight => 1, -pad => 10); $inw->gridRowconfigure(0, -weight => 1, -pad => 10); $ir[w->gridColuitinconfigvire(0,

Now

that

we need

we know how to call gridColuranconfigure and gridRowconfigure, know what the three different options do.

to

Weight

The -weight option

when

the

window

is

sets

how much

divided into

space

cells.

is

to

be allocated to

Remember

to use

that

column or row

-sticky => "nsew"

in

)

;

;

;

;

44

Chapter 2: Geometry Management

grid command if you want the widget to resize when the cell does. The -weight is 0, which causes the column width or row height to be dictated by the largest widget in the column. Each -weight value has a relationship to the your

( )

default

other

-weights

in the

rows or columns.

column or row has a -weight of 2, it is twice has a -weight of 1. Columns or rows of -weight want all your widgets to resize in proportion to the your code before you call MainLoop: If

a

($columns, $rows) = $mw->gridSize() for ($i = 0; $i < $col\ainns; $i++) { $iiw->gridColuninconfigure($i, -weight =>

1)

column or row

as big as a

don't get resized at

all. If

window, add

size of the

that

you

this to

;

}

for ($i = 0; $i < $rows; $i++) { $mw->gridRowconfig\ire ($i, -weight => 1); }

-weight of 1 to every single row and column in the grid, is. Of course, this method only works if you want to each row and each column, but you get the idea.

This code will assign the

no matter what assign the same Here

size the grid size to

an example of

is

how

the

-weight

option works (Figure 2-33 shows the

result):

$inw->Button(-text => "Buttonl", -coinmand => ($iTiw->Button(-text => "Button2", -coinmand $inw->Button(-text => "Button3", -command $mw->Button(-text => "Button4", -command -sticky => "nsew"

sub { exit } ->grid => sub { exit }), => sub { exit }), => sub { exit }), )

)

$inw->Button(-text => "Button5", \

-coitiraand

=> sub

{

X $mw->Button -text -> "ButtonV", -command => s\ib $mw->Button -text => "Buttons", -command => sub -sticky => "nsew"

exit

}

)

->gr

,

(

(

exit }), exit }),

{ {

;

$mw->gridColumnconfigure(l, -weight => $mw->gridRowconfigure(l, -weight => 1)

By

giving

1

and column

1

a weight of

1

(whereas

all

weight), they take over any extra available space

have

dow

row

1)

other rows and columns

when

and 3 are only to draw the buttons and their text, but column 1 has filled same effect happens for row with a weight of and row 1.

is

(The

increased. Notice that

window

columns

0, 2,

as

the size of the win-

wide

as

is

necessary

in the extra space. 1

with a

new

The

weight of

has been resized larger to demonstrate the effects of -weight.)

45

Grid

GrtdExanf^ite

S3J'^

Buttoni

Buttons

Figure 2-33- gridRowconfigure

Minimum

J

1'

ButtonZ

Buttons

Button4

Button?

Buttona

and gridColumnconfigure example

cell size

The option -minsize sets the smallest width for the column or the smallest height for each row. The -minsize option takes a valid screen distance as a value. In this example, the minimum size of the cells in row and column is set to 10 pixels:

-minsize => 10); $inw->gridRowconfigure(0, -minsize => 10); $iTiw->gridColuiTinconfigure(0,

column or row was normally forced to be at least that large. If

the

less

than 10 pixels wide, then

it

would be

Padding

You can add padding around the widget and to the widget by using the -padx/y and -ipadx/y options. You can also add a similar type of padding by using the -pad option with the gridColumnconfigure and gridRowconfigure methods. The padding is added around the widget, not to the widget itself. When you call gridColumnconfigure, the -pad option will add padding to the left and right of the widget. Calling gridRowconfigure with -pad will add padding to the top and bottom of the widget. Here are two examples: $mw->gridColumnconfigure(0, -pad => 10); $mw->gridRowconfigure(0, -pad => 10);

Bounding box

To

find out

how

($xoffset,

large a cell

is,

you can use the gridBbox method:

$yoffset, $width,

$height) = $master->gridBbox(0, 2);

This example gets the bounding box for column

returned are in pixels.

The bounding box

will

and row

change as you

2.

All

resize the

the values

window. The

four values returned represent the x offset, the y offset, the cell width, and the cell

height (offsets are relative to the

window

or frame

where the widget

is

gridded).

; ;

;

;

;

46

Chapter 2: Geometry Management

Removing a Widget Like

packForget, gridForget causes the widget(s)

the screen. This the size of

may

or

may

not cause the

$widget and where

$rnw->gridForget

)

(

it

was on #

;

$widget->gridForget $widget->gridForget ($widgetl) $widget->gridForget $wl $w3); ( )

(

The widgets

are

,

undrawn from

#

# #

window

the

to

be removed from view on

to resize

window. Here

itself;

are

it

depends on

some examples:

Nothing happens $widget goes away $widget and $widgetl go away $widget, $wl, $w3 go away

the screen, but the cells they occupied remain.

Getting Information The gridlnfo method returns information about the $widget in a list format. Just as with packinf o, the first two elements indicate where the widget was placed: @list = $widget->gridlnf o

Here are some sample

(

)

from gridlnfo:

results

-in Tk: :Frame=HASH(0x81abc44) -column -row -coluninspan -ipadx -ipady -padx -pady -sticky nesw

1

-rowspan

2

Widget Location The gridLocation method

returns the

column and row of the widget nearest

the given (x, y) coordinates: ($column,

$row)

= $inaster->gridLocation($x,

Both $x and $y are ples, $inw).

$y)

in screen units relative to the

For locations above or to the

When

given the arguments

which

indicates the cell at

(0, 0),

left

master

of the grid,

our application returned

column

and row

window

-1 is

(in

our exam-

returned.

this:

0.

Propagation There

is

a

gridPropagate method

$master->gridPropagate

When

(

that

is

similar to

packPropagate:

)

given a false value, gridPropagate turns off geometry propagation, mean-

ing size information

propagation

is

rent value

returned.

is

is

not sent upward to the parent of $master. By default,

turned on.

If

gridPropagate

is

not given an argument, the cur-

47

Place

How Many Columns and Rows? To

find out

how

large the grid has

you can use gridSize

become

after placing

numerous widgets

in

it,

back the number of columns and the number of

to get

rows: ($coluiTins,

The

list

many

$rows)

= $inaster->gridSize

returned contains the

number

)

;

number of rows. In was four columns by two

of columns and then the

we had

of the earlier examples,

(

a grid size that

rows. ($c, It

$r)

= $f->gridSize();

#$c

=4,

$r =

2

not necessary for a widget to be placed in a column/row for

is

sidered a valid column/row.

If

-row=>5, -column=>4 and then

gridSize

you place

and

will return 5

a widget in

the only other widget

it

to

be con-

column 4 and row 5 using in row and column 0,

is

6.

Grid Slaves There are two ways to find out which widgets have been put frame. Use

gridSlaves without any arguments

to get the full

list

in a

window

or specify a

or

row

and column. Here are examples of both: ©slaves = $mw->gridSlaves print "@slaves\n"

( )

The preceding code would have printed

this:

Tk: :Button=HASH(0x81b6fb8) Tk: :Button=HASH(0x81ba454) Tk: :Button=HASH(0x81ba4cc) Tk: :Button=HASH(0x81ba538) Tk: :Button=HASH(0x81b6fa0) Tk: :Button=HASH(0x81ba5e0) Tk: :Button=HASH(0x81ba6dc) Tk: :Button=HASH(0x81ba748)

We

could have specified the widget in column

0,

row

0:

$widget = $niw->gridSlaves -row => 0, -column => print "$widget\n" # Would print this: Tk: :Button=HASH(0x81b6fb8) (

If

)

;

you specify only the -row option, you'll get a list containing only the widgets in The same goes for only specifying a -coluinn; your list will contain only

that row.

the widgets in that column.

Place The place

( )

geometry manager

is

different than

grid

( )

or

pack

( )

.

Rather than

referencing against a cell location or a window's side, most of the time you'll be

'

.

Chapter 2: Geometry Management

'^8

You can also grid

using a relative form of x and y coordinates. lap portions of widgets,

Invoking place

$widget->place

The options

[

(

isn't

allowed

in either

similar to calling the other

is

( )

which

specified

option => value,

when you

.

.

place

call

]

.

( )

use place or

pack

( )

to over-

( )

geometry managers: );

affect

( )

how

the widgets are put

on

the screen.

Place Options -anchor => center

'n'

|

'ne'

'e'

|

|

'se'

|

's'

'sw'

|

'w'

|

|

'nw'

|

'

Sets the position in the

widget that

-bordermode => 'Inside'

|

will

be placed

'outside'

at

the specified coordinates.

'ignore'

|

Determines whether or not the border portion of the widget

is

included in the

coordinate system.

-height => amount Sets the absolute height of the widget.

-in => $window Indicates that the child widget will

parent that created

it.

Any

be packed inside $window instead of

relative coordinates or sizes will

still

in the

refer to the

parent.

-relheight =>

ratio

Indicates that the height of the widget relates to the parent widget's height

by

ratio.

-relwidth =>

ratio

Indicates that the width of the widget relates to the parent widget's width ratio.

-relx => xratio Indicates that the widget will be placed relative to

its

parent by xratio.

its

parent by yratio.

-rely => yratio Indicates that the widget will be placed relative to

-width => amount Indicates that the width of the widget will

be amount.

-X => X Indicates that the widget will be placed at

x x is

any valid screen distance.

-y =>y Indicates that the widget will be placed at y.

y is any

valid screen distance.

by

49

Place

Absolute Coordinates The parent window

(or frame) has a standard coordinate system

the upper-left comer. as

The x values increase

you go down. See Figure

where

0,0

is

in

and the y values increase

2-34.

Figure 2-34. Coordinate system ofparent

To use

to the right,

window when

absolute coordinates to specify

where

absolute coordinates are used

to place the widget,

we would

use

options -X and -y: -X => X, -y =>

y

x and y are valid screen distances (for example, 5, which is in pixThe widget will have its anchor position (controlled by -anchor) placed at X and y coordinates. The default anchor is "nw"; the upper-left corner of the

Valid values for els).

the

widget.

Another major difference between place

() and the other geometry managers is two arguments are required when place () is invoked. There are no default values for the -x and -y options You will get an error if you try to invoke place with no arguments (for example, $widget->place()).

that at least

.

The simplest example of using -x and -y $mw->Button(-text -> "Exit", -command => sub

{

is

exit })->place(-x =>

As you would expect, the widget ends up as

shown

positioned

widget

0,

at 0,0:

-y =>

0)

in the upper-left corner of the

No matter what size Even when the window

in Figure 2-35. at (0,0).

to place a

the is

window, our widget

window

will

move.

widget

will not

Here

an example of using -x and -y to create some overlapping widgets:

is

$mw->Button(-text => -command $mw->Button(-text => -command

"Exit", => sub

{

exit })->place(-x => 10, -y => 10);

"Exit", => sub

{

exit })->place(-x => 20, -y => 20);

Figure 2-36 shows the resulting window.

remain

resized as small as possible, the

50

Chapter

2:

Geometry Management

1

^

Place

^,HI

Exaii^

Exit

1

Figure 2-35- Button placed using -x =>

-i

.

-y

0,

=>

Race Example

1^ Ji

Exit

Figure 2-36. Overlapping buttons with placeO

Relative Coordinates In

place

( )

,

there

is

an additional coordinate system defined for the parent wid-

get that allows relative placement within

it.

This coordinate system

is

shown

in

Figure 2-37.

x=

0.0

y=

0.0

"

child widget

nw

n

ne

w

center

e

sw

s

se

x=1.0 y=1.U Figure 2-3 7. The relative coordinate system

The

upper-left corner has the coordinates (0.0,0.0).

coordinates are (1.0,

1.0).

The middle of

the

The lower-right

window would be

coordinates are specified in floating point form to allow size

window. This allows the widget to remain no matter how the window is resized.

instance)

at that

place

( )

corner's

(0.5, 0.5).

to handle

The any

position (in the center, for

51

Place

It

valid to specify coordinates both smaller than 0.0

is

ever,

your widget most

you use

likely

out-of- range coordinates.

shown

in Figure 2-38:

$b = $rnw->Button(-text => "Exit", -command => sub $b->place(-relx => 0.5, -rely => 0.5);

Figure 2-38. Using place with -relx =>

Although the button

0.5, -rely

in Figure 2-38

is

window ril

instead of the center.

discuss shortly.

middle of the

window

If

we

{

exit

}

)

=> 0.5

placed in the middle of the screen,

off-center because the upper-left corner of the widget

the

Howwindow when

larger than 1.0.

won't be completely visible in the

This code snippet produces the button

which

and

You can change

resize this

was placed

this

in the

it

looks

middle of

with the -anchor option,

window, the button

still

stays in the

(see Figure 2-39).

-

^

Race Exanf^

J

Exit

Figure 2-39- -relx =>

0.5, -rely

=> 0.5 window resized larger

This next example creates two buttons, both placed in the

window

with relative

coordinates:

No

$mw->Button(-text -> "Exit", -command => siib

{

exit

}

$mw->Button(-text => "Exit", -command => sub

{

exit

}

matter what two buttons will

size the

window

is

or

)

)

->place -relx => 0.2, -rely => 0.2); (

->place(-relx => 0.5, -rely => 0.5)

where other widgets

are in the screen, the

stay in those relative locations (see Figure 2-40).

52

Chapter

Figure 2-40.

The ated. it

left

It

relative to the parent

window in Figure 2-40 right window is what smaller. Notice that

does so because

we

are

is

also

window

the default size of the

still

maintaining the ordered

window; the second Exit button (placed above the other button.

You can

Geometry Management

window when it was creit looks like after the window was resized to make the second button placed in the window remains on

The

much

top.

Two buttons placed

2:

at 0.5,0.5) is

list

drawn

of widgets in the

so

last,

it's

drawn

combine the absolute and

using both in the argument

relative coordinate systems simply by The relative coordinate system is considered first, added to that position. The options -relx => 0.5,

list.

and then the x or y value is -X => -10 means to place the widget 10 pixels

to the left of the

middle of the

window.

Anchoring the Widget Think of the child widget as a piece of paper tin

board (the board

is

that

you want

You have a You can put

the parent widget).

use to keep the paper up on the board.

to put

tack that

on your

you

bulle-

are going to

the tack right through the

comer The point where the tack is going to stick the paper to the board is the -anchor point. The -anchor point on the widget is "tacked" to the coordinates given by -x, -y or -relx, -rely. The default -anchor is "nw". Figure 2-37 shows these -anchor points within the child widget. center of the paper, in the upper-left corner ("nw"), or in the lower-right

("se").

It

is

important to

know where

the widget within the parent.

the

-anchor

is

because

it

will affect

how we

see

53

Place

^

Fface EK^npqple

^jj

-I

Flace Examtrie

^^

^

Exit

Exit

Figure 2-41. Different -anchor values affect where the widget In Figure 2-41, almost identical place

is

placed in the window

commands were used

in the window, but the -anchor value was changed. The was created with this command:

$inw->Button(-text => "Exit", -coinmand => sub

The window on the

exit

right in Figure 2-41

$rnw->Button(-text

}

)

left

->place(-relx => 0.5, -rely => 0.5)

used

this

window's button

;

command:

"Exit",

==>

-command =>

As with

{

to put the Exit button

siib

packO and gridO,

{

exit

}

)

->place(-relx => 0.5, -anchor => " center " -rely => 0.5)

the possible values for

-anchor

are:

'center', 'nw', 'sw', 'ne', and 'se'. However, the value

'w',

'n', 'e', 's',

now

applies to

the child widget instead of the position within the allocation rectangle.

Width and Height When you

use place

( )

,

you can specify the width and height of the widget

in

one of three ways:

own



Allow the widget



Specify width and/or height in absolute measurements.



to determine

its

size.

Specify width and/or height in relative measurements (relative to the parent widget).

To

let

the widgets determine their

own

other ways involve the options -width,

no options are specified at all. The -height and -relwidth, -relheight

size,

respectively.

The -width and -height options allow you of the widget in a screen distance: -width => amount, -height => amount

to specify the exact

width or height

;

54

Chapter 2: Geometry Management

Each amount

is

a valid screen distance (discussed eariier in this chapter

pack). The widget will be these sizes even

played in

it.

Our button looks

quite

silly

if it

under

cuts off edges of the items dis-

on the screen when we use

a

-width of

40 pixels (see Figure 2-42). $iTiw->Button(-text => "This Button Will Cause the Program to Exit", -command => sub { exit })->place(-x => 0, -y => 0, -width => 40)

Figure 2-42. Using -width with placeO

The other two

options,

-relwidth and -relheight, determine

the widget in

relation to the parent widget.

-relwidth => ratio, -relheight => ratio

The

A

ratio

is

number (similar to that specified by -relx or -rely). make the widget as wide (or as tall) as the parent widget. A make the widget half as wide as the parent (see Figure 2-43).

a floating point

value of 1.0 will

value of 0.5 will

f^i^e

Exan^iie

j

Hace Example

j]

Exit

Exit

Figure 2-43- Example of the

H-f

same window

The options -width and -relwidth -height and -relheight.

resized with -relwidth => 0.5, -relheight => 0.5

are additive

when used

together,

and so are

Border Options Normally, the border of the widget

is

used as the edge of the possible space

window, which means any widgets placed with

in the

either the absolute or relative

55

Place

coordinate system will be placed inside the border. This can be changed by using the

-bordermode

option:

-bordermode => 'inside'

'outside'

'

ignore

Using 'outside' will allow the coordinate system to use the space occupied by the border as well.

A

value of 'ignore' will have the coordinate system use the

space designated as the

X

official

area. Overall, this option

can see from the difference each makes on our example

is

pretty useless, as

you

in Figure 2-44.

Figure 2-44. -bordermode examples

If

you look very

closely (get out your magnifying glass),

'outside' version

is

'inside' version. This

two is

pixels higher

because on

and two

you can see

pixels to the

my window manager

(fvwni),

left

my

that the

than the

border

is

defined as 2 pixels.

Methods Associated with Place The methods

for

place

( )

are simple

and don't allow much manipulation of the

widgets.

Removing

the widget

As with pack and grid, there $widget->placeForget If

you use

the screen.

this It is

is

a

place

version of the

Forget method:

{ )

method on the widget, the widget will be removed from view on also removed from the list maintained by the parent widget.

Place information

The placeinf o method

returns a

@info = $widget->placelnf o print "@info"; ## Produced these results

-X

-relx

-y

-rely

list

of information related to the widget:

( )

(there are blanks where there are no values) -relwidth -height -relheight -anchor nw

-width

Place slaves @widgets = $parent->placeSlaves

( )

56

Chapter

2:

Geometry Management

placeSlaves returns a list of the slave widgets that are within $parent. The list looks the same as it does when it is returned from packSlaves or gridSlaves .X ( )

( )

Geometry Management Summary You now know more about the three need to know to write a successful hints •

different

( )

is

good

for general

you'll ever

some

Perl/Tk application. Here are

on deciding which geometry manager

pack

geometry managers than

helpful

to use:

purpose use and

will

be your choice around 95%

of the time. •

gridO

is

perfect for those situations in

columnar layout •

place

( )

size that it



is is

that

is

which you would

like to create a

similar to a spreadsheet.

most useful when you want your widgets relative to the

widget that created them.

to stay in a position or

When

it is

used

correctly,

can be very powerful.

No matter which manager you use, take the time to get the widgets on your window where they belong (or more likely, where you want them). There's nothing more unsettling than a button that looks like the

it

just doesn't

belong

in

window.

As you read through

this

book, you'll notice that some of the option names for the

geometry managers are also option names when you are creating or configuring

a

widget type. For example, you can specify the -width of a button without using

place

( )

.

Always keep

in

mind the context

times the functional difference

is

very subtle.

in

which the option

is

used.

Some-

The Basic Button

The Button Widget -^1^'

*^

..-

.

\.

Button Wfdget

S

Of

of the wideets available with Perl/Tk, the button

all

^, ,

,

the most commonly used. Geometry Management When the button _-.»™_™,-_.,-«™™™J

Just see

,

,

the examples

(as in

The button

one of 2,

our Hello World example) to

beginning a longer series of operations such as opening a process.

is

Chapter

in

pressed, something happens. That

is

something can vary from exiting the program

„ all

typically displays a short text string:

or starting another

file

Done, Apply, Save, Ok,

Exit.

Other widgets are also

as

classified

checkbuttons, and

radiobuttons,

buttons:

menubuttons. This chapter covers the traditional button. Chapter

and Radiobuttons, and Chapter

11

Menus,

,

will

4,

Checkbuttons

cover the other types because they

look different on the screen and behave differently as well.

We

cover the button widget

on the

screen.

affect

it

same

options. Usually,

will also

first

Many if

because

the option

be the same (more or

it

is

way

easy to see the

different options

of the other widgets included in Perl/Tk utilize the

name

is

the same, the change to the widget

less).

Creating a Button The

basic usage to create a button

is

$button = $parentwidget->Button

We

(

as follows: I

option => value,

have already seen examples of buttons

Chapter

1,

and

in all the

examples, a button

is

in

.

on the screen with

$niw->Button(-text => "Done" -coinmand => sub ,

{

.

]

);

our Hello World program

geometry management examples

created and placed

.

in

Chapter

a

command

2.

in

In these

like this:

exit })->pack;

57

58

Chapter 3' The Basic Button

You can

save a reference to the button like

this:

$button = $nw->Button(-text => "Done" -coinmand => sub ,

we

In Hello World,

need

didn't

ated

assume

exit })->pack;

to refer to the button again later, so

have made sense to save a reference ter will

{

to

wouldn't

it

But most of the examples for

it.

this

we've saved a reference to the button widget when

that

chap-

we

cre-

it.

Button Options The

chapter covers the options available to change the look of the but-

rest of this

ton and

how

to

make

it

do what you want.

-activebackground => Sets the color the

button.

A

color

is

color

background should be when the mouse cursor

-activeforeground => Sets the color the text

-anchor => center '

'n'

|

over the

color

should be

'ne'

|

'e'

when |

the

'se'

mouse |

cursor

's'

is

'sw'

\

over the button. |

'w'

|

'nw'

|

'

Causes the text to

-background => Sets the

is

a text string such as "red".

stick to the specified position in the button.

color

background of the button

to color.

-bitmap => 'bitmapname' Sets default

bitmap or the location of a bitmap

(with @ in front of path).

file

-borderwidth => amount Changes the width of the edge drawn around the button. (Emphasizes the -relief.) -command => callback Indicates a pointer to a function that will

-cursor => 'cursomame' Indicates that the mouse cursor

will

be called when the button

change

to

'

cursomame

the button.

-disabledforeground =>

color

Sets the color the text should

-font => 'fontname' Changes the font of

-foreground => Changes the

all

be when the button

the text

color

text color to color.

on the

button.

is

disabled.

'

is

pressed.

when over

59

The Button Widget

-height => amount Sets the height of the button in characters

distance

if

an image or bitmap

-highlightbackground =>

if

text

is

displayed,

and the screen

displayed.

is

color

behind the focus rectangle (shows

Sets the color of the area

when widget

does not have focus).

-highlightcolor =>

color

Sets the color of the focus rectangle.

-highlight thickness => amount Sets the thickness of the black box around

the button; indicates focus.

-image => $imgptr $ imgptr

is

a pointer to an

Image object

that

was made with

a

PPM/PGM

GIF or

file.

-justify => 'left'

'right'

|

-padx => amount Adds extra space

to the

left

'center'

|

Sets the side of the button against

which

and

multiline text will justify

itself.

right side of the button inside the button

edge.

-pady => amount Adds extra space

to the top

-relief => 'flat' Changes the

and bottom of the button inside the button edge.

'groove' 'raised' 'ridge' type of edges drawn around the button |

|

-state => 'normal'

'disabled'

|

|

|

'sunken'

|

'solid'

'active'

Indicates the button's state of responsiveness.

If set to

"disabled", the

but-

ton does not respond.

-takefocus =>

|

1

|

undef

Indicates that the button will never get focus (0), always get focus (1), or let

the application decide (undef).

-text => 'text' Sets the text string displayed

on the

button.

-textvariable => \$variable Pointer to a variable containing text to be displayed in button. Button text will

change as $variable does.

-underline => n Underlines the wth character in the text character

when

button has the focus.

string.

Allows keyboard input via that

60

Chapter 3' The Basic Button

-width => amount Sets the

width of the button

distance

if

in characters

an image or bitmap

is

if

text

is

displayed and as a screen

displayed.

-wraplength => amount

maximum amount

Sets the screen distance for the

of text displayed

on one

line. Default: 0.

Displaying Text know what

For the user to

when

the button does

cate the function of the button with

its

pressed, you need to indiThe option that does this is

it's

text string.

-text: -text => 'text'

When you the key.

come up with a descriptive text string, short and simple is want your button to take over the whole window with a long

are trying to

You

don't

text string.

The

string

can be anything: alphanumeric, newline(s), or variables. Just

other string in Perl, ble quotes,

the option

is

it

is

if it is

put in single quotes,

interpolated.

parsed).

If

The

it

is

interpolation only

taken

literally,

happens once (the

the variable changes later in the program,

like

any

and with dou-

it

first

time

has no effect

on the text in the button. The only way the text in the button can be changed after it has been created is by using the configure method to reset it (e.g., $button-> configure (-text => "newtext" or by using the -textvariable option. )

There

is

no

-text

is

not specified.

default for the

-text

; )

option; the button will simply have

no

text

if

The other way to display text on the button is by using the -textvariable option. The -textvariable option allows a scalar variable to be associated with the button; anything in the variable will be displayed on the button. Specify the scalar variable as follows:

-textvariable => \$variable

This

means the

change.

When

text of the button will

change as the contents of $variable

the text within the button changes, the button

or smaller, and the entire This piece of code

window may change

may become

size.

shows how the -textvariable option

is

used:

$count = 0; $mw->Button(-text -> "Add 1", -coinmand => sub { $count++ } ->pack(-side => 'left'); $mw->Button( -textvariable => \$count) ->pack(-side => 'left'); $inw->Button(-text => "Exit", -command => sub { exit } ->pack(-side => 'left'); )

)

larger

The Button Widget

61

shows two windows. The first window shows how it looks when it is first created, and the second window shows what it looks like after clicking on the "Add 1" button many times. Figure 3-1

1

.^

Biittori

Addl

Exani|^B|§ 1

1

-i Ghitton

Addl

Exit

1

Example IS

^

J

Exit

j

1

Figure 3-1- Example of using -textvariable

Displaying an Image or Bitmap Instead of Text Instead of displaying a text string

on the

button,

you can use the -image option

to

display an image: -image => $imgptr

GIF and images

PPM/PGM

module (Tk::JPEG), which

CPAN. Other types of images are are being developed. Check CPAN

When

JPEG download from more modules like Tk::JPEG

formats are valid image types. Support

in a separate

is

also supported as to see

what

is

is

available for

available for

currently available.

using an image, only the image will be displayed because the button can dis-

To create an $imgptr variable, use the Photo method (and supply the name and path if the image is not in the current directory) of the image fUe. The $imgptr is passed in as a value to the -image option: play only a text string or an image, not both.

$arrow = $niw->Photo(-file => "Xcamel.gif " $iitw->Button(-text => 'Exit', -command => sub -image => $ arrow) ->pack; )

;

{

exit

Figure 3-2 shows an example of a button with a GIF

_J Pf

J

file

},

on

it.*

J

Figure 3-2. Button with image instead of text

Use the -bit:map option

to allow a button to display a

bitmap specified

in a text

string:

-bitmap =>

*

'

hitmapnaiae'

When I tried this example under the Windows 95 OS, didn't get a good colonnap of the GIF file. Tlie probmy video card or video driver for Windows 95, so might look better on your machine.

lem may have been

I

it

,

62

Chapter 3: The Basic Button

There are several default bitmaps: error, grayl2, gray25, graySO, gray75, hourglass, info, questhead, question, and warning (see Figure 3-3). They are specified in the option by placing single quotes around the bitmap name: $rnw->Button( -bitmap => 'error',

To

specify a bitmap from a

file,

$iTiw->Button( -bitmap =>

-command => \&handle_error) ->pack;

you need

an ©

to put

in front of the path.

@/usr/nwalsh/mybitmap' -command => sub { exit })->pack;

Note (e.g.,

'

you use double quotes, you have "\@/usr/nwalsh/mybitimap")-

that, if

Figure 3-3-

Window showing

all the default

to escape the @ with a backslash,

bitmaps

Assigning a Callback In addition to the

-text

option, the

-command option

is

almost always used to

do something when pressed, we have to associ-command option. The callback happens when mouse button 1 is released over the button.' If you click down on the button but move the cursor away from the button before releasing, nothing happens because the mouse-click was aborted. create a button. For the button to

ate a callback with the button via the

In the Hello

World program, we used the exit routine

$mw->Button(-text => "Done", -command => sub

{

There are several ways to associate a subroutine or ton. This discussion will will see this

apply to

all

as our callback:

exit })->pack; set of

commands with

the but-

widgets that have a -command option, so you

option referred to often.

Defining a

-command Callback

There are several ways the callback can be defined: •

Anonymous



Reference to a subroutine:



Anonymous list

subroutine:

list

with the

e.g.,

sub

e.g.,

first

.

.

do something

.

.

}

\&rnysub

element as a subroutine pointer, and the

as arguments to the subroutine:

Mou.se button 1 is the Icftmo.st mou.sc buttcjn, button 3 is the rightmost moLise button. •

{

[

\&mysub, $argO, $argl,

mouse button

2

is

the middle

mouse

rest

of the

\@arg2

button,

.

.

.

]

and mouse

The Button Widget

63

The button we created in our Hello World program used an anonymous subroutine. Here is the code again: $mw->Button(-text => "Done", -command => sub

We

also could

})->pack;

exit;

have created the anonymous subroutine prior to the button

and sent the reference

ation

{

to

it

instead:

exit } { $mw->Button(-text => "Done", -command => $inysubref = s\ib

;

$rrr/s\ibref )

->pack;

This is useful when our anonymous subroutine does some fancy would look awkward shoved into the list of arguments.

We

things

could also create a regular subroutine to handle the exit and then

reference to

cre-

just

and

it

pass a

it:

do_exit { &do_something_else

Slab

exit; }

$mw->Button(-text => "Done", -command => \&do_exit )->pack; It

a

is

good

idea to use a subroutine like this

exit the application.

menu, If

a button, or the

we need

mous

list

to pass

if

you have more than one way

to

For instance, you could set up your application to exit via a

window manager

Close

arguments to our do_exit

command. ( )

routine

we would

use the anony-

form:

sub do_exit

{

my ($argl, $arg2)

= @_;

&do_something_else if ($argl = 12); exit; }

$mw->Button(-text => "Done", -command => \&do_exit, $argl, $arg2 [

It is

important to remember

scope and which

variables

how

the different

you can

ways

)

]

->pack;

to specify a callback affect the

access.

Anonymous subroutines Anonymous

subroutines merely get "set aside" to be called later from within

MainLoop. The commands inside the anonymous subroutine are not parsed then.

Any

variables

f oreach

you use

will not

©names { $mw->Button(-text => $_, -command => sub

}

(

be evaluated

until that time.

)

{

print "$_ was pressed! \n"; })->pack;

until

;

64

Chapter 3: The Basic Button

we are using the $_ variable in the for each loop. The be set as expected because the $_ is evaluated when the However, the $_ that is inside the scope of the anonymous sub-

In the preceding code, button's text string will

button

is

created.

routine doesn't get evaluated until the button

could be undefined and errors

start printing

is

actually pressed. At that point,

$_

out every time you click the button.

Subroutine references: arguments or no arguments

The subroutine reference and

the

anonymous

are very similar except the

list

list

allows additional arguments (especially ones from within the current scope) to be sent to the subroutine: f oreach

©names { $inw->Button(-text => $_, -coitmand => (

)

\&print_name, $_

[

]

)

->pack;

}

sub print_naine { print "$_[0] was pressed! \n" }

The anonymous that

$_

in the

set to the

list

gets created during the call to create the button. This

means

evaluated within the context of the f oreach loop and will be

list is

same value

-text option

as the

uses.

Those of you who are comfortable with creating anonymous subroutines on the fly can also do it this way: f oreach

©names { $mw->Button(-text => $_, -command => {

)

sub

[

$_

print "$_[0] was pressed! \n";

{ )

]

},

->pack;

}

The anonymous subroutine

is

the

first

item in the

list

list is the argument $_. Keep in more than a single print statement in the subroutine, and makes sense to put it in a named subroutine.

the second item in the

want

a lot

ity, it

This

-command option, and mind that sometimes you'll

to the

is

Perl/Tk.

for readabil-

meant to be a brief overview of anonymous subroutines as it relates to The Camel Book* has all the information you would ever want and more.

Disabling a Button When

a button

The button

will

is

created,

assigned callback

when

-state => "normal"

Technically

it

shows up on the screen by

default,

change colors when the mouse passes over

known

as

pushed. I

You can change

"disabled"

Programming

I

this

it

and

ready for action. will

perform the

by using the -state option:

"active"

Perl, also available

from O'Reilly

&

Associates, Inc.

The Button Widget

65

is when the mouse The "disabled" state is when the button appears grayed out (or with whatever colors have been specified by -disabledforeground and -disabledbackground) and will not respond to the mouse at all.

The "normal" cursor

A

is

state

was

described.

just

physically over the button

and

The "active"

is

used

button should not be available for selecting unless for example, a button that disables another

tion;

would look

state

internally.

it

makes sense

when

it

is

in the applica-

pressed.

The code

like this:

$niw->Button(-text => 'Exit', -cornmand => sub { exit } ->pack; $var = "Disable Exit"; $inw->Button(-textvariable => \$var, -conmand => sub { itr/ $state = $exit_b->configure -state) if ($state eq "disabled") { $exit_b->configure( -state => 'normal'); $var = "Disable Exit";

my $exit_b

=

)

(

;

else { $exit_b->configure( -state => 'disabled'); $var = "Enable Exit"; }})->pack; }

In this example, a reference to the Exit button

used

later to

change the

the scope of the

state of the button. Also,

anonymous

is

saved because

subroutine. This will only

the global scope of the entire program so that

it

note that $exit_b

$exit_b

work will

if

needs to be is

used inside

$exit_b

is left

in

be defined when the

anonymous subroutine is executed. Be careful to not set $exit_b to something else; if you do, when the anonymous subroutine is invoked, it will refer to the new value in $exit_b, not the one you wanted. Figure 3-4

shows the window

after

we have

clicked

on

the Disable Exit button

once.

Figure 3-4.

Window with

The configure worry about

By

how

it

disabled button (Exit)

method is explained works just yet.

disabling widgets

when

and normal button

later in this chapter;

you don't need

to

they can't do anything, you can give users visual hints

about what they can and cannot do

in the application.

;

66

Chapter 3' The Basic Button

Manipulating the Text In addition to displaying text in the button, tion of the text within the button.

-font option

to

change the

you can

appearance and loca-

alter the

The simplest thing you can do

is

to use the

font:

-font => 'fontname'

There are several ways to specify the

font. If you are using Tk4 (which is the current book is being written) you should follow the directions in the followparagraphs. If you are using the newest version of Perl/Tk, which includes TkS.O,*

version as the ing

you should see Appendix

The new

the

is

it

covers the

new methods

to use with fonts.

specified as a text string that contains a font name. There

way you

is

a differ-

Win32 systems and Unix systems. Valid fonts your Unix system can be obtained by using the xlsfonts command or by using Tk:: Fonts module. The default font for the button widget on my Unix system ist:

ence for

font

C, Fonts;

in the

specify fonts for

"-Adobe-Helvetica-Bold-R-Normal--*-120-*-*-*-*-*-*"

Although

on a Win32 system, you need to send the -font option. Here's an example:

you'll see this default

type of string as the value to

a different

-font => "{Times New Roman} 12 {normal}"

You can look

in the Control Panel

under Fonts

to see

which

fonts are available.

window that shows the font in the differname of the font as it's listed in the Fonts directory for name between the curly braces. The number after the font

Double-clicking on them will bring up a ent sizes available. Use the the

first

name ally

is

part of the font

the size of the font in points.

normal,

italic,

The

third part

is

the type of the font, usu-

or bold.

There can only be a single font for each button, so the

text string

cannot change

font in the middle of a word. Each button (or widget) in an application can have a different font.

default font

Here

is

an example of two buttons

and the other with "lucidasans-14"

$mw->Button{-text => "Exit", -command => sub

(a

in a

window, one with the

Unix font) as

its

font:

->pack(-side => 'left', -fill => 'both', -expand =>

1)

$mw->Button(-text => "Exit", -font => "lucidasans-14", -command => sub { exit } ->pack(-side => 'left', -fill => 'both', -expand =>

1)

{

exit

)

}

,•

)

Figure 3-5



shows the

The numbering system 5, 6, and 7.

resulting

window.

for Perl/Tk follows the Tcl/Tk version

numbers.

I

have no idea

why

they

skipped

Not lowing

t

all

fonts are available

command

on every system, although your system's default should work. Use the folyour system: @config = $button->configure(-font)

to get the default font for

print "@config\n";

;

67

The Button Widget

~>

Button

Exit

J

1

-J

Exit

^

J .

Figure 3-5. Buttons with various fonts

you can also move the text around within word processing document, you can change where

In addition to changing the font,

button. As

you can

text will adjust

itself.

in a

The option

-justify => 'left'

The

default for

'

-justify

right is

that controls this '

'

|

center

is

the

the

-justify:

'

'center'. Normally, the text displayed

in a

button

is

a quick one- or two-word statement; for example, Exit, Done, Yes, No, or Cancel. The justification of the text isn't too obvious unless multiple lines of text are used. By default, the button will only display multiple lines if a \n is included in the string. You can have the program help decide when to wrap by using the -wraplength option:

-wraplength => amount

The amount Chapter will

This

indicates the

1). If

maximum

the length of the text string in the button exceeds this amount, the text

be wrapped around to the next an example

is

length of the line as a valid screen distance (see

that uses

line.

The

default for

-wraplength

is 0.

both the -justify and -wraplength options:

foreach (qw(left center right)) { $b = $inw->Button -text =>"This button will be justified $_" -command => sub { exit } -wraplength => 53, -justify => $_) ->pack(-side => 'left', -fill => 'both' -expand => 1) (

}

Figure 3-6

show

it,

it

shows the is

results of the three buttons.

possible for the text to be

-


J

ijQH

'blue'

and

J

-foreground => white'

-foreground and -background

options in conjunction with a

bitmap, the bitmap foreground and background will change to the specified colors.

The

effect of the colors

Figure 3-1

7.

'error'

depends on the bitmap. See Figure

bitmap with -foreground =>

when the

it

is

in the

'normal'

state.

When

and -background =>

'white'

The -foreground and -backgroimd options

These colors are

different

color,

-activeforeground =>

because

we want

mouse

cursor over

is it,

colors are used:

color

users to have

can press the button. By having the colors change

'black'

what color the button

control

the button has the

-activebackground and -active foreground -activebackground =>

3-17.

some

slightly

know that the button can be -activebackground is a slightly darker

visual clues that they

when

the

mouse

cursor

is

over the button, users

pressed to do something. The

default for

gray color ("#ececec")-

The

final color option,

button's state

is

-disabledforeground,

the color of the text

when

the

'disabled'.

-disabledforeground =>

When

is

color

it will not respond when the mouse cursor The default for the color of the text (or bitmap) is "#a3a3a3". Figure 3-18 shows the difference between the text colors with one disabled button and one normal button. (We also saw this example in Figure 3-4. Look there for the code that created this window.)

is

the button

over

it,

or

if it

is

is

in a disabled state,

pressed.

The Button Widget

75

Figure 3-18. -disabledforeground example

Changing the Mouse Cursor The mouse cursor normally looks like an arrow.* This can be changed on a widget-by-widget basis with the -cursor option: => cursomame

-cursor

When

the mouse is over the button, the cursor will change to the one specified. The cursor change will happen whether the button is disabled or not. There is a large set of available cursors. Following is a list of cursors, and Figure 3-19 shows what they look like.

X_cursor

arrow

based_arrow_down

based_arrow_up

boat

bogosity

bottom_left_corner

bottom_right_corner

bottom_side

bottom_tee

box_spiral

center_ptr

circle

clock

coffee_mug

cross

cross_reverse

crosshair

diamond_cross

dot

dotbox

double_arrow

draft_large

draft_small

draped_box

exchange

fleur

gobbler

gumby

handl

hand2

heart

icon

iron_cross

left_ptr

left_side

left_tee

leftbutton

ll_angle

lr_angle

man

middlebutton

mouse

pencil

pirate

plus

question_arrow

right_ptr

right_side

right_tee

rightbutton

rtl_logo

sailboat

sb_down_arrow

sb_h_double_arrow

sb_left_arrow

sb_right_arrow

sb_up_arrow

sb_v_double_arrow

shuttle

sizing

spider

spraycan

star

target

tcross

top_left_arrow

top_left_corner

top_right_corner

top_side

top_tee

trek

ul_angle

umbrella

ur_angle

watch

xterm

*

is

What

cursor

an arrow.

is

displayed

is

dependent on the window manager you are using, but most of the time

it

;

;

76

;

Chapter 3: The Basic Button

X ^ ±

J-

m

H-

^

D

SB

T

H

-

t

::3-

t

o

L^

ilTll

©

1J

^

/^

^ ^ ^ ^ ^

Q?

^\7



\new; $inw->Button(-text => "Exit", -command => sub { exit

)

}

->pack(-side => "bottom", -fill => "X")

$scroll = $mw->Scrollbar; $lb = $mw->Listbox{-selectmode => 'single', -yscrollcommand => [set => $scroll] $scroll->configure( -command => [yview => $lb]

)

)

$scroll->pack(-side => 'right', -fill => 'y'); $lb->pack{-side => 'left', -fill => 'both'); ## Open file that contains all available cursors ## Might have to change this if your cursorfont.h is elsewhere ## On Win32 systems look in C:\Perl\lib\site\Tk\Xll\cursorfont.h

open (FH, "/usr/XllR6/include/Xll/cursorfont.h" die "Couldn't open cursor file.Xn";

)

||

The Button Widget

while ()

77_

{

push((acursors,

if

$1)

(/\#define XC_(\w+)

/);

}

close (FH)

$lb->insert 'end' sort ©cursors) $lb->bind( '' sub { $ir[w->configure( -cursor => $lb->get ($lb->curselection) (

,

)

} )

;

;

MainLoop;

program might seem a

Although

this

a look at

how

does

Keep reading

okay. until

it

it

starts to

for a

sink

in.

box Widget, and bind

bit

complicated

at this

point in the book, take

you don't completely understand it right away, it's few chapters and then come back and look at it again

things. If

For reference, listboxes are covered in Chapter

is

covered

in

Chapter

7,

The

List-

Binding Events.

14,

Focus Options In an application,

you can tab between widgets

from the keyboard. The application indicates board input by drawing an outline around rectangle; see Figure 3-20).

If

the focus of the application. a specific

a

widget has

it

make them

available for input

widget

available for key-

in black (this

this outline

is

is

around

called the highlight it,

it is

(You can force the focus of an application

$widget->focus;

widget by using

to

that a

.)

Once

can use the spacebar on your keyboard to activate

1

it

said to

have

to start with

a button has the focus,

you

instead of using the mouse.

Exit

Exit

Figure 3-20. The first button has the input focus.

You can focus

force the application to not allow your button to receive the keyboard

at all

by using the -takef ecus option:

-takefocus =>

|

1

The -takefocus option

|

undef is

normally set to an empty string (undef), which allows

the application to dynamically decide

has

its

state set to

'disabled',

it

will

if

the widget will accept focus.

To have the application always through, use -takefocus => 0. To have the the widget, use -takefocus => 1. the widgets.

If

a widget

be skipped over when users tab through ignore the widget

when

all

tabbing

application always allow focus to

78

Chapter 3' The Basic Button

Altering the Highlight Rectangle The

highlight rectangle*

normally displayed with a thickness of 2 pixels. This

is

can be changed by using the -highlightthickness option: -highlightthickness => amount

The amount specified is any valid screen distance. In Figure 3-21, on the right has a -highlightthickness of 10 and has the focus.

Exit

i

the Exit button

Pi 1

Exit

Figure 3-21 Example of -highlightthickness => 10 .

When

the button doesn't have the keyboard focus, a small space

If this

extra space bothers you,

space won't display even

-highlightthickness The color of this:

if

to

you can

that if

is left

-highlightthickness to It is bad style also setting -takef ecus to 0.

set

widget has the focus.

you

aren't

the highlight rectangle can also be changed. There are

the color of the highlight rectangle

and the color of the highlight rectangle

-highlightcolor

when when

it.

and the to set the

two values

for

the button does not have the focus it

does have the focus. The option

the color of the highlight rectangle

is

around

when

the button does

have focus: -highlightcolor =>

color

shows the right button with the focus and with -highlightcolor 'yellow'. Compare it to the picture in Figure 3-21 to see the difference.

Figure 3-22 to

set

Exit

Exit

Figure 3-22. Example of button with -highlightcolor => 'yellow'

To change

the color of the space

focus, use the option

-highlightbackground =>



On Win32

left

around the button when

it

doesn't have the

-highlight±>ackground: color

system.s, the highlight rectangle

i.s

drawn

as a

dashed

line within the widget.

The Button Widget

79

Normally, the highlight rectangle

dow, which allows

it

to

blend in

same color as the background of the winwith the background of the window or frame that is

the

contains the button. Figure 3-23

shows an example where both buttons have the following

configuration:

-highlightcolor => 'blue', -highlightbackground => 'yellow'

The

right button

is

the

one

that has the focus.

Figure 3-25- Example of button with -highlightcolor => 'blue'

and -highlightbackground =>

'yellow'

Configuring a Button After creating the widget it

is

possible to use

and saving

methods on

a reference to

it

(such as $button),

in a scalar

that button.

There are two methods available to configure a button configuration information back:

after

it

is

configure and cget. They

created and to get are generic to

widgets and are covered in Appendix A, Configuring Widgets with configure cget.

common examples

Here are some

to get

you

started:

$state = $button->cget (-state) # Get the current $state = $button->configure -state) # Get the current $button->configure(-text => "New Text"); # Change the text $text = $button->cget (-text) # Get the current ©all = $button->conf igure # Get info on all (

( )

all

and

value for -state value for -state text value options for button

Flashing the Button The flash method will cause the button to appear to be "flashing" on the screen. It changes back and forth from the normal state colors to the active state colors: $button->flash()

Invoking the Button The invoke method invokes the subroutine to which the -command option points. Once you use -command to assign the callback, then anytime you need to perform that same task, you can use invoke ( )

$but ton- > invoke

( )

;

80

Chapter 3' The Basic Button

Some Fun Things One

to Try

of the best ways to figure out

how

Perl/Tk works

is

to try

it.

Once you under-

stand the basics, you'll spend most of your time tweaking options and callbacks to

do the •

correct thing.

Create a different



Create a

Here are some ways

window with three when clicked on.

to learn about the button widget:

buttons in

it.

Have each button

print

something

window with three buttons. Have the first two buttons change each when pressed. The last button should allow you to exit the program.

other's text •

Make some window.

really big buttons

and some

really tiny buttons all in the

same

Checkbuttons and Radiobuttons This chapter discusses both checkbutton and radiobutton widgets. Although they are very similar, they are used for different purposes.

Checkbuttons are useful as a

a

shopping

choice between Ql

when you want

to select as

many

items as you want, such

Radiobuttons are used in group situations

list.

items,

when you must make

such as on a multiple-choice exam:

What year did Columbus discover America?

:

1400 B) 1470 C) 1472 D) 1492

A)

E)

none of the above

Because radiobuttons are grouped together, you are forced to

one choice

in that group. If the default choice

would be automatically unclicked

is

always

select

A and you

one and only click

on D, A

(or unselected).

The two sections in this chapter cover how set them up and configure them.

to use

both widget types and ways to

The Checkbutton Widget \

_ Pi

In Chapter f

Checkbutton Widget

considered a type of button (and the

The Basic Button, you learned the options y f

3, ^'

^

associated with the button widget.

i

way

it

is

used

in

it

uses

an application

is

many

different

of the

same

A

checkbutton

options),

is

also

even though

from the way a standard button

is

used.

Instead of clicking ately,

you use

it

on

a checkbutton

to indicate a yes or

and expecting something

no answer.

If

to

happen immedi-

the checkbutton

is

checked

it

81

82

Chapter

means

unchecked means

yes;

The

no.

You might use

4:

Checkbuttons

and Radiobuttons

a checkbutton to

list

options for

on the checkbuttons might say Print Header Page, Even Pages Only, Odd Pages Only, and Number Pages. At the bottom of the window there would be a Print button, and when you clicked on it, the program would find out which checkbuttons were selected and submit the print job accordprinting a document.

text

ingly.

A window

buttons to ask the user job

name

run (like a batch job controller) might use check-

listing several jobs to if

each job should be run.

selected, the job will

is

be run.

If

the checkbutton next to the

the checkbutton

If

is

unselected, then the

job will be skipped this time around.

Each time a checkbutton

no

or

is

used, the application

question. Checkbuttons that

make up

is

button don't have

A

square on the

similar to a button;

it

side of the widget.

By

3D

left)

relief like a

left

mouse

same way

in the

button.

A

the indicator will look as If

if

it

a standard

like

it

is off, it

has

look

will

state of the

checkbutton

with color,

we

say

it

is

it

is

like a tiny

itself. If

checkbutton

window and

filled

is

on,

with a

gray button. is

the indicator's sta-

the checkbutton looks like

off (Figure 4-1; left checkbutton). If

on (Figure

it

own -relief (the way the been pushed down whereas a

state of the indicator. If the

a tiny raised button without color, then in

lit-

button does; you click on

has been pushed into the

the checkbutton

and the

also has an

its

Sometimes the terminology becomes confusing because there tus (or value)

it

edges of the check-

default, the outside

button will change

checkbutton will only change the darker color.'

displays a text string, but

standard button does, but the indicator (that

edges of the button are drawn) to look

is filled

each check-

does.

checkbutton operates

with the

to

independent of any other widgets or checkbuttons on the screen.

The checkbutton is indicator on the left tle

typically related (as in our

have to be because the answer

print job example), but they don't

button

asking the user to answer a yes

is

group are

a

4-1; right

it

checkbutton). The state of

the entire checkbutton (including the indicator) can be normal, active, or disabled. Both checkbuttons in Figure 4-1 have a state of normal.

J A

Figure 4-1.

*

Some

checkbutton that

operating

indicator to

show

m

Checkbutton Widget

.sy.stem.s

is

off and

actually put a

the state as on.

one that

checkmark

is

Checkbutton \Mdget

on

(t^) into the

little

box. Others

u.se a tiny "x" in

the

The Checkbutton Widget

83^

As when creating any widget, the checkbutton

created using a

is

method named

widget name, Checkbutton, invoked from the

after the capitalized version of the

parent widget. The basic usage looks like $cb = $parentwidget->Checkbutton(

this:

...

option => value,

[

)->pack;

7

In addition to having an indicator with a status, the checkbutton also can have a

callback that uses the -coitnnand option associated with is

it.

clicked (regardless of the indicator's status), the callback

When is

the checkbutton

invoked. However,

it

always necessary to associate a callback for radiobuttons and checkbuttons

isn't

since

you can

just

check the

status of the radiobutton or

checkbutton

later

on

in

the program.

The boolean status of the checkbutton is stored in a variable that you give via -variable option when it is created. Each checkbutton should have its own tus stored in is

its

own

When

unique variable.

the checkbutton

the sta-

clicked, the status

is

updated. In addition, any callback associated with the -coinmand option

invoked (regardless of the

change

new

status

The options

of the checkbutton).

a checkbutton's behavior are listed

below and explained

is

that

in greater detail

afterwards.

Checkbutton Options The following checkbutton options work exactly the same as a standard button, so I won't go over them in detail again. Refer to Chapter 3, for complete descriptions of these options: -activebackground, -activeforeground, -anchor, -background, -borderwidth, -cursor, -disabledforeground, -font, -foreground, -height, -highlightbackground, -highlightcolor, -highlightthickness, -justify, -padx, -pady, -state, -takefocus, -text, -textvariable, -underline, -width, and -wraplength. The

rest of the

options behave a

little

differently or are exclusive to the checkbut-

ton widget. They are covered in the following

Some

list.

options deal with only

-select image). Remember that the -state option refers to the entire checkbutton widget, and the status of the indicator is governed by the options -onvalue, -of fvalue, -indicatoron, and -variable. the indicator (such as

-activebackground =>

color

Sets the color the widget's

-activeforeground =>

background should be when the mouse

'n'

|

over

it.

color

Sets the color the widget's text

-anchor =>

is

'ne'

|

'e'

should be |

'se'

when j

'

mouse

the

s'

\

'sw'

over

is

|

'w'

it.

|

'nw'

|

'center' Sets the position of the text within the widget.

get

is

resized larger.

Most noticeable when the wid-

84

Chapter

Checkbuttons and Radiobuttons

4:

-backgroiand => color Sets the color of the

widget background (behind the

text).

-bitmap => bitmap Displays this bitmap instead of

text.

-borderwidth => amount Sets the

edge thickness of the widget. Also changes the thickness of the

cator. Default

indi-

is 2.

-coinmand => callback Associates a subroutine to the button. Called

when

button

is

clicked.

-cursor => cursomame Sets the cursor to

change

to

-disabledforeground => Sets the color of the text

cursomame when

it is

over the widget.

color

when -state

'disabled'.

is

-font => fontname

when

Sets the font to use

-foreground =>

displaying text in the widget.

color

Sets the color of the text.

-height => amount Sets the height of the button;

-highlightbackground =>

amount is

a valid screen distance.

color

around the widget should be when the

Sets the color the highlight rectangle

widget does not have focus.

-highlightcolor =>

color

Sets the color the highlight rectangle

around the window should be when the

widget does have focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle.

-image => imgptr Displays image instead of

-indicatoron =>

text.

1

|

Determines whether to display the indicator.

-justify => 'left'

|

'right'

|

'center'

Sets the justification of the text within the widget.

-offvalue => newvalue Sets the value

used when the button

is off.

Must be

a scalar. Default

is 0.

-onvalue => newvalue Sets the value

used when the button

is

on. Must

be a

scalar. Default is 1.

The Checkbutton Widget

85^

-padx => amount Sets the amount of space

between

left

and

text/indicator

left/right

edges of

widget.

-pady => amount Sets the amount of space

between

left

and top/bottom edges of

text/indicator

widget.

-relief => 'flat' 'groove' 'raised' Changes the look of the widget edges. |

|

-selectcolor =>

|

'ridge'

|

'sunken'

|

'solid'

color

when

Sets the color of the indicator

on.

-selectimage => imgptr Indicates the image to display instead of text

-image -state =>

is '

when

button

is

on. Ignored

if

not used.

normal

' ' |

disabled

'

' |

Sets the state of the widget. If disabled,

-takefocus => Determines

if

1

|

|

active it

will not

respond to any input.

\ixidef

the widget

is

available for focus or not.

-text => "text" Sets the text displayed in the widget.

-textvariable => \$variable Indicates that text in $variable

is

displayed as text in widget.

-underline => n Underlines the nxh character in the text

string.

-variable => \$value Associates the on/off value of indicator with $variable.

-width => amount Sets the

widget to

this width.

Can be any

valid screen distance.

-wraplength => amount Indicates that the text will

wrap when

it

exceeds

this

amount.

Storing the Indicator's Status The option -variable

will associate a variable with the status of the indicator

sending a reference as the value. To use the scalar $value, you would add the option

list

of the

Checkbutton

by

this to

call:

-variable => \$value Just as the

-textvariable option

sets the variable that

is

associated with the text

of the checkbutton, this option sets the variable associated with the indicator.

86

Chapter

When

is

clicked,

$value

cator (the value placed in

$value

is

the checkbutton

default are

1

and

now

will

Checkbuttons

mouse

$value

directly. If

contain the status of the indi-

defined by -onvalue and -of fvalue and

to

change the

status,

you can

You can

$value

specify

checkbutton, which will draw the checkbutton for the If

you change the value

=

your code contains $value

indicator will be turned on.

on.

in

$value

subroutine associated with -coinmand

Utilizing

on the

at

is

(if

any time

also

change the con-

some

there

1 before creating the

first

time with the indicator

after

one)

is

point, the

=

you

create the checkbut-

new

value.

not invoked

is

when

The the

changed.

-variable

is

usually the easiest

Here

is

an example

button.

by-

1 at

ton in your program, the checkbutton will change to reflect the

value of $value

and Radiobuttons

respectively).

In addition to using the tents of

4:

way

that has

to

check the

two buttons

status of the indicator

that

change the value

in

$cb_value: $cb_value = 0; $cb - $inw->C3ieckbutton(-text => "Checkbutton", -variable => \$cb_value, -command => sub { print "Clicked! $cb_value\n" ->pack(-side => 'top');

}

)

$mw->Button(-text => -command $mw->Button(-text => -command

"CB on", => sub { $cb_value = "CB off", => sub { $cb_value =

1

})

->pack(-side => 'left');

})

->pack(-side => 'left');

See Figure 4-2 for the resulting window.

iQiBcklmttoil -|_j

H

Checkbutton

CBoff

i

CBon

Figure 4-2. Buttons changing the value of a checkbutton

The value stored

in

$cb_value can be changed

checkbutton, clicking on the "CB

Only when you in the shell

click

off" button,

in three

or clicking

ways: clicking on the

on the "CB on"

on the checkbutton will you see the word it was run.

button.

"Clicked!" written

window from which

There are other ways to change the value associated with the checkbutton. See invoke, select, deselect, and toggle chapter.

in

"Checkbutton Methods"

later in this

87

The Checkbutton Widget

Assigning a Callback The -command option works

just like

it

does for a standard button, but usually the

function associated with a checkbutton's callback does something less obvious.

Many

times, there

is

no

important information

checkbutton was

One

callback at

all

associated with the checkbutton because the

the status of the checkbutton rather than whether the

is

just clicked.

of the things a checkbutton might

The checkbutton might look something

do

is

alter the

like the

one

appearance of the window.

in Figure 4-3-

l^iect'dbuttiro^T^

Show

all

widgets

Figure 4-5- Checkbutton that will display other widgets on the screen

When

the user clicks

changes to look

on the checkbutton

on, our

it

clicked

window

like Figure 4-4.

if

Show

ButtonZ

Buttoni

Window after clicking

Here's the code that

^31

ChecklHitton

...

Figure 4-4.

to turn

when

makes

all

widgets

Buttons

Button4

the checkbutton

the magic happen:

#! /usr /bin/perl -w use Tk; $ir[w = MainWindow->new; $mw->title "Checkbutton" (

)

## Create other widgets, but don't pack them yet! for ($i =1; $i Button(-text => "Button$i" }

$ir[w->Checkbutton(-text => "Show all widgets", -variable => \$cb_value, -command => sub { if

($cb_value)

{

foreach (©buttons) { $_->pack(-side => 'left'); } }

else { foreach (©buttons)

{

)

)

Buttons

magically

;

88

Chapter

$_->pack

forget

( '

'

)

;

'

)

4:

Checkbuttons and Radiobuttons

} } )

}

->pack -side => (

'

top

MainLoop;

So

we

can display some widgets

later

on

in the

program,

we

create

them ahead of

time and store references to them in the ©buttons array. The buttons in this

example

because they don't even have a -command associated

aren't very useful

with them. Normally, they would each have a specific task they would perform

when

pressed; however, for our example,

Then we

indicator),

its

it

just

When

magic checkbutton.

create our

the status of

we

want them

the button

is

to exist.

clicked (regardless of

pointed to by -command. Our

will call the subroutine

shows the buttons if it is on, changed before this subroutine is called. When our checkbutton is clicked again, the extra buttons will be removed from the window and the window will shrink back to the size it was presubroutine looks

and hides them

the current value of $cb_value,

at

if it is off.

The value

in

$cb_value

is

viously.

great when you want to keep a basic window uncluttered but show more widgets if the user can handle the advanced functions of the extra widgets. For example, you can create a Find window that has a place to enter some text, a button to start the find, and an Advanced Search checkbutton. Clicking on Advanced Search would add some more widgets to the bottom of the window allowing you to match case, use regular expressions, and use

This type of setup

want the

is

ability to

other fancy search mechanisms.

On and If

Off Values

you don't

change

like the default

-onvalue => newvalue

The same

is

These options

you would it

long as

hashes It

If

1,

you can use the -onvalue option

to

will

like the

if

is

## Default is

change the values stored checkbutton

makes sense it

## Default is 1

true of the off value:

-offvalue => newvalue

times

on value of

it:

to use different values.

a scalar value. This

you

really

want

in

$variable. Depending on

to interact with the rest of

means

that

how

your application, some-

The newvalue could be anything, as you can use references to arrays and

to.

good practice to keep the meaning of -onvalue the opposite of -offvalue. -onvalue is now the string "ON", logically -offvalue should be "OFF". Of

is

89

The Checkbutton Widget

course,

if

the purpose of this checkbutton

is

to use a

more accurate value of

7C,

then -onvalue could be "3.14159265359", and -offvalue could be "3.14".

Be

careful

when you

use unusual values for -onvalue and -offvalue.

the variable to something that doesn't equal either

If you set one of them, the checkbutton

even though the value of the $variable will not equal the -offvalue value. For instance, if you set -onvalue => 1, -offvalue => 0, and

will

be considered

you

set

off,

$variable

to

3,

then the checkbutton will be considered

off.

Indicator Color You can use the -selectcolor option when the checkbutton is selected: -selectcolor =>

to alter the color that

fills

in the indicator

color

The default value is "#b03060" (a dark pink color). Changing the value for -selectcolor will also change the background of the button when the button is selected and -indicatoron => .

Hiding the Indicator One

of the ways a checkbutton

different

Use the -indicatoron option

tor.

square button

at

we

(i.e.,

to

from a standard button

|

have seen from the previous examples, the default for -indicatoron

show

the indicator).

If

we change

this

-indicatoron

look almost like a normal button (without quite as though). Even though

it

looks a

Note

Figure 4-5). is

that

lot like a

which

clicked (to turn the indicator,

-indicatoron

the

is

Figure 4-5- Checkbutton with -indicatoron => checked.

is 1

checkbutton

much space around the its behavior when it

hidden, to on) is

is

completely different

ignored completely

when

set to 0.

js^^^^HEZG ifj^^^«^

Checkbutton NMdgetl

is

to 0, the

regular button,

-relief option

C2ieckiHJtton

right

little

1

text,

(see

the indica-

Perl/Tk not to draw that funny

tell

will

is

is

all:

-indicatoron =>

As

is

0.

Window on

left is

unchecked.

Window on

;

;

90

Chapter

4:

Checkbuttons and Radiobuttons

background on the checked button is the -selectcolor, not the -backgroundcolor. You might want to use the nonindicator configuration if you change the text of the button to reflect the new state of In this example, the color for the

the checkbutton. For instance, change Logging Enabled to Logging Disabled.

Displaying a Picture Instead of Text As you can with image

a

normal button, you can use the -image option to display an

in place of the text

on

available to display a different

-image => $imgptr

a checkbutton.

Another option, -selectimage,

image when the checkbutton has been

-selectiinage => $imgptr

[

The usage statement shows -selectimage if -image is not used.

is

clicked:

]

as optional because

it

will

be ignored

The imgptrs can be created by using the same methods as those used in Chapters with a button's -image option: $arrow = $mw->Photo(-file => "nextart gif " )

.

The image

be put

will

in place of the text

precedence over the -text option, so

-text option

will

if

on the checkbutton. These options have both -text and -image are listed, the

be ignored.

Which image is displayed depends on whether the button is on or off. If only the -image option is specified, this image will be displayed no matter what. If -selectimage is also specified, the image associated with it will be displayed when the button is checked. Figure ^-d shows an example that uses both options.

~i C3l

J

-.

J

-.Ch -.jj

\

Exit

Figure 4-6. The

same window

X Exit

with the checkbutton unchecked (on the

left)

and checked (on

the right)

The checkbuttons

in Figure 4-6

were created with

this

code snippet:

$imgl = $raw->Bitmap(-file => "/usr/XllRe/include/Xll/bitinaps/lineOp.xtm") $iing2 = $mw->Bitmap(-file => "/usr/XllR6/include/Xll/bit:inaps/xlogo32")

$rnw->Checkbutton(-text => "Checkbutton", -image => $imgl, -selectimage => $img2, -variable => \$cb_value) ->pack(-side => 'top');

;

The Checkbutton Widget

9J_

Using two different images to indicate whether the checkbutton

make more sense you want

if

you

is

off or

on might

-indicatoron and set it to 0. For instance, if document is locked (read-only) or unlocked you could -image and a picture of a lock with a line through it for

also use

to indicate that a

use a picture of a lock for

-selectimage. For

this

example,

I

chose to use bitmap

files

as our images. Instead of using the

-image option to display a bitmap, you could use the -bitmap option directly. The -bitmap option is exactly the same as the standard button -bitmap option; it replaces the text of the button with the specified bitmap (see Figure 4-7).

Figure 4-7. Checkbutton with -bitmap => 'warning'

Unlike -image and -selectimage, using -bitimap will not change the image

when

the button

You might

is

clicked

on or

off.

would make your application understand. However, if you use too many

think that using images instead of text

easier for non-English speakers to

A few

checkbuttons with images, you might confuse people even more.

easily

understood icons are better than a large collection of vague icons.

Checkbutton

Style

Although the button and checkbutton both share the -relief and options,

and they mean the exact same

ton, the effects are visually different

thing,

when

because of the

-borderwidth

they are used with a checkbut-

indicator.

As a reminder, the

possi-

ble values are:

-relief => 'flat' 'groove' -borderwidth => amount |

|

'raised'

|

when

Figure 4-8 shows the different relief types used.

The

default for a checkbutton

is

'

'ridge'

flat

'

|

'sunken'

a default

|

'solid'

-borderwidth value

because the

relief

edge of the checkbutton doesn't change when the checkbutton

is

is

of the outside

clicked; only the

shows that the edges of the checkbutton are to the text; the -padx and -pady default values are smaller than the button. The -relief option does not affect the indicator.

indicator changes. Figure 4-8 also

much

closer

default for a

The -borderwidth option

affects

both the outside edge of the checkbutton and

the indicator inside the checkbutton.

The

indicator itself stays the

same

size

no

92

Chapter

4:

Checkbuttons and Radiobuttons

'^

\4^

:

groove

flat

raised

sunken

ridge

Figure 4-8. Example of all possible -relief types

matter what the borderwidth of the widget width.

When you

shown

in Figure 4-9.

is,

but the indicator's edges change in

use a large -borderwidth, you get some interesting

QiecHbutton

-J

^

results, as

J J

:

J

groove

flat

raised

ridge

{

ijt

sunken

Figure 4-9. Example using -borderwidth => 4

We

used a -borderwidth of

thicker, is

much

in the

4, and you can see that the outside edges got a bit and so did the edges of the indicator. With a larger -borderwidth, there

less

room

to

middle of those

show

the indicator's color

when

is

it

on

(see the tiny square

indicators?).

!

QiecktHJtton

'-J

groove

flat

raised

J •

iB

,

sunken

ridge

Figure 4-10. Example using -borderwidth => 10

In Figure 4-10,

We

we

When

at all,

10.

Notice the remarkable difference!

even though there

these checkbuttons are checked or unchecked, there

the current state I

used a -borderwidth of

can no longer see the indicator

highly

it

is

because the indicator

recommend

that

is

is still is

space

no way

to

for

left tell

it.

what

essentially invisible.

you do not use the -borderwidth option associated

with a checkbutton because of

this interesting side effect.

Configuring a Checkbutton methods

Like the button widget, the checkbutton has is

created.

ated,

These methods can be invoked

even before

it

is

at

any time

that

after the

it

checkbutton

after is

it

cre-

displayed on the screen.

You can use both configure and cget methods with These methods are explained

and cget.

can manipulate

in

Appendix

a checkbutton as well.

A, Configuring Widgets with configure

The Radiobutton Widget

93

Turning a Cbeckbutton

On and

You can

go from on

force the checkbutton to

Off to off or vice versa using the

dese-

lect and select methods.

The deselect method will always set the indicator to the able assigned by -variable to the value in -of fvalue: $cb->deselect

vari-

the indicator to be set to the

on

the -onvalue:

)

(

Both methods are ignored

You can

and the

( )

The opposite of deselect, select will cause state and the variable assigned by -variable to $cb->select

off state

if

-state

also toggle the indicator

is

'disabled'.

from on to

off or vice versa using the

toggle

method: $cb->toggle Calling to

be

{ )

toggle does not cause

the subroutine associated with the

-command value

called.

Flashing the Checkbutton You can make ors

by

the indicator flash with the

-background and -foreground

col-

calling flash:

$cb->flash();

Invoking the Checkbutton To perform ton, call

the

$cb->invoke It

will

same

action as clicking the checkbutton with the

mouse

left

but-

invoke: { )

cause any callback associated with -command to be called;

the state of the indicator from

on

it

will also switch

to off or vice versa.

The Radiobutton Widget A

radiobutton looks similar to a checkbutton because

it

also has

Radiobutton

an indicator on the

mond,

rather than a square.

left side.

The radiobutton

Both look 3D and are

slightly raised

indicator

when

is

a dia-

unselected.

94

Chapter

The main

difference

between

A

serve in an application.

a radiobutton

radiobutton

and

a

checkbutton

used to

is

Checkbuttons and Radiobuttons

4:

select

the function they

is

one of several

different

choices: •

In a multiple choice



Which version of



Your income



Which type

the answers A, B, C, D, or E

test,

you would

a tool

like to

use

range: 0-20,000; 20,001-30,000; 30,001^0,000; 40,000

you

of entree

In each example, only

prefer: beef, chicken, or vegetarian

one answer

is

appropriate. For instance,

sense to have a salary of both $18,000 and $33,000. multiple-choice gives

you

test,

credit.

you

can't select

You have

all

it

wouldn't

And when you

the answers and

hope

make

are taking a

that the teacher

to pick only one.

Because radiobuttons are used always create

and up

at least two.*

It

to decide

doesn't

between several choices, you should

make sense

to ask a question at

there

all if

is

only one choice. Radiobuttons should always be created in groups of two or more.

Creating Radiobuttons So

far,

always

you have learned in a group,

we

to create

one widget

at a time.

Because radiobuttons are

more than one at quickly and painlessly

generally need to create

and create all the widgets as show you some quick ways to make up a group of radiobuttons. can be

efficient

(To show you

how

of widget creation and that

more complicated. By now, you should know

how

an option works exactly

ter for a

more complete

as possible,

I'll

advantage of the widgets in the best way, the exam-

to take

ples will start to get a bit

So you

a time.

to specify options during the creation. like

did with widget

it

X and

refer

you

I'll

the basics often say

to that chap-

discussion.)

Radiobuttons are similar to checkbuttons; they also have a $variable associated with the state of the indicator (using the option -variable).

group of radiobuttons, use the same $variable group.

The value put

radiobutton the

is

new group

selected.

into

To

the

$variable

create a

will

new group

When you

create a

for every radiobutton in the

change according

to

which

of radiobuttons, simply associate

with a different $variable.

Because each radiobutton

in a

group points

to the

same $variable,

there

isn't

a

concept of onvalue and offvalue. The offvalue would be whatever the other radiobutton wanted

it

to be.

To accomplish

this,

radiobuttons use the option

-value instead of -onvalue and -offvalue.



If

with

create only one radiobutton, it would stan out un.sclcctcd (unlcs.s the variable you a.s.sociated contained the on value). Once that radiobutton wa.s .selected, you would never be able to deselect it.

you did it

95

The Radiobutton Widget

For our

first

example, we'll create a group of radiobuttons that indicate the back-

ground color of our window. We need configure -background => color) (

work, so

we

will

for creating a radiobutton

$rb = $parentwidget->Radiobutton(

Here

is

command. Simple

names

color

usually

use red, yellow, green, blue, and gray.

As always, the basic usage

ground

to use colors that are valid to the $inw->

[

is

as follows:

option => value,

...

7

)->pack;

the code that will create the radiobutton group that controls the backcolor:

setup the default value we would like $rb_value = "red"; $mw->configure -background => $rb_value) #

(

create the radiobuttons that will let us change it foreach (qw(red yellow green blue grey)) { $niw->Radiobutton(-text => $_, -value => $_, -variable => \$rb_value, -cornmand => \&set_bg) ->pack -side =>

#

(

'

left

'

)

;

}

function to change the background color using $rb_value set_bg { print "Background value is now: $rb_value\n" $inw->configure( -background => $rb_value)

#

s\ib

;

}

We

are storing the status of our radiobutton

initial

ing.

group

value of "red", which happens to match the

When

in

We

$rb_value.

first

radiobutton

set

we

it

to

an

are creat-

any of the radiobuttons are clicked, including the one currently

selected, the subroutine

set_bg

will

be

called. This subroutine will print the

window

value of $rb_value and then change the background of our main

new

to that

color.

One

thing to note: Although

"red", that doesn't

mean

we

set the default

that the

value of our radiobutton group to

background of the window has been

set to

red

We

do this by calling the configure command and sending it the value in $rb_value. We could also do it by an explicit call to the set_bg routine, or we could have done it when we created the Main Window. as well.

The window we have created looks

Radiobutton

ii •

^

like Figure 4-11.

red

v- yellow

green

^

bUje

grey

J

Exit

j .

1

Figure 4-11. Radiobuttons that will change the background color of the

window

96

Chapter

The run

way

best

on each radiobutton,

change

window works is to type in the code and shown in this book. When you strip of the window at the top and bottom

this

you'll see a

color. You'll only see this small strip

because

ground of $mw, not of each radiobutton or the

Now

Checkbuttons and Radiobuttons

This will be true for a lot of the examples

it.

click

how

to understand

4:

we

exit button.

we've seen a basic application of radiobuttons,

that

only changed the back-

we

can go over each of

the options.

Radiobutton Options As with the checkbutton, the following options are the same

any of the three

for

types of buttons: -activebackground, -activeforeground, -anchor, -back-

ground, -borderwidth, -cursor, -disabledforeground, -font, -foreground,

-height, -highlightbackground, -highlightcolor, -highlightthickness, -padx, -pady, -state, -takefocus, -text, -textvariable, -underline, and

-width.

same between checkbutton and radiobutton: -command, -indicatoron, -image, -selectimage, -bitmap, -wraplength, -justify, and -selectcolor. In

The

rest

text in

I

following

the

addition,

bit differently

-activeforeground =>

background should be when mouse

'n'

|

'ne'

|

'e'

should be |

'se'

when

over

it.

|

mouse

the

's'

|

'sw'

over

is

|

'w'

it.

|

'nw'

|

'

Sets the position of the text within the widget. is

is

color

Sets the color the widget's text

get

because of the con-

color

Sets the color the widget's

'

the

are using them.

-activebackground =>

-anchor => center

are

because they behave a

will discuss

which we

options

Most noticeable when the wid-

resized larger.

-background =>

color

Sets the color of the

widget background (behind the

text).

-bit:map => bitmapname Displays this bitmap instead of

text.

-borderwidth => amount Sets the

edge thickness of the widget. Also changes the thickness of the

cator. Default

is 2.

-command => callback Associates a subroutine to the button. Called

when

the button

is

clicked.

indi-

97

The Radiobutton Widget

-cursor => cursomame

cursomame when

Indicates that the cursor will change to

it

is

over the

widget.

-disabledforeground =>

color

Sets the color of the text

when -state

is

'

disabled'

-font => fontname

when

Sets the font to use

-foreground =>

displaying text in the widget.

color

Sets the color of the text.

-height => amount Sets the height of the button;

-highlightbackground =>

amount is

a valid screen distance.

color

around the widget should be when the

Sets the color the highlight rectangle

widget does not have focus.

-highlightcolor =>

color

Sets the color the highlight rectangle

around the window should be when the

widget does have focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle.

-image => imgptr Indicates that an

image

-indicatoron =>

|

is

displayed instead of

1

means

Indicates the status of the indicator;

-justify => 'center'

text.

|

'left'

|

indicator

not displayed.

is

'right'

Sets the justification of the text within the widget.

-padx => amount Sets the amount of space

left

between

text/indicator

and

left/right

edges of the

widget.

-pady => amount Sets the amount of space

left

between

text/indicator

and top/bottom edges of

widget.

-relief => 'flat' 'groove' 'raised' Changes the look of the widget edges. |

|

-selectcolor =>

|

'ridge'

color

Sets the color the indicator should

be when on.

|

'sunken'

|

'solid'

98

Chapter

Checkbuttons and Radiobuttons

4:

-selectimage => imgptr image should be displayed instead of

Indicates that an on. Ignored

if

-image

-state => 'normal'

is

'active'

|

Sets the state of the widget.

-takefocus =>

|

1

|

|

when

the button

is

'disabled'

disabled,

If

it

will not

respond to any input.

xixidef

Determines whether the widget

-text =>

text

not used.

is

available for focus or not.

textstring

Sets the text displayed in the widget.

-textvariable => \$variable Indicates that the text in $variable

displayed as text in the widget.

is

-underline => n Underlines the nth character in the text

string.

-value => newvalue Sets the value assigned to

radiobutton

is

$variable

selected (default

(set

with -variable option)

when

this

is 1).

-variable => \$variable Sets the variable to use

when

this

radiobutton

is

clicked.

-width => amount Sets the

width of the widget. Can be any valid screen distance.

-wraplength => amount Indicates that the text will

wrap when

it

exceeds

this

amount.

Using the -variable Option The -variable option will look the same in each radiobutton creation command, except logically, we are using it differently. We should have several radiobuttons sharing the same $variable instead of each one having their own distinct $variable. The example for Figure 4-11 shows how this works.

Setting the Value With checkbuttons,

had

we

to

we had two

worry about the

state of

options,

-onvalue and -of fvalue, because we

each individual checkbutton. With radiobuttons,

only care about the state of the whole group. Each radiobutton should have a

different

-value

to

it,

so a glance

at

$variable

will tell us

which radiobutton

is

selected.

The default -value is 1. (Remember: When you use one radiobutton, that one is always checked.)

a

group

that consists of only

99

The Radiobutton Widget

To make sure you understand the difference between the -value option, let's walk through a short example.

the

-variable option and

$inw->Radiobutton(-text => "Beef", -value => "Beef", -variable => \$entree) $ir[w->Radiobutton(-text => "Chicken", -value => "Chicken", -variable => \$entree) $rnw->Radiobutton(-text => "Vegetarian", -value => "Vegetarian", -variable => \$entree)

Here

we

have created three radiobuttons

that

their values in. If the user selects Beef, then

"Beef".

If

the user selects Chicken, then

"Chicken". Later printer,

we

can

in

just

the

all

use the variable $ entree to store

$entree will contain the value of $entree will contain the value of

program when we build the physical menu

check to see what

is

in

$entree

to find out

what

for the

that user

wants for dinner.

Radiobutton

Style

Okay, so the -relief option does the same thing is

it

does

worthwhile to show a screen shot of what happens

in a checkbutton.

when

But

it

different relief types

are used (see Figure 4-12).

_Jjj J

RadMbutton

,_, _

flat

»

groove

?

raised

«

ridge

sunken

Figure 4-12. Different relief types for a radiobutton

As with the checkbutton, changing -borderwidth can cause the radiobutton to look drastically different (see Figure 4-13).

^itoto5Hr~~""~Ta flat

groove

raised

ridge

sunken

Figure 4-13- Radiobuttons with -borderwidth of 4

Remember how the indicator completely disappeared in a checkbutton when we used a -borderwidth of 10? Well, in a radiobutton, it makes it look kind of like a kite (see Figure 4-14). You still won't be able to tell which radiobutton is checked or not, so I don't recommend using the -borderwidth option.

;

;

100

Chapter

4:

Checkbuttons and Radiobuttons

p(-— '


flash()

colors off

;

Invoking a Radiobutton To programmatically $rb->invoke It

select a radiobutton, use the

invoke method:

( )

causes the radiobutton to be selected and will also invoke any callback associ-

ated with the radiobutton via the thing

it

would do

if

-command

option. Essentially,

it

you clicked on the radiobutton with the mouse.

does the same

Fun Things

101

to Try

Fun Things Create a all

to Try

bunch of checkbuttons and

a

Go

button that will report the status of

the checkbuttons.

Make up

a survey that uses checkbuttons for questions that have

one or more

options and radiobuttons with only one appropriate choice. Create three different groups of checkbuttons: Favorite Color, Favorite Song,

and Shoe

Size.

Then

use.

The curwhich checkbuttons the user can see and

create a radiobutton to represent each group.

rently selected radiobutton dictates

;

;

Label and Entry Widgets There are times

want users

you'll

name, address, or even entry widgets.

the user

You can use

in the entry.

Most

often, you'll see the label

entry combination used multiple times in a database entry-type there are

many

such as

their

use

this is to

widget with an entry to clearly communicate to

a label

what should be typed

to type in specific information

number. The simplest way to do

a serial

different pieces of information the user

must

and

window where

enter.

The Label Widget So

far, all

buttons.

the screen?

anything.

It

The

we

What

label widget

does

label

can show

if

we

widget

is

it)

and

want

A

text,

have a different

both

a button

font,

have

102

some

like a

informative text

on

button that doesn't do

does nothing when you It is

click

on

it.

similar to a button in that

it

relief (default is flat), display multiple lines of

and so on. Figure

label, created

is

and by default cannot have the keyboard it

with

this

5-1

)

shows

a simple

code:

use Tk; $mw = MainWindow->new() $inw->Label -text => "Label Widget " ->pack $rnw->Button(-text => "Exit", -command => sijb MainLoop (

to put

label

probably the simplest widget.

text (or a bitmap),

and

just

just that.

a noninteractive widget

is

focus (meaning you can't tab to

The

have talked about are buttons, buttons, and more

( )

;

{

exit })->pack();

window, with

103

The Label Widget

Label

¥1 1

1^4

ahel Wid get Exit

a-

Figure 5-1-

A

simple

Here are some •

with label

and

button

typical uses for a label:

Put a label to the is



window

left

of an entry widget so the user

knows what type

of data

expected.

Put a label above a group of radiobuttons, making their purpose more clear (e.g.,

"Background

Color:").

You can do

the

same thing with checkbuttons

if

they happen to be related or along the same theme. •

Use a label to tell users what they did wrong: "The number entered must be between 10 and 100." (Typically, you would use a Dialog composite widget to give messages to the user like



this,

but not always.)

Put an informational line across the bottom of your window. All the other widgets

would have

a

mapping

that displays a string containing information

about

that widget.

Creating a Label The command

to create a label

$label = $parent->Label

[

(

is,

of course. Label. Here's the basic usage:

option => value

.

.

.

)->pack();

]

Hopefully, you are starting to see a trend in the creation

when you create a label, you can appearance and how it behaves.

expect,

command. As you might

specify options that will change

its

Label Options The following

-anchor => center '

list is

'n'

a

|

comprehensive 'ne'

'e'

|

of options for labels:

'se'

|

's'

|

'sw'

|

'w'

|

'nw' |

'

Causes the text to

stick to that position in the label widget. This

ous unless the label

-background => Sets the

|

list

is

forced to be larger than standard

color

background color of the

label to color.

-bitmap => bitmap Displays the bitmap contained in bitmap instead of

text.

size.

won't be obvi-

Chapter 5: Label and Entry Widgets

104

-bordeirwidth => amount

Changes the width of the edges of the

label.

-cursor => cursomame Changes the cursor to cursomame when

the

mouse

is

over

this

widget.

-font => fontname be displayed with fontname.

Indicates that the text in the widget will

-foreground => Changes the

color

text of the button (or the

bitmap) to be color

color.

-height => amount Sets the height of the label to

-highlightbackground =>

amount; amount

a valid screen distance.

color

Sets the color of the focus rectangle

-highlightcolor =>

is

when

the widget

when

the widget has focus to color.

is

not in focus to color.

color

Sets the color of the focus rectangle

-highlightthiclcness => amount Sets the

width of the focus rectangle. Default

for the label.

is

-image => imgptr Displays the image to which imgptr points instead of

-justify => 'left'

'right'

|

Sets the side of the label against

|

text.

'center'

which

multi-line text will justify.

-padx => amount Adds extra space

inside the

edge

to the left

and

-pady => amount Adds extra space

inside the

edge

to the top

and bottom of the

'groove' 'raised' -relief => 'flat' Changes the type of edges drawn around the |

|

-takefocus => Changes the -text =>

|

1

|

|

right of the label.

'ridge'

|

label.

'sunken'

button.

undef

ability of the label to

have the focus or

not.

text

Displays in the label a text string.

-textvariable => \$variable Points to the variable containing text to be displayed in the label. Label will

change automatically as $variable changes.

-underline => n Causes the nth character to be underlined. Allows that key to invoke the widget when it has the focus. Default value is -1 (no character underlined).

105

The Label Widget

-width => amount Causes the label to be width amount.

-wraplength => amount Indicates that the text in the label will

This

list

briefly describes

wrap when

each option and what

different defaults for the label

we

widget than

type widgets, causing the label to behave a

How a Label Differs from

it

it

does.

gets longer than

Some

amount.

of the options have

are used to seeing with the button-

bit differently.

Other Widgets

When we

created button-type widgets, we could either click them with the mouse them and then use the keyboard to cause the button to be pressed. A label widget, on the other hand, does not interact with the user. It is there for informational purposes only, so there is no -coitimand option. We also can't tab to a label widget because nothing would happen. or tab to

-takefocus option is 0, making the label noninteractive. When tabbing between widgets on the screen, the highlight rectangle shows us which widget currently has the keyboard focus. Since we don't allow the label to have the focus (remember, -takefocus is set to 0), it doesn't make sense to have a visible highlight rectangle. The default value for the -highlight thickness option in a label widget is 0. You can make a rectangle appear around a label by setting -highlight thickness to something greater than 0, and setting -highlightbackground to a color such as blue or red. The

default value for the

The

label

widget also doesn't have a -state option. Since

click a label,

we

should never have to disable

we

shouldn't be able to

it.

Relief In Figure 5-2,

you can see what happens when you change the

label's

-relief

option. Notice that the edges of the widget are very close to the text. Unlike a button,

you usually don't want much extra space around the label (space is conby the -padx and -pady options). Normally, you want the label widget to

trolled sit

right next to the

_. flat

widget (or widgets)

Label

j\ sunken '

groove raised ridge

it

is

describing.

Label

-A flat

flEd!

*

Figure 5-2. Labels with different relief values.

You'll notice that

I

like

Window on

right

rals«tli

s

_jj PSHf sftiMcen

has a -borderwidth of 10.

seeing what widgets look like with the different

relief values.

This sometimes helps determine where the widget ends, especially with widgets that

;

106

Chapter 5: Label and Entry Widgets

have a default value of

make and

sure

I

Also,

often change the relief of different widgets to

I

widgets are where on the screen. After creating 10 entries

labels with less than creative variable

ing the borderwidth relief

program

anyone

to

bound

is

to

make

else to run! Color

Status Message

names,

that

and borderwidth back

change the

I

"flat".

know which

is

it's

easy to lose track. Also, chang-

one widget stand

to something

good way

also a

out.

Of

course,

non-obnoxious before to

do

I

I

always

give the

a diagnostic message.

Example

often use the groove or ridge relief

when

making a help or

I'm

status label

along the

bottom of my window. I make a label that is packed with -side => 'bottom' and -fill => 'x'. There are two different ways you can use a status label: •

Set the variable associated with

announcing •

to the user that

Have the help application

it

is

it

so

label give information

when

it

changes as your program progresses,

it

busy, or something

is

happening.

on each of the different widgets bind command.

in

your

gets the focus, using the

Both types are demonstrated

in the following

This code shows the "What I'm doing

sample code.

now" type

of help label:

$rnw->Label (-textvariable => \$message, -borderwidth => 2, -relief => 'groove' ->pack( -fill => 'x', )

$inw->Text

{)

-side => 'bottom'); ->pack(-side => 'top', -expand => 1, -fill => 'both')

$inessage = "Loading file index html ..." .

;

$message = "Done";

The label is created across the bottom of the screen. We pack it first because we want it to stay on the screen if we resize the window (remember, the last widgets packed will get lower priority if the window runs out of room). As the program executes (represented by the. .), it changes the label accordingly. .

This code

shows an example of using

a widget-helper help label:

$mw->title( "Help Label Example");

$mw->Label (-textvariable => \$message) ->pack(-side => 'bottom', -fill => 'x'); $b = $mw->Button(-text => "Exit", -command => \&exit) ->pack(-side => 'left'); &bind_message($b, "Press to quit the application");

107

The Label Widget $b2 = $inw->Button(-text => "Do Nothing" ->pack( -side => lef t &bind_message($b2, "This button does absolutely nothing!"); )

'

$b3 = $mw->Button(-text => "Something", -coinmand => sub { print "something\n"

&bind_inessage $b3 (

siib

bind_message

"

,

Prints the text

}) ->pack(-side something "

=>

;

)

'

'

)

left

'

)

;

{

my ($widget, $msg) $widget->bind $widget->bind

'

'

( '

( '

= @_;



sub { $message = $_[1] sub { $message = " " } [

'

;

'

;

$msg

},

]

)

)

}

This example

method get

we

is

is

a bit longer because

explained

create,

in

we want

more

detail in

we

are using the

Chapter

to associate a help

14,

bind method

Binding

message with

(the

it.

We

do

this

bind

each wid-

Events). For

by adding

bindings to each widget that change the variable $inessage to a specified string

when

the

widget.

mouse

We

enters the widget,

and

to

an empty

string

if

the

mouse

used a subroutine to avoid writing the same two bind

over again. Figure 5-3 shows what our

window

looks like with the

leaves the

lines

over and

mouse over

the

center button.

Exit

Do Nothing

Something

This button does absolutely nothing!

Figure 5-3-

Window

J

with label across the bottom

Container Frames In Figure 5-3,

When text

you can see

that the

example

text

is

centered within the label widget.

when you fill the widget across the screen, the even if you add the -justify => left option. You can

using non-multiple line labels,

remains centered,

get around this

by

'

'

creating a container frame, giving

frame across the screen (instead of the

label),

the frame: $f = $mw->Frame( -relief =>

'groove',

it

the desired

and placing the

relief, filling

label

the

widget within

;

108

Chapter

-bd =>

5:

Label

and Entry Widgets

->pack(-side => 'bottom', -fill => 'X') $f->Label (-textvariable => \$message, ->pack(-side => 'left'); 2)

)

grow and shrink within

This allows the label to

you've typed

text sticks to the left side. If

with the strings will resize itself

bound

tell

the

fairly

is

is

window

to not resize

in

and played

that the

window

too long to display in the label.

small to begin with. There are

you can always use

to deal with this: First,

ond, you can

$message

your window

if

example

each widget, you might have noticed

the text assigned to

if

This can get annoying

ways

to

the frame as necessary, while the

this short little

when

really short text strings,

and

two sec-

the label changes size.

The drawbacks with each approach aren't too bad, and which one you pick just depends on the application you are working on. If you can make really short sen-

make

tences that

though



it

is

sense, great. Telling the

accomplished by adding one

$inw->packPropagate

(

Using packPropagate placed inside the

)

right

will

your widgets

in

it,

first

You can

figuring out a

$inw->geometry( 512'^) to request gets, for info

to not resize

is

almost as easy,

your program:

window

when

a widget

is

talked about packPropagate in Chapter

2,

cause your

window (we away.

line to

;

Geometry Management). This means your widgets

window

that

to not resize

your window might not be showing

deal with this by keeping

good

starting size for

that size initially. (See

it

on

until

you get

all all

your window and using Chapter

13,

Toplevel Wid-

on the geometry method.)

Label Configuration two methods available to change on it: cget and configure. Both methods work for Label the same way they work for the Button widget. Please refer to Appendix A for the details on arguments and return values. Label

is

a pretty boring widget, so there are only

or get information

The Entry Widget Until

now, the only input

we know how

to get

from the

[entry widget is

a

mouseclick on a button widget (Button, Check-

which

is

handled via the -command option. Getting input

user button, or Radiobutton),

from a mouseclick

is

useful, but

it's

also limiting.

type in text that can then be used in any

The

way by

entry widget will

let

the user

the application. Here are a

few

examples of where you might use an entry widget: •

In a database

form

that requires

one entry per

field (e.g..

Name,

Address) •

In a software registration

window

that requires a serial

number

Last

name,

109

The Entry Widget

window



In a login



In a configuration



In

an

Open

we

File

that requires a

window

window

usemame and password name

to get the

of a printer

that requires the path

and name of

a

file

what users type

in an entry widget until they are done happen "after the fact" when a user clicks some sort of Go button. You could get fancy and process each character as it's typed by but it is probably more trouble than it is worth. setting up a complicated bind

Normally,

don't care

and any processing

typing,

will



The user can type anything decide

if

from an

some

the text entered

entry,

we

an entry widget.

into

valid or not.

is

When

should do some error checking.

we

alphabetic characters,

is

It

up

programmer

to the

to

preparing to use the information

we want

If

an integer and get

should issue a warning or error message to the

user.

An

entry widget

entry widget

is

a

is

much more complex widget

than

it

appears to be. The

first

simplified one-line text editor. Text can be typed

really a

selected with the mouse, deleted, middle-of-the-line widget.

It's

and added.

I

would

more complicated than

classify

in,

an entry widget as a

a button, but

much

less

com-

plicated than the text or canvas widgets.

Creating the Entry Widget No

surprises here:

$entry = $parent->Entry

When

the entry widget

cursor

(if

is

option => value

[

(

created,

it

is

.

.

is

]

)->pack;

empty of any

initially

the entry had the keyboard focus)

.

at

the

text,

and the

insert

far-left side.

Entry Options The following

list

contains a short description of each option available for config-

uring an entry widget. Several of

them

are discussed in

more

detail later in this

chapter.

-backgroimd => Sets the

color

background color of the entry widget. This

is

the area behind the text.

-borderwidth => amount Changes the width of the outside edge of the widget. Default value

-cursor => cursomame Changes the cursor to cursomame when

-exportselection => If

|

is

over the widget.

1

the Boolean value specified

windowing system's

it

is 2.

clipboard.

is

true,

any

text selected will

be exported to the

.

|

Chapter 5: Label and Entry Widgets

110

-font => fontname Changes the font displayed

-foreground =>

fontname.

in the entry to

color

Changes the color of the

-highlightbackground =>

text.

color

Sets the color the highlight rectangle should

be when the widget does not

have the keyboard focus.

-highlightcolor =>

color

Sets the color the highlight rectangle should

be when the widget does have

the keyboard focus.

-highlightthickness => amount around the widget. Default

Sets the thickness of the highlight rectangle

-insertbackground =>

is 2.

color

Sets the color of the insert cursor.

-insertborderwidth => amount Normally used

Sets the width of the insert cursor's border.

-ipadx and -ipady options

for the

in conjunction

with

geometry manager.

-insertofftime => milliseconds Sets the amount of time the insert cursor

is

off in the entry widget.

-insertontime => milliseconds Sets the amount of time the insert cursor

is

on

in the entry widget.

-insertwidth => amount Sets the

width of the

-justify => 'left'

insert cursor. Default

|

'right'

is 2.

'center'

|

The

Sets the justification of the text in the entry widget.

-relief => 'flat'

|

'groove'

Sets the relief of the outside

-selectbackground => Sets the

|

'raised'

|

'ridge'

default

is left.

'sunken'

|

'solid'

edges of the entry widget.

color

background color of any selected

text in the entry widget.

-selectborderwidth => amount Sets the width of the selection highlight's border.

-selectforeground => Sets the text color of

color

any selected

text in the entry widget.

-show => char Sets the character that should

-state => 'normal'

|

be displayed instead of the actual

'disabled'

|

Indicates the state of the entry. Default

'active' is

'

normal

'

text typed.

111

The Entry Widget

-takefocus =>

|

1

Allows or disallows

|

this

xxndef

widget to have the keyboard focus.

-textvariable => \$variable Sets the variable associated with the information

typed

in the entry widget.

-width => amount width of the entry in characters.

Sets the

-xscrollcoinmand => callback Assigns a callback to use

when

scrolling

back and

forth.

The following options behave as we expect them to, and aren't worth further discussion: -background, -cursor, -font, -highlightbackgroimd, -highlightcolor, -highlightthickness, -foreground, -justify, -takefocus, and -state. For more detailed information on these how these options affect a widget,

see Chapter

3.

Assigning the Entry's Contents to a Variable The -textvariable option

lets

you know what the user typed

in the

entry

widget: -textvariable => \$varia]Dle

By now, you should be familiar with this option from several of our button examples. Any text input into the entry widget will get assigned into $variable. The reverse also applies. Any string that gets assigned to $variable will show up in the entry widget. It is

important to remember that no matter what the user enters,

to this variable. This (e.g.,

"314"),

means

that

it

will

be assigned

even though you are expecting numeric input

like "3sl4" if the user accidentally (or on wrong key(s). Before using any information from an entry good idea to do some error checking to make sure it's the informa-

you might get something

purpose!) presses the widget,

it's

a

you expect or, at the very least, in the correct format. Trying an equation would most likely produce undesired results.

tion

The other way you can

find out

what

is

in the entry

widget

is

to use "3sl4" in

by using the get

method: $stuf f = $entrY->get

You can

( )

use get whether or not you have used the -textvariable option.

.

Chapter 5: Label and Entry Widgets

112

Relief all the widgets, you can change the way the edges -relief and/or -borderwidth options:

As with

-relief => 'flat' 'groove' -borderwidth => amount

'raised'

|

The

default for an entry

seen so

far.

is

drawn by using the

'sunken'

'ridge'

'sunken', which

is

are

change from what we've

also a

Figure 5-4 shows the different relief types at different

values incrementing from the default,

2,

-borderwidth

to 4, to 10.

J

Bitry Entry

MjI

Entry

1^ Jl

flat

flat

flat

groove

groove

igroove

j

j

raised

raised

!

iridge

raised

i

iridge

fsunken

sunken Exit

sunken

Exit

Exit

Figure 5-4. Different relief types for

This

is

name

entry widget: -borderwidth of 2 (the default),

an

4,

and 10

the code snippet that created the five entry widgets and used the relief

as the entry widget's text:

foreach (qw/flat groove raised ridge sunken/) { $e = $inw->Entry (-relief => $_) ->pack(- expand => 1) $e->insert 'end' # put some text in the entry $_) ;

(

,

;

}

Entry Indexes In order to manipulate the text in the entry widget, tify

specific portions or positions within the text.

The

you need some way last

example

actually

to iden-

used an

The line $e->insert 'end' $_) uses the index 'end' Just like the insert method (covered later in the chapter), all of the methods that require information about a position will ask for an index (or two, if the method requires a range of characters). This index can be as simple as 0, meaning the very beginning of the text, or something more complicated like insert index

in

it.

(

.

,

'

'

The Entry Widget

Here are the

1J3

different

forms of index specification and what they mean:

n (any integer)

A

numerical character position.

is

the

first

character in the string.

If

the entry

mother hit your mother right on the nose" and we used an index of 12, the character pointed to would be the "t" in the word "hit." contains the string "My

'

insert Indicates the character directly following the insertion cursor.

cursor get

clicking '

that funny-looking

is

when

text

on

is

little

insertion

bar thing that shows up inside the entry wid-

You can move

typed.

The

it

around with the arrow keys or by

a different location in the entry widget.

sel first .

The first character in the selection string. This will produce an error if there is no selection. The selection string is the string created by using the mouse or shift-arrow. The selected text is slightly raised from the background of the entry. If

our selected

were the word "nose"

text

in this string

(shown here

in bold)

My mother hit your mother right on the nose '

'

sel first .

'

would

sel last .

The character

just after

produce an error example, '

indicate the "n".

if

the

there

is

would mean

this

last

character in the selection string. This will also

no

selection in the entry widget. In the preceding

the space after the "e" in nose.

anchor The 'anchor' index changes depending on what has happened with the selection in the entry widget. By default, it starts at the far left of the entry: 0. It will change if you click anywhere in the entry widget with the mouse. The new value will be at the index you clicked on. The anchor index will also change when a new selection is made either with the mouse (which means the anchor will be wherever you clicked with the mouse) or by Shift-clicking and anchor will be set to where the selection starts. Mostly, this index is used internally, and you'll rarely find a case where it would be useful in an '

'



'

'



'

'

application.

•end' This indicates the character just after the is

the

index.

same

as

if

last

one

in the text string. This

you specified the length of the

entire string as

value

an integer

Chapter 5: Label and Entry Widgets

114

'&x'

This form uses an x coordinate in the entry widget. tains this

X coordinate

be used.

will

acter in the entry widget. This

The

character that con-

"(iO" indicates the leftmost (or first) char-

form of index specification

is

also

one

you'll

rarely use.

Text Selection Options You can

an entry widget, and several things happen. The indices

select the text in

'sel. first' and 'sel.last' point to the beginning and end of the selected

You can

text respectively.

on

a

make

also

the selected text available

on the clipboard

Unix system by using the -exportselection option:

-exportselection =>

|

1

The -exportselection option

indicates

whether or not any selected

text in the

entry will be also be put in the selection buffer in addition to being stored internal to the entry as a selection.

By leaving

this

option in

its

default value,

you can

paste selected text into other applications.

The

selected text also has

some

color options associated with

it:

-selectback-

ground, -selectforeground, and -selectborderwidth: -selectbackground => color -selectforeground => color -selectborderwidth => amount

The -selectbackgroimd and -selectforeground options change the color of the text and the area behind the text when that text is highlighted. In Figure 5-5, the word "text" is selected.

-\ ,

Entry

Select the word

^

in this

,

j

Ji

entry

Exit 1

Figure 5-5. Entry with -selectbackground =>

'red'

and -selectforeground =>

You can change

the width of the edge of that selection

borderwidth.

you

If

see the effects of

it.

left

The

'yellow'

box by using -selectyou wouldn't

the size of the entry widget unchanged,

To actually see -selectborderwidth value use the -selectborcommand and the -ipadx and -ipady in the geom-

entry widget cuts off the selection box.

the results of increasing the

derwidth option in the entry etry management command.

115

The Entry Widget

'^^t-

Enfry

iSelectthe word te^lln

'^^^'^iii

this entry

Exit

Figure 5-6. Entry widget with -selectborderwidth =>

You might want extra space

5

change the -selectborderwidth option

to

around your

text or

if

you

want

really

to

if

you

like a little

emphasize the selected

text.

Here's the code that generated the entry widget in Figure 5-6: $e = $inw->Entry (-selectborderwidth => 10) ->pack(- expand => 1, -fill => 'X', -ipadx => 10,

$e->insert 'end' {

,

-ipady => 10) "Select the word text in this entry");

Notice the -ipadx and -ipady options in the

pack command.

The Insert Cursor The

insert cursor

entry widget

is

when

that funny-looking it

widget actually has the keyboard focus.

board focus, the insertion cursor insertion cursor

is

little

has the keyboard focus.

immediately

is still

after the

If

bar that blinks on and off inside the It

will

only

show up when

the entry

another widget (or none) has the key-

there, but

second "n"

it

is

invisible. In Figure 5-7, the

in the

word

"Insertion."

Figure 5-7. Default insertion cursor

You can change

the thickness, border width,

and width of the

insertion cursor

by

using these options: -insertbackground => color -insertborderwidth => amount -insertwidth => amount

The -insertwidth option simply changes the width of the cursor so it looks fatter. The -insertbackground option changes the overall color of the insertion cursor. Figure 5-8 shows an example.

J 116

Chapter 5: Label and Entry Widgets

jsj»^^

mm T

111!

Entry II

|

-|^

imwtTmwwwnTwJmiMJiiB

'

Insertion Cursor

Exit

Figure 5-8. Insertion cursor with -insertbackground => 'green'

No two

how wide

matter

characters.

The

the cursor,

it

and

-insertwidtb

always centered over the position between

is

insertion cursor in Figure 5-8

is

in the

same

it was in them unneces-

location

Figure 5-7. This can look distracting to users and might just confuse sarily,

=> 10

so you most likely won't change the -insertwidth option.

You can

give the insertion cursor a

Figure 5-9).

Like the

doesn't have

much

3D

-insertwidth

look by using -insertborderwidth (as in option, the

-insert±)orderwidth option

practical use.

aW

Entry

Insertion Cursor



Exit

1

.

1

Figure 5-9. Insertion cursor with -insertborderwidth => -insertwidth

You can

5,

-insertbackground => green

'

and

=> 10

also

change the amount of time the cursor blinks on and

off

by using

these options: -insertof ftime => time -insertontime => time

The default value for -insertof ftime is 300 milliseconds. The default for -insertontime is 600 milliseconds. The default values make the cursor's blink stay on twice as long as it is off. Any value specified for these options must be nonnegative.

For a really frantic-looking cursor, change both values to something For a relaxed and mellow cursor, double the default times.

-insertof ftime

blinking cursor, change

If

much

smaller.

you don't

like a

to 0.

Password Entries There are times

when

displayed on the screen.

use the -show option: -show => char

that shouldn't

be

display something other than the actual text typed

in,

you'll request information

To

from the user

The Entry Widget

The char is

a single character that will

be displayed instead of the typed-in charac-

For a password entry, you might use asterisks (see Figure 5-10).

ters.

ify a string, just is

117_

the

character of that string will be used.

first

By

If

you spec-

default, this value

undefined, and whatever the user actually typed will show.

fs\j.

ilj^-^^'^^BWIf^*^

Exit

Figure 5-10. Entry displaying a password

When

using the

-show

option, the information stored in the associated

$variable

will contain the real information, not the asterisks. If

you use

this feature, the

user can't cut and paste the password (regardless of the

value of -exportselection).

saw on the screen

user

information behind

If

(the asterisks, for

You might

it.

and pasted

cut

is

it

example)

think that

if

widget such as $entry->conf igure (-show =>

would suddenly appear. Luckily, this berish) show up instead. Any variable associated with the entry will

an $entrY->get well.

( )

still

to another screen,

isn't true.

is

you did " "

)

;

,

actually pasted, not the

on the entry words the user entered

a configure

the

A bunch

what the

of \xOs (essentially gib-

-textvariable option and is If you perform

that uses the

contain the correct information.

the correct (nongibberish) information will be returned as

,

The get method

is

described later in

this chapter.

Using a Scrollbar If

the information requested from the user could get lengthy, the user can use the

arrow keys to manually

scroll

through the

To make

text.

assign a horizontal scrollbar to the entry widget

it

easier,

we

can create and

by using the -xscroll command

option: -xscrollcoinmand =>

For now, I'm going to entry widget. For

To

more

'

[

set

'

=> $scrollbar

show you details

and associate

create a scrollbar

the

on the it

]

most basic way to assign

a scrollbar to the

scrollbar see Chapter 6, Scrollbars.

with an entry widget, do

this:

$scroll = $itiw->Scrollbar (-orient => "horizontal"); # create scrollbar -> $e = $inw->Entry (-xscrollcoinmand => 'set' => $scroll pack(-expand => 1, -fill => 'x'); # create entry $scroll->pack( -expand => 1, -fill -> 'x'); $scroll->configure(-coinmand => $e => 'xview' # link them $e->insert 'end' "Really really really long text string"); ]

[

[

(

,

]

)

;

)

;

.

Chapter 5: Label and Entry Widgets

118

Figure 5-11 shows the resulting

looked

way

when

it

was

window

in

and on the

created,

two

right,

states:

how

on the

the

left,

window

looks after scrolling

it

all

as

it

the

to the right.

Entry

^

j

jReally really really long

Entry jally really

t

Exit

Figure 5-11. Scrollbar and

an

.

\

j

long text string

Exit

entry widget

want to use a scrollbar with an entry widget. The scrollbar douamount of space taken, and you can get the same functionality without it

You'll very rarely bles the

by simply using the arrow keys when the entry widget has the needs to enter multiple Chapter

8,

lines of text,

you should use

focus.

If

the user

a text widget instead. See

The Text Widget, for more information on what

it

can do.

Configuring an Entry Widget Both cget and configure are the same for the entry widget as they are of the other widgets.

Appendix

The

default options for the

A, Configuring Widgets with configure

for

any

entry widget are listed in

and cget.

Deleting Text You can use

the

delete method when you want

from the entry widget.

You can

characters or a single index to

remove one

$entry->delete (firstind€yc,

To remove all of the the -textvariable variable to an

empty

text,

/"

remove some or all of the text remove two or more

character: ])

you can use $entry->delete(0,

you can also $variable =

Here are some other examples of $entry->delete(0) $entry->delete 1 (

lastindex

option, string:

to

specify a range of indices to

# #

)

how

delete method:

Remove only the first character Remove the second character

,

;

#

Remove selected text present

# if

).

If

you use

by reassigning the

"

to use the

'sel.last') $entry->delete( 'sel. first if $entry->selectionPresent '

delete the contents "

'end'

119

The Entry Widget

Getting the Contents of an Entry Widget There are two ways to determine the contents of the entry widget: the get method or the variable associated with the

-textvariable

$entry_text = $entry->get

will assign the entire contents of the entry

get into

( )

find out the content

the information.

If

you only need

into a database,

it

a variable. Simply use the

would be

appropriate).

initially store

Moving

it

depends on what you are going

to reference

it

once

in

order to write

it

do with to a

file

doesn't

the information in the entry widget

If

to

number

is

going to be a

easy access

in a variable for

fre-

it

makes

insert took

place.

for a mathematical calculation, then later.

the Insertion Cursor

The icursor method $entrY->icursor

By To

wid-

make sense to waste memory by storing it in get method in the print statement (or wherever it

it

quently used value such as a

sense to

get method,

$entry_text.

Which way you or insert

option. Using the

(

will place the cursor at the specified index.

index)

;

wherever the

default, the insertion cursor starts out

force the insertion cursor to

show up

last

elsewhere, you could do something like

this:

$e_txt = "Entry Text"; $e = $rnw->EntrY{ -textvariable => \$e_txt) ->pack() $e->focus; $e->icursor (1) # put cursor at this index

;

;

We

focus method (which

use the

generic to widget.

Then we place and

acters (indices for

the insertion cursor

1) in the entry.

start

it's

with the focus on our entry

between the first and second char16, Methods for Any Widget,

See Chapter

more information on focus.

You might want

to

move

$e->icursor

Getting a

( '

end'

For instance, set $e_txt

=

if

)

Numeric Index Value

The index method

will convert a

named index

$nuinindex = $entry->index (index)

One

you are starting the "http://" and then do

the starting position of your cursor

text with a specific string.

get:

not specific to the entry widget;

is

widgets) to have the application

all

into a

numeric one:

;

of the uses of index is to find out how many characters are $length = $entry->index 'end' Of course, if we used (

)

.

in the entry

the

wid-

-textvari-

;

;

120

Chapter 5: Label and Entry Widgets

able

option,

we

could get the same result by using $length = length ($vari-

able).

As an example of using index this

where

to find out

$startindex = $entry->selectionPresent $entry->index( 'sel. first' (

We

the current selection

starts,

use

code:

discuss

selectionPresent

)

? )

:

-1;

later in the chapter.

Inserting Text The insert function $entrY->insert

(

will let

index,

you

string)

insert

any

text string at the specified index:

;

Here's a simple application that uses insert: # /usr/bin/perl use Tk; $n!W = MainWindow->new; $mw->title "Entry" !

(

)

$e_txt = "Entry Text"; # Create entry with initial text $e = $inw->Entry(-textvariable => \$e_txt) ->pack(- expand => 1, -fill => 'X') $inw->Button(-text => "Exit", -command => s\ib { exit } ->pack(-side => 'bottom'); )

#

Create a Button that will insert a counter at the ciirsor

$i = 1;

$mw->Button(-text => "Insert #", -command => sub { if ($e->selectionPresent { $e->insert( 'sel. last' "$i"); $i++; )

,

} )

}

->pack;

MainLoop;

We

the entry widget with "Entry Text" as a default. Then we create two butThe first one is the obvious Exit button that will allow us to quit the application. The second one is a bit more complicated. When pressed, it will check to see if any text is selected in the entry $e. If text is selected, it will insert a number that keeps track of the number of times we have pressed the Insert # button. fill

tons.

In Figure 5-12,

we

first

selected the

button four times. Each time

it

was

word

pressed,

"sel. last". This index didn't change

we

are counting backward!

"Entry"

in

it

and then pressed the

inserted a

between button

number

presses, so

Insert

at the it

*

index

looks as

if

121

The Entry Widget

m

,

g^,g,^_^»^

J

|Entry4.321 Text

Insert* „,.

.„:„™.

1

...J

Exit

Figure 5-12. Using the insert method

Scanning Text Both scanMark and scanDragto are used within the entry widget. They allow within the entry widget.

fast scrolling

coordinate passed

in for

$entrY->scanMark(.r)

$entrY->scaiiDragto

use

later

A

call to

scariMark simply records the x

with scanDragto.

It

returns an

empty

string.

;

(x)

;

The companion function to scanMark is scanDragto, which also takes an x coordinate. The new coordinate is compared to the scanMark x coordinate. The view within the entry widget is adjusted by 10 times the difference between the coordinates.

Working with the Selection The selection method has several possible argument web-page documentation, you'll see that you can use: $entry->selectionAdjust

You might 'adjust'

also see the

the

is

(

w^fer)

If

you look

at

the

.

where same thing as you

form $entry->selection( 'adjust'

argument. Be aware that they

first

lists.

mean

the

,

index),

read code written by other people.

You can

adjust the selection to a specified index

$entrY->selectionAdjust

The

To

selected text

is

(

index)

by using selectionAdjust:

;

extended toward the index (from whichever end

is

closest).

clear out the selection:

$entrY->selectionClear

Any

( )

selection indicator will be

removed from the entry widget, and the indices now undefined. The selected text remains.

'sel. first' and 'sel.last' are

To

reset the

'

anchor index '

to the specified index, use

$ent2r/->selectionFrom( index)

;

selectionFrom:

;

Chapter 5: Label and Entry Widgets

122

This does not affect any currently selected text or the indexes 'sel. first' and

'sel.last'.

The only way to check selectionPresent:

to see

if

($entrY->selectionPresent

if

there

( )

)

a selection in the entry widget

is

is

to use

{

}

It

returns a

1

there

if

a selection,

is

which means

'sel. first' and 'sel.last' indices printed

when you

there

no

is

there

(if

you can

isn't a selection,

selectionPresent

refer to either index).

safely use the

an error

will

will return a

be if

current selection.

You can change

the selection range

by

calling

selectioriRange:

$entry->selectionRange (startindex, endindex)

The two

that

;

where you would like the selection to cover. If startsame or greater than endindex, then the selection is cleared, causing sel first and sel last to be undefined. Otherwise sel first and 'sel.last' are defined to be the same as startindex 2Lnd endindex respeciively.

index '

indices indicate

the

is

.

'

'

.

'

'

The selectionTo method will cause the new anchor point to the specified index: '

(

index)

Changing the View xview

is

passed

in.

a

method

With no arguments,

set

from the current

;

in the Entry Widget

that will

change

will return a

it

purpose based on what arguments are

its

two-element

These two numbers define what currently

number .3,

be

'

$entry->selectionTo

1.

selection to

'

.

then

indicates

30%

how much

of the text

how much

returned

is

plus the

amount

that

When

$right)

=

of the text

list

off to the

is

is

containing numbers from

to

The first left and not visible. If it were widget. The second number

visible in the entry widget.

to the left of the entry

of the text

not visible on the

left

visible in the widget. In this case,

is

ally visible in the entry

($left,

is

is

side of the entry widget

50%

of the text

is

actu-

widget (see Figure 5-13)-

$entry->xview()

passing an index value to xview, the text in the entry widget will

tion so that the text at the specified index $entry->xview(/npack(-side => 'right', -fill => 'y'); $lb->pack(-side => 'left', -fill => 'both');

show

a

129

The Scrollbar Widget

Creating the scrollbar

we

create the listbox,

with the scrollbar vertical,

is

we want

pretty simple;

have to

when

up

set

a callback so the listbox can

(if

it

it

is

communicate

move around. Our scrollbar is set command and our scrollbar

horizontal, use -xscrollcoitimand).

by the user without using the by invoking $scrollbar->set (...).

listbox are scrolled

scrollbar

As we

it.

the contents of the listbox

so the -yscrollcommand option has the

assigned to

the default options for

all

When

the contents of the

scrollbar, the listbox will alert the

$scrollbar->configure( -command => 'yview' => $lb] does almost the opposite; it configures the scrollbar to communicate with the listbox. When the user clicks on the scrollbar, the scrollbar will invoke $lb->yview( The

line

[

)

.

to

tell

of the

how to change the view of the contents. We view command because this is a vertical scrollbar. the listbox

.

.

use the "y" version

yview in "How the Scrollbar Communicates with Other Widgets," later in this chapter. The last two lines in this example pack the scrollbar and the listbox in the window so that the scrollbar is the

There

is

more information on the

same height

as the listbox

Always pack your scrollbars to

and

scrollbars

remain

visible

details of

lies to

within the

first

when

the right of the listbox.

window or frame. This window smaller.

the user resizes the

resize the listbox (or other widget) but leave the scrollbars visible

allows the It

will

then

on the edges of

the screen.

Now set

that

we've seen a complete example of

up the widget

it

we

will scroll,

how

and how

to create a scrollbar

can go over the options with an idea of

to

how

they are used.

Scrollbar Options This

list

contains the options available with a scrollbar, and their quick definitions.

The important options

are discussed in

-activebackground =>

=>

detail later in this chapter.

color

Sets the color the scrollbar

-activerelief

more

'flat'

when

the

'groove'

|

should be |

mouse

pointer

'raised'

is

|

over

it.

'ridge'

|

'sunken'

The -activerelief option determines how active elements elements in question are arrowl, arrow2, and the slider.

-background => Sets the

are drawn.

The

color

background color of the

scrollbar (not the trough color).

-borderwidth => amount Sets the

width of the edges of the scrollbar and the arrowl, arrow2, and

slider elements.

|

130

Chapter

6:

Scrollbars

-command => callback Sets the callback that

invoked

when

displayed

when

is

the scrollbar

is

clicked.

-cursor => cursomame Sets the cursor that

is

the

mouse

pointer

is

over the scrollbar.

-elementborderwidth => amount Sets the

width of the borders of the arrowl, arrow2, and slider elements.

-highlightbackground =>

color

around the scrollbar widget should be

Sets the color the highlight rectangle

when

it

does not have the keyboard focus.

-highlightcolor =>

color

Sets the color the highlight rectangle

around the scrollbar should be when

it

does have the keyboard focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle. Default

-juitp =>

is 2.

1 I

jump

Indicates whether or not the scrollbar will

-orient => "horizontal"

|

scroll.

"vertical"

Sets the orientation of the scrollbar.

-relief => 'flat' 'groove' 'raised' Changes the edges of the widget. |

|

-repeatdelay => time Sets the number of milliseconds required auto-repeat. Default

is

1

|

1

'ridge'

to hold

'sunken'

down an arrow

|

'solid'

before

it

will

300 ms.

-repeatinterval => time Sets the number of milliseconds -takefocus =>

|

in

between

auto-repeats. Default

is

100 ms.

\indef

Controls whether the scrollbar can obtain the keyboard focus.

-troughcolor =>

color

Changes the color of the trough (both troughl and trough2).

-width => amount Sets the width of the scrollbar.

Scrollbar Colors Within the scrollbar, trough gets

its

own

we

have a

new

part of the widget called a trough. This

coloring through the

-troughcolor

considered the part behind the arrows and slider. Figure 6-6

The trough shows an example.

option.

is

ne Scrollbar Widget

131

-trou9hcok)r-> 'p»9n'

i

-3

:

"*' '

Figure 6-6. Scrollbar with -trough color set to 'green'

The background of tion

the scrollbar consists of the arrows, the slider, and a small por-

around the outside of the trough. You change the color of the background by

The -activebackground option controls the mouse cursor is over one of the arrows or the slider. Figure 6-7 shows two examples of -background; the second window uses both -background and -troughcolor. using the

color that

->!

-background

is

displayed

option.

when

-backpTMiiti => 'gremi'

the

rrii ~'

'

PI

-.j-lig=> 'green', -tnn^tocMn- ==> 'yefiow'

jqr

3 Xif

Figure 6-7. Examples of -background option

Scrollbar Style The -relief and -borderwidth options affect both the outside edges of the scrollbar and the arrowl, arrow2, and slider elements. This is similar to how the checkbutton and radiobutton widgets are affected by the -relief and -borderwidth options. See Figure 6-8 for a screen shot of different values for these two options.

dt

,

-JU -^1

a

,^,,

I^H

Scrrtlbar

^ ::^A

^A ^i W^ '^

Figure 6-8. First row shows different relief values; second row different relief values with -borderwidth => 4



The -activerelief option affects the decoration of three elements arrowl, arrow2, and the slider when the mouse cursor is over them. The -elementborderwidth also affects the same three elements: arrowl, arrow2, and the slider. The width of the edges of these elements can be changed with this option. The -borderwidth option also changes the width of these elements but



also

changes the width of the edges of the widget. Notice

edges of the scrollbar remain

at a

width of

2.

in Figure 6-9

how

the

152

Chapter

-eienwntbCMnterwMtti «>

-J

4

j

h

6: Scrollbars

^j ^^..1

-^

Figure 6-9- Example of -elementborderwidth set to 4

The -width of

the scrollbar

is

the distance across the skinny part of the scrollbar,

not including the borders. Figure 6-10 demonstrates

when you

how

the scrollbar changes

-width.

alter the

1

-^omentteittefWRitti »>

1

4

J

-





\^l

,''' '

Figure 6-10. Top scrollbar has default width of 15, bottom scrollbar has width of 20

Scrollbar Orientation As mentioned scrollbar

is

$scrollbar

You could

earlier, a scrollbar

can be

'vertical'. To change = $inw->Scrollbar

also use

this,

vertical or horizontal.

The

default for a

use the -orient option:

(-orient => 'horizontal');

-orient =>

'vertical', but since

this is the default,

it

is

not necessary.

Using the Arrows and Slider When you

on one of the arrows in a scrollbar, you cause the slider to move unit. If you continue to hold the mouse button down, after a bit of a delay, the slider will auto-repeat that movement. The amount of time you must wait before the auto-repeat kicks in is determined by the -repeatdelay option. The default is 300 milliseconds. click

in that direction

by one

Once you have held there

is

trolled

the

a short delay

mouse button down long enough

between each time

it

to start auto-repeating,

repeats the action. This delay

by the -repeatinterval option. The default

for

con-

is

-repeatinterval

is

100

milliseconds.

when you click on the slider and move around, the data within the move accordingly. This is because the scrollbar is updating the widget will only continuously as you move the slider. To change the scrollbar so that update the widget when you let go of the slider, use the -juirp option and set Normally,

widget

it

will

it

it

to

1.

The

default for -juirp

is 0.

You would most

likely

want

to use -juirp

=> 1

The Scrollbar Widget

when your

133

scrolled widget contains a large

screen to update while you slide through

amount of data, and waiting for the would make the application seem

it

slow.

Assigning a Callback when you list

create a scrollbar,

you

tell

it

which widget

to talk to

and which method

by using the -coinmand option with an anonymous list. The contains the name of the method to call and the widget from which that

in that

widget to

call

method should be invoked. In this code snippet, we can see the yview command to scroll the widget $lb (a listbox):

that

we want

to use

$scrollbar->configure( -coinmand => ['yview' => $lb]

Now when

on by the user, it will invoke $lb->Yview. $lb is vertical because it uses the yview command. For a horizontal scrollbar, use xview. Both yview and xview tell the widget to move the widget contents an amount that is determined by where the user clicked in the scrollbar. The yview and xview methods are cov-

We know

the scrollbar gets clicked

that the scrollbar associated with

ered in the next section.

How the Scrollbar Communicates with

Other

Widgets earlier, you use the -coinmand option with the scrollbar so it knows which widget and method to use when the scrollbar is clicked. The command

As described

should be xview for horizontal scrollbars and yview for

can

call

vertical scrollbars.

these methods yourself, but most of the time you won't want

You

to.

Both xview and yview take the same type of arguments. Where the user clicked in the scrollbar

determines the value used, but the value will always be sent as

one of the following forms:

$widget->xvievyMoveto fraction) # or $widget->yvievMoveto( fraction) This form is used when the user clicks on the slider, moves drops it again. The argument is a fraction, a real number from (

;

;

resents the

moved

first

part of the data to

the slider

all

the

way

the slider

to 1 that repIf

the user

to the top or left of the scrollbar, the very

were moved

;

to the center of the scrollbar, the

$widget->xviev\Moveto (0.5)

;

first

be seen on the screen. This means the

0:

$widget->xvievayioveto(0) If

around, and

be shown within the widget.

part of the data in the widget should

argument should be

it

argument

is 0.5:

;

;

134

Chapter

$widget->xviewScroll(^zwmfoer,

$widget->yviewScroll number, (

This form

is

used

when

Scrollbars

"units"); # or "units " )

the user clicks

The widget should move

scrollbar.

6:

data

its

number of

;

on one of

the arrow elements in the

up/down

or left/right unit by unit.

number means that the next unit of data on the bottom or right of the widget becomes visible (scrolling one unit of data off the left or top). A value of -1 means that a previous unit of data will become visible in the top or right of the widget (one The

first

argument

the

is

can be any number, but

bottom or

unit will scroll off the

1

A

or -1.

right of the widget).

The value value of

for

1

For example, every time

on the down in a vertical scrollbar associated with new line shows up at the bottom of the listbox. arrow

the user clicks

box, a

units to scroll by.

typically either

it's

The second argument

is

the string "\jnits".

widget. In a listbox, a unit

would be one

would mean one

What

a unit

line of text. In

is

a

list-

depends on the

an entry widget,

it

character.

Here are some example

calls:

User clicked down arrow $listbox->yviewScroll (1, "units") #

User clicked up arrow $listbox->yviewScroll (-1,

#

"units")

User clicked right arrow $entry->xviewScroll (1, "units");

#

$widget->xviewScroll (;7wm^er, $widget->yviewScroll number, (

This form

is

"page"); # or

"page "

exactly like our previous

instead of "units".

(between the

slider

When

)

;

one except the

last

argument

is

"page"

users click in the trough area of the scrollbar

and arrows), they expect

to see the data

move by an

entire page.

The type of page is defined by the widget being scrolled. For example, a listbox would page up/down by the number of lines shown in the listbox. It would page right/left by the width of the listbox.

Scrollbar Configuration get and set any of the options available with a scrollbar by using cget and configure. See Appendix A, Configuring Widgets with configure and cget,

You can for

complete

details

on these methods.

I

The Scrollbar Widget

Defining

135

What We Can See

The set method, which we tell the scrolled widget about when we create it, defines what is visible. In our first example, we created a listbox and told it to use our scrollbar and the set method: $scrollbar = $inw->Scrollbar # Vertical scrollbar $lb = $mw->Listbox(-yscrollcommand => ['set' => $scrollbar ;

( )

When

the widget invokes the

set command,

it

]

)

sends two fractions

and

lasi)

The arguments

first

the position of the

first

(first

as the arguments:

$scrollbar->set (first, last);

This will change the position in the data that

and

last are real

numbers between

and

1

.

we

are seeing.

They represent

we can see and the position of the last data item we can see, respecIf we can see all of the data in our widget, they would be and 1. 1^\\q first

data item tively.

value gets larger as more data smaller as

more data

case in which to

is

is

scrolled off the top,

scrolled off the bottom.

call set yourself,

so

You

just try to get

and the

will

last

value gets

probably never find a

an idea of what

it

does behind

the scenes.

complete data

"first"

item

line

1

line

2 item 1,2

line

3

line

4

1

10%

into data

view of data

80%

"lastline

20

line

21

tfirougti

widget

into data

Figure 6-11. View of data through widget by set method (assumes vertical scrollbar)

document that we are viewing with a vertically The dashed rectangle represents the view of what we can cur-

Figure 6-11 shows a hypothetical scrolled widget.

rently see within the widget.

When

the widget calls set,

it

determines

how

far into

document the first viewable item is and sends this as the first argument. In Figure 6-11, this would be 10%, or 0.10. The second argument to set{) is how far into the document the last viewable item is. From our example, this would be the

80%, or

0.80.

)

;

;

136

Chapter

6: Scrollbars

Getting the Current View The get method

returns in a

$last)

{$first,

list

whatever the

$scrollbar->get

=

This data can change

if

(

latest

arguments to set were:

)

the widget requests a change in position of the data or

if

the scrollbar requests a change.

Activating Elements in a Scrollbar To determine which

part of the scrollbar

is

you can use the activate

active,

method: $elem

=

$scrollbar->activate(

The value returned active) or the

name

)

an empty

is

(which means no element

string

of the currently active element.

is

currently

The possible elements

are

"arrowl", "arrow2", or "slider".

you send an element name as the argument to activate, that element will to the color and relief specified by the -activebackground and -activerelief options. The element will continue to display that color and relief

If

change until

an event (such as the mouse cursor passing over the element) causes

it

to

change. Contrary to what you might believe, using activate does not invoke that element. Here are

some examples:

$scrollbar->activate "arrowl " $scrollbar->activate "arrow2 " $scrollbar->activate( "slider" (

(

no activate when the mouse is over There

is

for

"trough" because the trough doesn't change color

it.

Calculating Change from Pixels The number returned by delta

move

indicates

how much

the slider deltax pixels for horizontal scrollbars

scrollbars.

(The inapplicable argument

$ainount = $scrollbar->delta((i(?/itoc,

The amount returned can be

is

the scrollbar must change to

and deltay

pixels for vertical

ignored for each type of scrollbar).

deltay)

positive or negative.

Locating a Point in the Trough Given

a point at (x,y),

cating

where

fraction

that coordinate point

$loc = $scrollbar->fraction(.Y,

will return a real

would v)

;

fall in

number between

and

the trough of the scrollbar:

1

indi-

Examples

137

The point

(x,y)

must be

relative to the scrollbar. Figure 6-12

three possible results from fraction: 0.0, 0.5

and

shows

the location of

1.0.

Figure 6-12. Example of values returned by the fraction method

Identifying Elements The identify method

returns a string containing the

name

of the element located

at the x,y coordinate:

$elem If

x,y

is

-

$scrollbar->identify (x,j')

;

not in any element, the string will be empty. Both

coordinates relative to the scrollbar. The possible element

x and y must be names

pixel

are "arrowl",

"arrow2", "trough", and "slider".

Examples These examples are included use scrollbars in the ble;

we

then

we do

the

Each example uses the Scrolled method

same thing manually.

are using here, but

we

up any confusion about how

to hopefully clear

real world.

aren't

We

haven't covered

all

doing anything fancy with them

an option or method you don't recognize,

just

if

to

possi-

the widget types either. If

you see

see the appropriate chapter for that

widget to learn more.

Entry Widget The

line of text at most,

so a vertical scrollbar

create a scrolled entry widget $inw->Scrolled( "Entry" If

The entry can only contain one would do nothing. Using Scrolled to

entry widget can only be scrolled horizontally.

you want

requires

it,

to

make

,

is

easy:

-scrollbars => "s", -width => 30)->pack();

the scrollbar only

use -scrollbars

=>

show when

"os". Using the

the data in the entry widget

Scrollbar method

more work: $scrollbar = $niw->Scrollbar (-orient => 'horizontal'); $entry = $mw->Entry (-width => 30, -xscrollcommand => $scrollbar] set $scrollbar->configure( -command => ['xview', $entry] $scrollbar->pack(-side => 'bottom', -fill => 'x'); $entry->pack(-side => 'bottom', -fill => 'x'); [

'

'

,

)

)

Both

will create

an entry

that looks similar to the

one

in Figure 6-13-

is

a bit

;

)

,

138

Chapter

^j

Entry

j

.

iReally really really long

N

Scrollbars

6:

t

^

1

Exit

Figure 6-13- Entry widget with a scrollbar

Listbox, Text,

A

and Canvas Widgets

widget can be scrolled both horizontally and

listbox

might not always want to use both options. going to be and the

Our

essary.

first

If

window can accommodate

although you

vertically,

you know how wide your data it,

a horizontal scrollbar

example uses the Scrolled method and creates two

is

unnec-

is

scrollbars:

$mw->Scrolled( "Listbox" -scrollbars => "se", -width => 50, -height => 12)->pack(); ,

same thing manually, we need to use Scrollbar bars and configure them to work with the widget:

To do

the

$f = $inw->Frame() ->pack(-side => 'top', expand => 1, $xscroll = $f->Scrollbar (-orient => 'horizontal');

to create

two

scroll-

-fill => 'both');

$yscroll - $f->Scrollbar() $lb = $f->Listbox{ -width => 50, -height => 12, -yscrollcommand => ['set', $yscroll] -xscrollcoinmand => ['set', $xscroll] $xscroll->configure( -command => ['xview', $lb] $yscroll->configure( -command => ['yview', $lb] $xscroll->pack(-side -> 'bottom', -fill => 'x') $yscroll->pack{-side => 'right', -fill => 'y'); $lb->pack(-side => 'bottom', -fill => 'both', -expand => 1); )

Scrolled saves a lot of extra work. with two scrollbars, one on the south and one on

As you can a listbox

see, using

was created using Scrolled. There is a open space where the two scrollbars meet ate the scrollbars ourselves,

packed

first

Scrolled text

widget

One

is

takes

In Figure 6-14,

the east. This

we

see

window

subtle difference: the small square of in the southeast

comer.

When we

cre-

don't get that small space (whichever scrollbar gets

it).

and canvas widgets are created the same exact way a scrolled we won't bother repeating the same code again.

listbox

created, so

Scrollbar, Multiple Widgets

There are times

When

we

;

when you want

the user clicks

direction at the

same

on the

to use

scrollbar,

one it

more than one widget. the widgets in the same

scrollbar with

should

time. For this example,

scroll all

we

will create three listboxes,

each

Examples

139

J

ScrcMed Ustbox

->]

# Conversion from Tk4.0 scrollbar.tcl competed,

package Tk::Scronbar; require IK;

use AutoLoader;

@ISA =

qwCrX::Widget);

Construct Tk::W!dget 'Scrollbar'; bootstrap Tk::Scrollbar $Tk::VERSION;

sub Tk_cmd '

{

\8(Tk::scro[lbar }

R

/ i

'

\

Figure 6-14.

A

listbox with

two scrollbars

with eleven items. There will be one scrollbar that will scroll

all

on it. When the user tabs to the listboxes and scrolls by using the arrow keys or the pageup/pagedown keys, the other also scrolled. Figure 6-15 shows what the window looks like. the user clicks



cine Scfiiiiatf!iiir»3 five

^

when up and down

three

five

;SlX

six

six

jseven

seven

seven

eight

eight

eight

rane

nine

nine

ten

ten

ten

The code

A window

j

with three listboxes all controlled by the

for Figure 6-15

is

same scrollbar

as follows:

use Tk; MainWindow->new() Scrollbar /Three Listboxes"); $rnw->Button(-text => "Exit", -concnand => sub { exit } ->pack(-side => 'bottom');

$inw -

;

$iTiw->title( "One

)

$scroll = $mw->Scrollbar() # Anonymous array of the three listboxes $listboxes = $mw->Listbox $mw->Listbox( [

( )

,

listboxes are

"JUnH

Usttox£»

five

Exit

Figure 6-15.

lists

)

,

$mw->Listbox()

];

;

140

Chapter

6: Scrollbars

This method is called when one listbox is scrolled with the keyboard makes the scrollbar reflect the change, and scrolls the other lists sub scroll_listboxes { my ($sb, $scrolled, $lbs, @args) = @_; $sb->set (@args) # tell the scrollbar what to display my ($top, $bottom) = $scrolled->yview( foreach $list (@$lbs) { $list->yvievMoveto($top) # adjust each lb #

# It

;

)

;

}

}

Configure each listbox to call &scroll_listboxes foreach $list (@$listboxes) { $list->configure{-yscrollcommand => \&scroll_listboxes, $scroll, $list, $listboxes ]);

#

[

}

Configure the scrollbar to scroll each listbox $scroll->configure(-comaTiand => sub { foreach $list (@$listboxes) $list->yview(@_)

#

{

;

}});

Pack the scrollbar and listboxes $scroll->pack(-side ~> 'left', -fill => 'y'); foreach $list (@$listboxes) { $list->pack(-side => 'left'); $list->insert 'end' "one", "two", "three", "four", #

(

,

"seven",

"eight",

"nine",

"five",

"ten",

"six",

"eleven");

}

MainLoop; In order to connect multiple widgets to

command for

to create the scrollbar.

each of the listboxes

array so that

all

is

scrollbar,

we

use the Scrollbar

first

to configure

easily).

The other

each listbox to

part

subroutine

three listboxes in addition to adjusting the scrollbar. Normally,

all

-yscrollcoiranand would only have ['set',

$lb] assigned to

set from within

Fun Things

call

scrollbars for the

method you

it.

Instead,

we

that subroutine.

to Try

Create two of each scrollable widget type,

own

it

call a special

use a callback to \ScScroll_listboxes and

your

calls yview anonymous that makes the

the scrollbar so

are scrolling (the listboxes are kept in an

methods can reference them

listboxes truly connected that scrolls

we

one

Then we configure

make one Scrolled, and create will show you which

second of each type. This

prefer to use.

Create two scrollbars and attach them to the

same widget

(the opposite of our

one scrollbar/multiple widgets example). For instance, create a listbox with a scrollbar on the left and one on the right, both of which will scroll the listbox vertically.

The Listbox Widget

A

listbox widget

per

line.

box

is

designed to

You can then

list

strings of text,

one

select a line or multiple lines

text string

from the

list-

perform other operations on. Some examples of things to

to

place inside a listbox:



An



A

alphabetized

list

of

cities.

of servers to log in

list

password

into

some

to.

name and then

Select a server

entry widgets. Click the

OK

enter a

button to log

name and

in.



A

list

of operating systems.



A

list

of payment options: MasterCard, American Express, Visa, Check, Cash.

A

listbox

is

numerous

ideal for replacing radiobuttons or

checkboxes

that

have become too

on the screen. Usually 3 or 4 checkbuttons or radiobuttons if you had to try to display 10 at a time, the window could get a little crowded. A group of radiobuttons can be replaced by a listbox that limits the number of selections to one and has a default selection. A bunch of checkbuttons can be replaced by a listbox that allows multiple selections. to display

aren't a big deal, but

Creating To

and Filling a

create a listbox widget, use the $lb = $parent->Listbox(

The Listbox method can

now

use

this

[

Listbox

Listbox method on

options .. .]

the parent of the listbox:

)->pack;

returns a reference to the listbox that has

been

created.

You

reference to configure the listbox, insert items into the listbox.

141

; ;

;

,

142

;

Chapter

and so on. The most common thing insert method to insert items into it: $lb->insert{ 'end'

,

@listbox_i terns)

,

$iteinl,

to

do

after creating a

7:

The Listbox Widget

Hstbox

is

to use the

# or...

$lb->insert( 'end'

$item3);

$item2,

The insert method takes an index value arguments

will

be considered items

to

as the

be put

argument; the

first

rest

of the

into the listbox. Listbox indexes are

similar to the entry widget indexes except they refer to lines instead of individual

characters.

We

could use a listbox instead of radiobuttons to select our

color (see Chapter

The

ple).

listbox

Checkbuttons

4,

code looks

and

window background

Radiobuttons, for the radiobutton exam-

like this:

$lb = $rnw->Listbox(-selectmode => "single" ->pack() $lb->insert 'end' qw/red yellow green blue grey/); $lb->bind( '' sub { $lb->configure( -background => $lb->get $lb->curselection )

{

,

(

( )

)

)

});

The -selectimode option limits the number of selections to one. "We insert some colors to choose from. There is no -command option for a listbox, so we use bind (see Chapter 14, Binding Events) to have something happen when the user clicks on an item with the left mouse button. Using the listbox methods get and curselection, we determine which item the user clicked on and then set the background of the here;

listbox to that color.

There are only

you can use more colors and add

can add a scrollbar by changing the

line

five colors in

a scrollbar to

make

with Listbox in

it

more

our example useful.

You

it:

$lb = $mw->Scrolled{ "Listbox" -scrollbars => "e", -selectmode => "single") ->pack() ,

All the other lines in the

adding and

an example,

we want

program remain unchanged. For more information about

utilizing scrollbars, let's

see Chapter

6,

Scrollbars.

go over the options and methods

Now

that let us

that

we've looked

use the listbox the

at

way

to.

Listbox Options As with any of the widgets, you can configure the listbox using options. The

stan-

dard widget options are -cursor, -font, -height, -highlightbackground,

-highlightcolor, -highlightthickness, -takefocus, -width, -xscrollThe options that behave the same for each widget will only be listed in the following list. Those options specific to listbox coramand, and -yscrollcommand.

widgets will be discussed

later in this chapter.

143

Listbox Options

-background =>

color

Sets the color of the area

behind the

text.

-borderwidth => amount Sets the

width of the edges of the widget. Default

is 2.

-cursor => cursomame Sets the cursor to display

-exportselection => Determines tion as well.

the

same

when

the

mouse

is

to

If set

1,

listbox.

1

|

the current listbox selection

if

over the

is

made

available for the

X

selec-

prevents two listboxes from both having selections

at

time.

-font => fontname Sets the font of any

-foreground =>

text displayed within the listbox.

color

Sets the color of nonselected text displayed in the listbox.

-height => amount Sets the height of the listbox.

-highlightbackground =>

color

Sets the color the highlight rectangle should

be when the

listbox

does not

have the keyboard focus.

-highlightcolor =>

color

Sets the color the highlight rectangle

should be

when

the listbox does have

the keyboard focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle. Default

-relief => 'flat'

'groove'

|

Sets the relief of the

'raised'

edges of the

-selectbackground => Sets the color

|

|

is 2.

'sunken'

'ridge'

|

'solid'

listbox.

color

behind any selected

text.

-selectborderwidth => amount Sets the

width of the border around any selected

-selectforeground =>

color

Sets the color of the text in

-selectmode => "single" Affects

how many

text.

|

any selected

"browse"

items can be selected

items.

at

once; also

bindings for the listbox (such as Shift-select). Default

-setgrid =>

|

1

Turns gridding off or on for the

"extended" affects some key/mouse

"multiple"

|

listbox. Default

is 0.

is

|

"browse".

144

Chapter

-takefocus => never,

1

1

|

Determines the

7:

The Listbox Widget

undef

|

ability of the

widget to get the keyboard focus or not.

means always, undef means dynamic

means

decision.

-width => amount Sets the

width of the listbox in characters.

made

wide

as

If

amount

is

or

less,

the listbox

is

as the longest item.

-xscrollcoinmand => callback Assigns horizontal scrollbar to widget. See Chapter

6.

-yscrollcoramand => callback Assigns vertical scrollbar to widget. See Chapter

Selection As part of the

6.

Modes

listbox widget,

select items in the listbox.

you

are given several choices in the

You can have

selected (emulating radiobuttons), or

it

so only one item

you can have many

at a

way you can time can be

different contiguous or

noncontiguous items selected (emulating checkbuttons). You control

this

behavior

with the -selectimode option.

The

possible

select

modes

are

"extended". The default mode

is

"browse",

"single",

"multiple",

or

"browse".

browse & single The "browse" and "single" modes are similar in that only one item can be selected at a time; clicking on any item will deselect any other selection in the listbox. The browse mode has a slight difference: when the mouse is held down and moving around, the selection moves with the mouse. For bind purposes, a "" bind will be invoked when you first click down. If you want to catch the event when the mouse is released, define a ButtonRelease binding (binding events to widgets is discussed in Chapter 14). extended The "extended" mode lets you select more than one item at a time. You can click on a single item with the left mouse button, but it will deselect any other selection. To select more than one item, you must Shift-click or Control-click more items. Shift-clicking (holding down the Shift key while pressing a mouse button) will extend the selection from the already selected item to the newly selected item. Control-clicking (holding

mouse alter

button) will

any of the other

button, hold

down

select them. This

is

down

the Control key while pressing a

add the item being clicked on to the selection, but selections.

it

won't

You can also click an item with the mouse move the pointer over other items to

the button, and then

what

for very fast selection of

I

call a click-drag

many

motion. Using "extended" allows

different items in the listbox.

145

Colors

multiple The "multiple" mode

you to select more than one item. Instead you have to select items one at a time. select it, and selecting an already selected

also allows

of Shift-clicking or Control-clicking, Selecting an unselected item will

item will unselect

it.

Operating System Differences when

-selectmode feature, I discovered that Windows 95 does not allow the "multiple" selection mode to behave properly. It behaves the same as "single" mode on Windows 95 only. On Unix and Windows NT, "multiple" mode works correctly. testing the

When you tion

select

an item

in a listbox,

(meaning you can cut and paste

by default

it

any

X

it

like

made

is

available as an

X

selec-

any window). Even

selection in

do anything with the clipboard on Win32 systems, it still affects the selection in multiple listboxes. Items can be selected in only one listbox at a time, even if you have more than one listbox. The option -exportselection controls this. Use -exportselection => to allow items to be though

this

selected in

doesn't

more than one

listbox at the

same

time.

Colors In

most widgets there

those,

we

also

is

a

-background and

a

-foreground

color. In addition to

have the -selectbackground and the -selectf oreground color

options in a listbox.

When

a listbox entry

is

selected,

it

appears in a different

color.

Although you can change the color of the selected color.

You cannot make

text,

you can only use one

different lines in the listbox different colors.

U$$toK

E

p

one

Ustbox

•tH^al

one

two

two

three

three

four

four

/

five

Figure

7-1.

Examples of -foreground, -background,

In Figure 7-1, the listbox

on the

ground

=>

'red',

-selectbackgroimd =>

left

-selectforeground,

has -foreground

'green'. The listbox on the

right

and

=>

-selectbackground

'red',

-back=>

has -select foreground

'green'. Make sure that the foreground and

background values contrast with each other

if

you change these

options.

146

Chapter

7:

The Listbox Widget

Listbox Style -relief of a listbox is 'sunken'. The default -borderwidth is 2. shows the five different relief types (flat, raised, ridge, groove, and sunken). In the first window, the default -borderwidth is used; in the second window, a -borderwidth of 4 is used. To save space in the windows, I didn't draw any scrollbars. The

default

Figure 7-2

_l

Figure

Style

h

UstiMix

Ustbox

-^

J|

mm^^

one

one

one

one

one

one

one

one

one

one

two

two

two

two

two

two

two

two

two

two

three

three

three

three

three

three

three

three

three

three

four

four

four

four

four

four

four

four

four

four

five

five ~—;

five

five

ifive

five

five

five

five

five

!

Examples of -relief and -borderwidth in

7-2.

listboxes

of Selected Items

is also a borderwidth associated with any selected text. This is controlled by -select±)orderwidth option. Figure 7-3 shows what changing the selection

There the

borderwidth to 4 does to the

listbox.

-^Jl lone

two

1 5

.three

four five *

t

\

1

Figure

Example of -selectborderwidth => 4

7-3-

Special Listbox Resizing The -setgrid option changes how the window is drawn when it's resized. Using -setgrid => 1 causes the window to stay resized to the grid created by the listbox widget. Essentially, this means that the listbox will display only complete lines (no half

lines)

always display

and complete at least

option has nothing to

box

in the

window.

characters.

A

side benefit

is

that the listbox will

and can't get resized off the visible window. This do with which geometry manager you use to put the listone

line

147

Inserting Items

Listhox Indexes The items in an entry widget are ordered. The first listbox item is at index 0, and the numbers increment by 1 These values are valid for any of the methods .

an index value.

that require

n

An

integer index.

The

item in a listbox

first

index

at

is

0.

"active"

The index within

the listbox that has the location cursor.

has the keyboard focus,

it

will

If

the listbox

be displayed with an underline.

"anchor" This index

is

set

with the selectionAnchor (...) method.

"end"

The end of it

or

the listbox.

Depending on which method

mean just after the last element could mean the last element in the

could it

is

using this index,

when insert is used), (such as when delete is

(such as listbox

used).

"@x,y"

The

listbox item that covers the point at the coordinate x,y (pixel coordi-

nates).

The

closest item will

be used

if

x,y

is

not

at a specific item.

Configuring a Listbox You can use the cget method to options. You can use configure

find out the current value of

any of the listbox

to query or set any of the listbox options. See Appendix A, Configuring Widgets with configure and cget, for more information on using the configure and cget methods.

Inserting Items Use the insert method $lb->insert

to

add items

element,

(;>7insert

(

,

beginning of the

@new_elements

7:

The Listbox Widget

listbox:

)

Deleting Items You can use

delete method

the

$lb->delete{firstindex-

The

first

just that

[,

from the

listbox:

lastindex ]);

argument is the index from which to start deleting. To delete more than one item, you can add a second index. The firstindex must be less than or

equal to the lastindex specified. $lb->delete(0,

To

to delete items

To

delete

the elements in the listbox:

all

'end');

delete the last item in the listbox:

$lb->delete

( '

end

'

)

Retrieving Elements The get method

returns a

of listbox elements specified by the indexes first to

list

last:

$lh->get firstindex {

If

only the firstindex

be

less

is

[,

specified, only

than or equal to the lastindex.

©elements = $lb->get(0,

To

lastindex

])

one element

To

get a

list

of

is

returned.

all

The firstindex must

elements

in the listbox:

'end');

get the last item in the listbox:

$lastitem = $lb=>get 'end' (

To

find

)

out which items in the listbox are selected, use the

curselection

method: @list = $lb->curselection()

containing the indexes of

It

returns a

list

If

no items

are selected,

ple of

how

the

all

currendy selected items

curselection returns an empty curselection method is used:

string.

in the listbox.

Here

is

an exam-

©selected = $lb->curselection; foreach (©selected) { # do something with the index in $_ }

Make

sure to

remember

that

curselection

returns a

list

of indexes, not elements.

Selection

149

Methods

Selection

Methods

The curselection method, discussed in the preceding section, only what the user has selected. You can also change the selection by using the selection method.

tells

a

you

form of

Selecting Items To select a range of items in a listbox, you can use the "set" form of the selection method (selectionSet). select ionSet takes either a single index or a range. Any items not in the range are not affected. If you use a range, the first index must be less than or equal to the last index. Here are some examples: select everything $lb->selectionSet(0, 'end' ttselect the first item $lb->selectionSet (0) #

Even

if

);

you have used -selectmode

to limit the selection to only

one

item,

you

can force more than one item to be selected by using selectionSet (...)•

Unselecting Items To clear any selections in the listbox, use the "clear" form of the selection method (selectionClear). Pass in an index or a range or indexes from which to remove

clear the selection. For instance, to

would do

all

the selections in the listbox,

you

the following:

$lb->selectionClear (0,

Any indexes

"end");



outside the specified range will not be unselected

unselect one item

at a time.

You can

$lb->selectionClear "end"

also clear the selection

this

from

just

allows you to

one

item:

{

)

Testing for Selection To test to see if a specific index is selection (selectionlncludes). item last

at

the specified index

item in the if

}

list is

is

already selected, use the "includes" form of Calling

selected

and

selected:

($lb->selectionIncludes 'end' (

)

)

{

selectionlncludes if it is

not.

returns

1 if

For instance, to see

if

the the

;

;

;

;

;

150

Chapter

7:

The Listbox Widget

Anchoring the Selection Using the "anchor" form of selection (select ionAnchor) to

"anchor"

mouse

used

is

when you

set the

index

are using the

The first item you click becomes the "anchor" index. For exam-

cursor to select several items within the listbox.

(without letting up on the ple,

The "anchor"

to the specified index.

you would use

mouse

button)

this to set the

anchor as the

first

item in the

list:

$lb->selectionAnchor (0)

Moving To cause

a

to

the listbox to

%Vo->se.& {index)

show

Index

a specific item,

you can use the see method.

;

Given an index, see index. For

Specific

will

cause the listbox to page up or

an example of using see, look

at

the Listbox

down

to

Example

show

the item at that

later in this chapter.

Translating Indexes The index method

an index specification (such as "active") into the = if the listbox contained 12 items, $index

translates

numerical equivalent. For instance,

$lb->index( "end") would item in a listbox

is

at

index

set the variable

$index

to 11.

(Remember

the

first

0.)

Counting Items The size method

returns the total

number

of items in the listbox:

$count = $lb->size();

Active Versus Selected The activate method will set the listbox item at index index to the active element. This allows you to access this item later using the "active" index. Figure 7-4 shows two windows with active elements underlined. Each listbox also has the black highlight rectangle around it, which indicates it has the keyboard focus (the active element isn't seen as marked unless the listbox has focus). The first window activates the item "four" $lb->activate(3) $ lb- > focus # The second window activates the item "three" $lb2->activate(2) $lb2->focus() #

( )

Scrolling

Figure

Methods

7-4.

151

Windows showing a

listbox with

an

"active" element

Bounding Box The method bbox around the ($x,

returns a

list

of four elements that describes the bounding

box

text at index.

$y,

$w,

$h)

= $ lb- >bbox( index)

The four elements are (in order): x, y, w, and h. The x,y coordinates are the upper left corner of the bounding box. The w is the width of the text in pixels. The h is the height of the text in pixels. These measurements are shown in Figure 7-5.

x,y Text

in

listbox

h

W Figure

7-5.

Bounding box values around text

Finding an Index by Y Coordinate If

you know

a

y coordinate in the listbox, you can determine the index of the it by using the nearest method:

nearest listbox item to

$index = $lb->nearest {y)

The nearest method

returns a

number

that

corresponds to the index of the clos-

est visible listbox item.

Scrolling

Methods

The listbox can be scrolled both horizontally and vertically so it has both xview and yview methods and all their associated forms. These forms and how to use them are described in detail in Chapter 6.

;

;

;

152

Chapter

7:

;

The Listbox Widget

The scan method allows you to use a really fast scrolling method. It is automatically bound to the second mouse button by the listbox. Here is how you can do the same thing within your window: $mw->bind( "Listbox" $inw->bind( "Listbox"

When you

""

""

[

'scan'

,

window

click in the

your mouse around, speed.

,

,

,

'mark' ,Ev( 'x' [

,

'scan'

,

]

)

)

with the second

to bind this to another combination of

method

is

explained in Chapter

,Ev( 'y'

)

]

)

mouse button and then move by

at super-fast

bind statement if you keys/mouse actions. The bind

14.

Example

Sometimes when you put

ment

)

the second argument of each

wanted

through the

)

you'll see the contents of the listbox zip

You could change

Listbox

,Ev( 'y'

'dragto' ,Ev( 'x'

listbox. If

a lot of items in a listbox,

you

it

takes a long time to scroll

insert the items in the listbox sorted,

a search routine. Here's a quick script that

shows you how

you can impleto use

an entry

widget to input the search text and then search the listbox every time you get

new

character in the entry:

use Tk; $inw =

MainWindow->new;

$rnw->title "Listbox" (

)

;

For exaitple purposes, we'll use one word for each letter @choices = qw/alpha beta charlie delta echo foxtrot golf hotel India Juliet kilo lima motel nancy oscar papa quebec radio sierra tango uniform victor whiskey xray yankee zulu/; #

Create the entry widget, and bind the do_search sub to any keypress $entry = $mw->Entry(-textvariable => \$search) ->pack(-side => "top", -fill => "x"); \&do_search, Ev("K") $ent2ry->bind( "" #

,

[

]

)

Create listbox and insert the list of choices into it $lb = $mw->Scrolled( "Listbox" -scrollbars => "osoe", ->pack(-side => "left"); $lb->insert "end" sort ©choices) #

rny

,

)

(

,

$mw->Button(-text => "Exit", -command => sub

{

exit;

})

->pack(-side => "bottom");

MainLoop; # This routine is called each time we push a keyboard key. sub do_search { my (Sentry, $key) = @_;

a

Fun Things

to Try

153

Ignore the backspace key and anything that doesn t change the word The Control or Alt keys return if ($key =~ /backspace/i) rettum if ($oldsearch eq $search) #

'

# i.e.

Use what's currently displayed in listbox to search through This is a non-coir^slicated in order search my ©list = $lb->get(0, "end"); foreach (0 $#list) { if ($list[$_] =~ /^Ssearch/) { $lb->see{$_) $lb->selectionClear (0, "end" $lb->selectionSet($_) # #

.

.

)

;

last; }

>

$oldsearch = $search;

Fun Things Use

a listbox to create a

mini

file

when you

click

on

a button that, file

to Try

becomes one

viewer. Use an entry field to read a filename and it,

loads the

entry in the listbox).

file

into

your listbox (each

line in the

The Text Widget

when you

think about what a text widget might do,

displays text." This

is

tnie, yet

can do quite a

it

bit

you automatically more. The text widget

the most powerful standard widgets available in Perl/Tk. urable,

and easy

It

is

is

flexible,

Here are some examples of

to use for simple tasks.

think,

"it

one of config-

how you

can

use text widgets: Display and edit a plain text

file.

HTML

Display formatted text from an

document.

Create a scrollable color key, with buttons that allow you change the colors

Gather multiline, formatted text (including colors) from a user (mini word processor).

Display text with different colors based on the input.

Make

on. This could be

You can text

put simple

HTML, or

text,

widget can be used

Creating

it

could be similar to the widget demo.'

formatted

much

create a text widget, use the (

[

with scrollbars to allow

154

many pages

A of

Text Widget

Text method from

options

...

]

)

the desired parent widget:

->pack;

When you in.stalled the Tk module with Perl, you also in.stalled command line to .see the capabilitie.s of widgets in Perl/Tk. •

inside a text widget.

less space.

and Using a

$text = $parent->Text

and other widgets

text,

in conjunction

information to be viewed in

To

and perform an action when clicked

certain portions of text "clickable"

the widget

demo. Type widget on the

Text Widget Options

155^

After the text widget

The user can type

directly into

$text->insert 'end' (

The

basic form of the

,

insert method

A

you do, only the

typical use of the text

it's

start

takes

placing the

two arguments. The

first

widget

item in the array is

to read a

file

first is

The second argument

text.

insert method, you

to insert. Unlike the listbox If

it,

text in

it.

"To be or not to be...\nThat is the question");

value that indicates where to

argument.

ways to place or you can use the insert method:

created, there are several different

is

can't use is

an index the string

is

an array as the second

inserted into the text box.

and place

it

in the text

widget as

read:

$text = $inw->Scrolled("Text") ->pack() die "Could not open chapterl"; open (FH, "chapterl") while () { $text->insert 'end' $_) ;

|

|

(

,

}

close (FH)

You can use

the text widget to display the

ing the insert line to

$text->insert (0,

backward

file

$_)

.

(line

by

line)

by chang-

This will put the next line read

at

the top of the text widget instead of at the end.

The

text

widget can do a

lot

more than

Shakespearean play. In addition to options, to control

how

display a

just

we

also

file

have

or

two

lines

tags, indexes,

from a

and marks

the contents of a text widget are displayed.

Text Widget Options Options used with the Text method change the

way

the text

within the text widgets. The following options are standard for

all

is

displayed

the widgets:

-borderwidth, -cursor, -exportselection, -foreground, -highlightbackground, -highlightcolor, -highlightthickness, -insert-

-background,

-insertontime, -insertborderwidth, -insertofftime, -insertwidth, -padx, -pady, -selectbackground, -selectborderwidth, -selectforeground, -setgrid, -state, -takefocus, -wrap, -xscrollcommand, and -yscrollcoitimand. background,

To

more about what these options do, check back where they were first covered.

find out

Button,

-background =>

to

Chapter

3,

The Basic

color

Changes the color of the screen displayed behind the

text.

-borderwidth => amount Sets the

width of the edges of the widget.

-cursor => cursomame Sets the cursor displayed

when

the

mouse

cursor

is

in front of the text widget.

|

156

.

Chapter

-exportselection => Determines

if

The Text Widget

1

|

the text selected within the widget can also be used

dowing system (such

as

X

-font => fontname Sets the font in which the

-foreground =>

8:

by the win-

windows).

text

is

displayed.

color

Sets the color of the text.

-height => amount Sets the height of the widget. Default

-highlightbackground =>

is

24.

color

Sets the color the highlight rectangle

around the widget should be when

it

around the widget should be when

it

does not have the keyboard focus.

-highlightcolor =>

color

Sets the color the highlight rectangle

does have the keyboard focus.

-highlightthickness => amount around the widget. Default

Sets the thickness of the highlight rectangle

is 2.

-insert±)ackground => color Changes the color of the

insert cursor.

-insertborderwidth => amount Changes the width of the

insert cursor.

-insertofftime => time Sets the time the insert cursor blinks in the off position. Default

is

300.

is

600.

-insertontime => time Sets the time the insert cursor blinks in the

on

position. Default

-insertwidth => amount Sets the

width of the

-padx => amount Adds extra space -pa amount Adds extra space

insert cursor.

to the left

and

to the top

right of the text inside the text widget's edge.

and bottom of the

text inside the text widget's

edge.

-relief => 'flat'

|

Sets the relief of the

'groove'

|

'raised'

|

'ridge' 'sunken' sunken is

edges of the widget. Default

-selectbackground =>

color

Sets the color of the area behind the selected text.

-selectborderwidth => amount Sets the width of the border of the selected area.

'

'

|

'solid'

157

Text Widget Options

-selectforeground =>

color

Sets the color of the selected text.

-setgrid =>

1

|

Enables gridding for the text widget. Default

-spacingl => amount Sets the amount of additional space its

own

Default

line.

left

is 0.

on top of

a line of text that begins

-spacing2 => amount Sets the amount of additional space left on top of a line of text after been wrapped around automatically by the text widget. Default is 0. -spacingS => amount Sets the amount of additional space a "\n". Default

left after

a line of text has been

it

has

ended by

is 0.

-state => 'normal'

'disabled'

|

Indicates the state of the text widget. Default

abled', no

on

is 0.

is

'normal'.

If set

to

can be inserted by either the user or the application

text

'dis-

(via the

insert method). -tabs =>

list

Specifies a

no

list

of tab stops to use in the text widget. Default

is

undefined (or

tab stops).

-takefocus => Determines

if

|

1

|

undef

widget can obtain keyboard focus.

-width => amount Sets the

width of the

-wrap => "none" Sets the

|

text

widget

"char"

mode used

in characters. Default

is

80.

"word"

|

to determine automatic line wrapping. Default

is

"char".

-xscrollcornmand => callback Determines the callback used

when

the text widget

is

scrolled horizontally.

when

the text widget

is

scrolling vertically.

-yscrollcoitimand => callback Determines the callback used

Fonts You can use the text

is

Text that

the

-font option

to

change the

font, including

is

inserted without a text tag (a tag allows

you specify

that applies only to certain portions of the text) will

use

was covered

first

The use of option.

how

large or small

(see Figure 8-1). This defines the default font for the entire text widget.

fonts

in

Chapter

3,

the

special formatting

this font.

time

we saw

the

-font

158

Chapter

8:

The Text Widget

J

Text

This is a different font! !

are using fontname "rl6'

Figure 8-1. Text widget using -font => "rl6"

Widget Size When you a

first

create a text widget,

it

will usually

width of 80 characters. Depending on

have

how you

a height of 24 lines

and

put the text widget in the

window (whether you

use pack with the -expand and -fill options or grid —sticky => "nsew"), it can change size when the window changes size. To force a certain size, you can use the -width and -height options: with

Text widget 20 characters wide and 10 lines tall $raw->Text -width => 20, -height => 10)->pack;

#

(

The values associated with -width are in characters, and the values associated with -height are lines of text. It is possible that the text widget will not be that exact width and height if you force the window to be larger via the minsize routine (i.e., $itTw->itiinsize(400,400)), especially if you used -expand => 1 and -fill => 'both' with the pack command. So if you don't see what you expect on the screen the first time out, keep this in mind.

Widget Style As with other widgets, you can change

how

drawn using -relief and -borderwidth Figure 8-2 might not look

much

the edges of the text widget are options.

like text widgets,

but

The examples shown

trust

me

—they

in

are!

Line Spacing When

text is displayed in a text widget, it can wrap around automatically if becomes longer than the text widget can display. The amount of room between lines is defined by using the - spacing A^ options. Figure 8-3 shows different areas that -spacingl, -spacing2, and -spacingS affect. line

the left

the

how much room is above a new line of text (the The -spacing2 option affects the space between lines when text that is wrapped automatically is too long to fit on one line. The -spacingS option determines how much room is left after a paragraph is finished

The -spacingl option first

affects

line in a paragraph).

(right after

an

explicit newline).

159

Text Widget Options

^

Text

Jl

-relief => flat

-relief => groove 1

-relief => raised

-relief => ridge

-relief => sxmken

Figure 8-2. Text widgets showing different -relief values (also shows use of -width options to force smaller size)

and

-height

-spacingi

This

is

a line of text.

It

can wrap around to the

-spacingi!

next line and even another

line.

The spacing

•spacing2

how much space

determines

]

is left

between

spacing2 lines.

-spacingS \

-spacingi

and between paragraphs

Figure 8-3. Example of -spacingN options

Tab Stops The

default setup for text widget tab stops

equals eight spaces (but default setting

it

by using the -tabs option

-tabs => [qw/2 center/] -tabs => [2, "center"]

is

ever/ eight characters. Each tab

doesn't actually use spaces).

#

#

You can

replace this

as follows:

Place tabs every 2 pixels The same tiling, different syntax

The argument that goes with -tabs is an anonymous list that specifies positions in which to place each of the tab stops. You can also specify an optional justification value for

each tab stop (as

in the

preceding example)

after

each tab stop's

;

:

160

Chapter

numerical value. This

some examples

sounds much more confusing than

all

The Text Widget

really

Here are

is.

to help clarify things:

-tabs => [qw/li center/] -tabs => [qw/li 1.5i/]

The

it

8:

default justification

#

every inch, text centered on tab-stop at 1 inch, 1.5 inch and every .5 inch after

# ts

"left". The possible

is

justification values are

"left",

in centimeters, inches, or pixels),

they are

"right", "center", or "numeric".

"When you specify the values (whether not cumulative. The

edge of the

the

left

left

edge.

If

the specified

tance between the

Of

course, setting

editing, so in

You can

last

list

two tab stops

up new

most

"1.5i"] translates to one tab stop at 1 inch from and the next tab stop will be 1.5 inches from the isn't long enough to span the entire window, the dis-

["li",

list

text widget,

tab stops

specified will be repeated across the screen. is

pretty useless unless you're doing major text

cases, you'll leave this option alone.

reset the tab stops

back

to the default

by

setting

-tabs

to

undef

$text->config\ire (-tabs => undef);

A

Short Break for a Simple Example

Before

we

get into

with a text widget, This

is

a short

then save

some of let's

look

program

the at

more complex (and more fun)

complete use of the

that will display a

file,

let

things

you can do

text widget.

you make changes

to

it:

use Tk; $itiw = MainWindow->new; # Create necessary widgets $f = $inw->Frame->pack(-side => 'top', -fill => 'x'); $f->Label (-text => "Filename: ") ->pack (-side ==> 'left', -anchor => 'w'); $f->Entry(-textvariable => \$filename) ->pack(-side => 'left', -expand => 1) -anchor => 'w' -fill => 'x' $f->Button(-text => "Exit", -command => sub { exit; } -> pack (-side => 'right'); $f->Button(-text => "Save", -command => \&save_f ile) -> pack (-side => 'right', -anchor => 'e'); $f->Button(-text => "Load", -command => \&load_f ile) -> pack (-side => 'right', -anchor => 'e'); $mw->Label (-textvariable => \$info, -relief => 'ridge' )-> pack(-side => 'bottom', -fill => 'x'); $t = $mw->Scrolled( "Text" ->pack( -side => 'bottom', -fill => 'both', -expand => 1); ,

,

)

)

MainLoop; # load_file checks to see what the filename is and loads it if possible sub load_file {

it,

and

161

Text Indexes

$info = "Loading file $filename' " $t->delete("1.0", "end"); if (!open(FH, "$filenaine" { "ERROR: Could not open $filenaine\n" $t->insert "end" return; .

'

.

)

.

)

(

,

)

>

while () { $t->insert "end" $_) close (FH) $info = "File '$filenaine' loaded"; (

,

}

;

}

# save_file saves the file using the filename in the entry box. sub save_file { $info = "Saving '$filename' " open (FH, ">$filenaine" print FH $t->get "1.0" "end"); $info = "Saved. "; )

;

(

,

}

Figure 8-4' shows the

Filename:

window when

a

document has been loaded and saved.

Itexffile

This is a file that just contains text. You can add text

,

or delete text

You can create a file just by typing text here, then entering a new filename, and clicking save.

J^ Saved.

Figure 8-4. Simple file editor with a "text/He" loaded

Text Indexes When we listbox.

talked about listbox index values, each index referred to a line in the

The

first

line in the listbox

was

at

the index can point to a specific line, but that line.

An

index for a text widget

is

index it

*

should be put

in

and so on. With a

text widget,

can also point to a character within

built

optionally modifying that index with a modifier. fier

0,

by using a base index and then The entire index, base, and modi-

double quotes.

For those of you paying attention, you'll notice this screenshot looks slightly different. That's because was taken off of Windows 95 instead of X Windows. Note the "Tk" in the upper left-hand corner, and

this

the

Windows

controls in the upper-right.

162

Chapter

8:

The Text Widget

Base Index Values "n.m" This format allows you to explicitly specify a line

number within widget), "

that line. Lines start at 1

and characters

(which

number and

a character

different than the listbox

is

start at 0.

&x,y"

The

character in the widget that

is

closest to the x,y coordinate.

"end"

The very end of the "

text widget, after

any "\n" characters as

well.

mark" Specifies the character after the location

named mark. The two mark names

provided by Tk are "current" and "insert". What they refer to cussed

is

dis-

later in this chapter.

"tog. first"

A

tag

name

is

simply a placeholder for some special formatting instructions

(discussed in the very next section). After creating tags, you can use this index form. tag. fir St is,

is

the

first

character in the text widget that

you could create a "heading"

tag

is

of type tag. That

and use "heading, first" index.

"tag.last" Specifies the character directly after the text

$widget If you have an embedded widget, you can widget by the variable referring to it.

marked with

refer to

its

tag.

location within the text

$ image

You can have embedded images using the variable referring to

as of TkS.O.

You can

refer to

its

location

by

it.

Index Modifiers The index modifiers can be used following [

+

a base index value.

chars lines — You can use the + and to add/subtract lines and characters to a base index. The index "end — 1 chars" refers to text on the line before the "end". Be careful when you use this, though, because any "\n" lines also count as a -

]

count

[

]

|

I

complete

line.

lines tart JVIodifies

the index to refer to the

insert ("end linestart", the

last

line in the text widget,

index given.

first

$string)

insert

character

on

that

line;

i.e.,

$t->

will insert the string at the front of will place the

new

text before the

163

Text Indexes

lineend Refers to the last character in the line (usually the newline).

you don't know the exact number of characters text at the end of it.

in a line

It

is

useful

when

but want to insert

words tart Adjusts the index to refer to the

first

word

character at the start of the

that

contains the base index.

wordend Adjusts the index to refer to the character after the

end of the word

that con-

base index.

tains the

Text Index

Examples

"end"

The

position right after the last line of text in the widget,

text

is

no matter how much

in the widget.

"1.0"

The and "2.0

character

first

on the

line in the text widget.

first

The

1 represents the line,

represents the character.

-

1

The

chars"

on the end of the first line. We reference it by using the first on the second line (2 0) and subtracting one character value from If we used the insert method with this item, we would insert the text before the "\n" at the end of the first line.

last

character

character that.

right

.

"Lend" Also the ting to

last

character

on the end of the

first line.

This

is

a simpler

way

of get-

it.

"2.0 lineend"

The end of 2

The little

is

the second line.

It is

necessary to specify 2.0, not

just 2,

because

an invalid base index.

basic indexes are easy.

When you

more complicated. You

just

position in the text widget that

start

doing index arithmetic,

have to remember

may change

if

that

you

it

becomes

a

are referring to a

other text has been inserted or

deleted (either by the user or the application).

Although some of the combinations start"), keep

in

mind

that

you

will

may seem most

silly (for

likely

be

example, "1.0

calling

methods

line-

that return

indeterminate information about an event. For example, a user clicks in the text

widget and presses a button that

index arithmetic allows you to reference that entire line sure

which

line

it

is

on.

The without even knowing for

will increase the font size of that entire line.

.

164

Chapter

8:

The Text Widget

Text Tags Text tags give you another

way

to address portions of text in the text widget.

has three purposes, and the same tag can serve •

Assigning formatting information to a portion(s) of text



Associating a binding with text in the widget



Managing selected

how

and spacing are among

change

tag

text

Tags are also used to change ing,

A

three or only one:

all

text properties

the text appears

few of the

a

on the

screen: font, size, color-

text properties affected

by creating your own

tags (with their

own

by

tags.

You

names), and

using option/value pairs to assign formatting information. In addition to changing

you can use a tag to apply a specific binding (such as perform a on that text). A special tag "sel" manages the selected Anytime the user selects some text, the location of that text is marked with

the formatting,

when

task text.

the tag

Any it.

sel "

of the text within the text widget can have one or

you apply two

If

last

"

the user clicks

tags to the

same piece of

text

more

tags associated with

and they both

alter the font, the

tag applied wins.

Options Used With Tags The options you can use

to configure

figuration options of the text widget

be used through tagged

-background =>

tagged text are mostly a subset of the con-

itself.

There are some options that can only

text.

color

Sets the color of the area

behind the

text.

-bgstipple => pattern Sets the pattern

used to draw the area behind the

text.

Can

create a

shaded

look.

-borderwidth => amount Sets the

width of the

relief

drawn around the edges of

-fgs tipple => pattern Sets the pattern

used to draw the

-font => fontname Sets the font

used

-foreground =>

for the text.

color

Sets the color of the text.

text.

the text, line by line.

165

Text Tags

-justify => 'left'

'right'

|

|

'center'

Sets the position of the text within the text widget.

-linarginl=> amount

amount of indentation from the

Sets the

left

edge

for the

first

line of a paragraph.

-Iinargin2=> amount

amount of indentation from the left edge for the second and of a paragraph. Sometimes called a hanging indent.

greater

Sets the lines

-offset => amount Sets the amount the

text

to create superscripts

-overstrike => If

and

is

raised or lowered from the baseline.

1

|

have a

a true value, causes the text to

-relief => 'flat'

'groove'

|

way

Determines the

Can be used

subscripts.

|

line

drawn through

'raised'

|

'ridge'

it.

|

the edges of the text are drawn, line by

-rmargin => amount Sets the amount of space

left

between the

text

and the

'sunken' line.

right

edge of the

widget.

-spacingl => amount Sets the amount of additional space its

own

line.

Default

left

on top of

-spacing2 => amount Sets the amount of additional space left on top of a line of text after been wrapped around automatically by the text widget. Default is 0.

-spacingS => amount Sets the amount of additional space a "\n". Default

-tabs =>

on

a line of text that begins

is 0.

left after

a line of text has

it

has

been ended by

is 0.

list

Indicates the set of tab stops for this text. See "Tab Stops" earlier in this chapter for

more

detailed information.

-underline => boolean Indicates that the text should be

-wrap =>'none' Determines the

|

'char'

mode

in

|

will

underline.

'word'

which the

text

is

wrapped, 'none' means

wide are not wrapped, 'char' wrap between words.

are longer than the text widget

each character, 'word'

drawn with an

is

lines that

will

wrap

at

;

166

A

;

Chapter

8:

The Text Widget

created and use

it

to insert

Simple Tag Example

Let's

look

at

how

an example of

a simple tag

widget (the resulting screen

text into a text

$t = $inw->Text

( )

->pack

(

)

is

is

shown

some

in Figure 8-5):

;

$t->tagConfig\ire{ 'bold' -font => "-*-Courier-Medium-B-NorTnal *-i20-*-*-*-*-*-*") # Use -font => "{Courier New} 24 {bold}" for Win32 systems $t->insert 'end' "This is some normal text\n"); $t->insert 'end' "This is some bold textXn", 'bold' ,



(

,

(

,

Line

creates the Text widget

1

Line 2 creates the ure"

same

as our

as

Unix

we

text

and places

it

on the

screen.

Don't be fooled by the use of the word "config-

tag.

When you

named 'bold' and

At this point,

up

'bold'

instead of "create."

ated a tag the

)

configure a tag, you are creating

associated a different font with

widget default

font, just the

it

(it

haven't changed anything in the text widget.

a valid text string.

font" or "tagl." If tain

cre-

to

be

We

are just setting

You can use any name to indicate a We could have named the tag "bold_font" or

you have good programming style (and want that indicates what the tag does.

to

tag as long

"big_bold_

be able

to

'bold'

tag.

main-

your code), use a name

Line 3 inserts

some

text into the text widget.

some more text into the insert method allows us to specify a

Line 4 inserts

string of text to

be inserted into the

text widget, but uses the

be shown with the

The

tag as the third argument. This causes that

text

widget and assigned the tag

'bold' tag was configured to change the will

We

bold version).

to use the tag later in the code. it is

it.

happens

font,

'

bold

'

.

The

so any text with the 'bold' tag

different font.

Ta«

-1

Bmrnmamaems^

some normal text This is some boldtoxt This

is

Figure 8-5. Text widget with normal

This in

is

and

bold text

What if we want to alter text that has been typed insert method then. We use the tagAdd method:

a pretty simplified example.

by the

user?

We can't use the

$t->tagAdd( 'bold'

This applies the

'

'1.0',

,

bold

'

tag to

'end'); all

of the text within the text widget.

167

Text Tags

Using the "seV'Tag to Manipulate the Selection The "sel" is

tag

is

a special tag that

is

maintained by the text widget. Any text that

by the user will be assigned the "sel" tag. You can also force the by using some of the tag methods (which we haven't covered yet) to put

selected

selection

the "sel" tag

on some

text.

"3.0",

$t->tagAdd("sel",

For instance, to select the third

line:

"3.0 lineend");

Here's an example that shows

how

to

add another tag

to the currently selected

text:

$t->tagAdd( 'bold'

When you

if

'sel. last')

($t->tagRanges 'sel' (

use the "sel" tag as part of an index, you need to

exists (using

huge

'sel. first',

,

tagRanges) within the

text

widget

first

make

)

)

sure the tag

or you'll get a really nasty

error.

Configuring

and

Creating Tags

by using tagConfigure (unless you're using the automatically defined "sel" tag). The first argument to tagConfigure is the name of the tag. The rest of the arguments (which are optional) are

The

first

thing you'll

do with

a tag

is

create

it

option/value pairs as described in the earlier section, "Options Used with Tags."

Here are some examples: creating a tag with no options $text->tagConf igure "special " # Creating a tag that will change the color $text->tagConfigure( "blue" -foreground => "blue"); # Creating a tag that will make underlined text $text->tagConfigure( "underline" -underline => 1) # Creating a tag that changes the color and spacing $text->tagConfigure( "bigblue" -foreground => "blue", -spacing2 => 6) #

(

)

,

,

,

You can change the settings for an already second time. Any changes you make to the screen that has that

created tag by using

tagConfigure a any text on the

tag immediately affect

tag:

Add backgro\jnd color to "blue" tag $text->tagConfigure( "blue" -background => "red"); # Change the spacing for "bigblue" $text->tagConfigure( "bigblue" -spacing2 => 12); #

,

,

As with widget configure methods, you can use tagConfigure to find out the current settings for a specific tag. list

of

To

get

all

the tag options

lists:

@listof lists = $text->tagConfigure( "blue" foreach $1 (©list) { print "@$l\n"; } # print it out )

and

their values in a

,

,

;

;

168

Chapter

Each

within the

list

You can

($option, If

list

contains

also limit the information

The Text Widget

two elements: the option name and you retrieve to a single option:

$value) = $text->tagConfigure( "blue"

you only want information on the value $value = $text->tagCget "bigblue"

,

the value.

-font)

tagCget:

for a particular option, use

-spacing2)

(

Adding a Tag

8:

,

to Existing Text

We've already seen an example of using the tagAdd method. It allows you to add a tag to portions of text in the text widget. The usage of tagAdd is as follows: $text->tagAdd( tagname' '

indexl

,

[

,

index2,

indexl,

index2,

...

]

)

You can add

a tag to a single index or a range of indexes. This means you can add a tag to the text widget to multiple places at the same time. Let's say you wanted to add the tag 'heading' to the 1st, 12th, and 30th lines because they are

the location of rest of the text.

some heading information that you want The tagAdd line would look like this:

$text->tagAdd

( '

heading ',

'1.0',

to look different than the

'1.0 lineend '12.0 lineend' '

'12.0'

,

'30.0'

,

'30.0 lineend')

Now, assuming the formatting of 'heading' makes the font bigger, those lines now show up differently than the defaults from the rest of the text in the widget.

You can add more

than one tag to a section of

both a 'heading' tag and a 'color' (such as -font), the

Once you

last setting for that

place a tag on a range of

and ending indices of rounding

it.

tag. If

text.

both tags

For example, you can have try to alter the

same option

option wins.

text,

any

text inserted

between the beginning

that text will automatically get the tag of the characters sur-

This happens whether you are using insert without any specific tags

or the user just types text into the text widget.

If

you specify

a tag with

insert,

it

overrides the surrounding tag.

Using Bind with Tags One

of the main reasons for tags

is

the ability to assign a binding to certain por-

tions of the text. After creating a tag with

callback will execute

when

a

tagConf igure, you can use bind so a a mouse click)

sequence of events happens (such as

on that tagged text. On our button widgets, we have a default binding of that invoked the callback associated with the -coinmand option. We can do the same thing with tagged text.

169

Text Tags

The

example

best

using text like a

is

web

new document

something happens: a

hyperlink.

presented to the user. The basic form of a tagBind $text->tagBind( tagname

callback

sequence,

[,

When you

loaded or another

is

]

on the

click

window

is

link,

created and

call is as follows:

)

The callback is similar to that specified for the -coitmand callback on a button. The sequence is a description of the event that triggers the script. The only sequences you can specify are those that are keyboard or mouse related. (See Chapter 14, Binding Events, for more details on available events.)

The following code shows a psuedo-link example. on it is show the end of the text widget:

does

All the link

when we

click

-width => 40) ->pack(- expand => 1, -fill => 'both') $t->tagConfigure( 'goto_end' -underline => 1, -foreground => 'red'); "" sub { shift->see( 'end' $t->tagBind( 'goto_end' } $t = $niw->Scrolled( "Text"

,

,

,

,

)

Setup Bindings to change cursor when over that line "" $t->tagBind( 'goto_end' sub { shift->configure( -cursor => 'hand2') " $t->tagBind goto_end' " sub { shift->configure (-cursor => 'xterm') $t->insert end' "END\n" "goto_end"

;

)

#

,

});

(

,

'

}

)

(

'

,

,

)

Insert a bunch of lines for ($i = 1; $i insert 'end' "$i\n");

#

{

(

,

}

tagBind

Inside the subs in the

We

calls,

we

use the shift

command

to invoke a

bind callback is the text widget. This is done implicitly for you. Whichever widget tagBind is invoked on is the widget that will be sent as the first argument to the callback. To use the text widget more than once in the callback, assign it to a local variable; for exammethod.

ple, If

itry

we

can do

this

because the

to the

$widget = shift.

created our text widget in the global scope of the program and placed a

erence to the widget

is

scope and available during the callback.

you want

to use the

same callback

$tl->tagBind( 'goto_end' $t2->tagBind( 'goto_end' s\ib goto_end { ray $text = shift; $text->see end' (

'

we

in the variable $t,

the callback via the $t variable. This

}

argument sent

first

)

;

,

,

with,

ref-

could also access the text widget

only possible because $t

is

in

in the global

you have two different text widgets that use shift to get the correct text widget:

If

"" ""

,

,

\&goto_end \&goto_end

); );

(

;

(

)

170

Chapter

Using the same callback for both text widgets helps save space

To determine what the bindings tag name argument:

are for a tagname, just use

8:

The Text Widget

your program.

in

tagBind with only

the

©bindings = $text->tagBind( "tagname")

The

be empty

will

list

if

there are

no bindings

currently for that tag.

Deleting All Instances of a Tag Once

a tag

you can use the tagDelete method

created,

is

$text->tagDelete tagname

The

[

,

tags are deleted completely

reverts

back

tagname

...

when you

]

use tagDelete. This means the text

and any bindings or other

to the default configuration values,

mation associated with those tags

To remove

infor-

also deleted.

is

The tagDelete method can be used if you are cally within the program and you need to delete tion is no longer valid.

Removing a Tag from

to delete the tag:

creating temporary tags dynami-

the tags later

when

the informa-

the Text

the tag from a specific block of text,

you can use the tagRemove

method: $text->tagRemove tagname, indexl {

Specify the

name

remove the

tag.

[,

index2,

indexl,

index2 ...])

of the tag and an index or range of indexes from which to

This leaves the tag

intact;

it

merely removes

it

from the specific

text indicated with the indices.

Raising When

and Lowering Tags same

there are several tags applied to the

overrides the previous ones, and

its

text,

the

last

tag

added

to the text

configuration options are given priority.

You

can change the priority of the tags by using tagLower and tagRaise: $text->tagLower{ tagname $ text -> tagRaise tagname

These methods take argument, the

first

text in the text

specified, the

Think of

it

a tag

tag

is

[, [

,

belowtag ]) ahovetag ]

name

as the

)

first

argument.

given the highest or lowest

If

there

priority.

widget no matter where the tags are applied.

first

tag

is

specifically placed before or after the

as reordering a stack of tags

the top has the most say, and

if it

tag

If

a

second

second tag

is

tag.

applied to the same text). The tag on -foreground option of 'red', then all

(all

has a

no second

is

This affects the entire

171

Inserting Text

the text with that tag will be red, regardless of

ground

to. If

we

use tagRaise to

move

what the other text tags set -fore-foreground of 'blue' to

a tag with

the top, the tagged text will change to blue.

Getting Tag You can whole

Names

find out

widget by using the tagNames method:

text

$text->tagNaines If

the different tags that apply to a specific index or to the

all

(

index

[

])

you specify an index, the

index.

If

returned contains tags that only apply to that

list

a specific index isn't given, then the

list

returned contain

all

the tags that

apply to the entire text widget whether or not that tag has been applied to text within the widget.

Determining Where a Tag Applies If

you know the name of the

tag,

you can

widget by using the range methods. The that contains pairs of

find out

first

where

it

applies in the text

method, tagRanges, returns a

list

index values for the whole text widget:

©list = $text->tagRanges "tagname" # returns beginl endl begin2 end2 (

,

(

If

no

text in the text

You can

,

...

,

widget has that

tag, the

one

get the pairs of index values

)

returned at a

list

will

be empty.

time by using the tagNextrange

method: ($start,

The search index2

is

$end)

for

=

$text->tagNextrange( "tagname"

"tagname"

will

begin

,

indexl

[

,

index2

])

indexl and go no farther than index2.

at

If

not specified, then the search will continue until the end of the text wid-

get or until

it

finds the tagname,

whichever comes

first.

Inserting Text Now

that

we've gone over

and marks,

text indexes

we

can

talk in

more

detail

about the methods for manipulating the widget's contents.

As we've seen from the many examples into the text widget. will

be

(which

inserted. is

first

argument

The second argument

optional)

inserted text.

The is

a single tag

The usage

in this chapter, is is

name

we

use insert to put text

an index and indicates where the

The next argument names to assign to the

the string to insert.

or a

list

of tag

is:

$text->insert (index, string,

[

taglist, string,

text

taglist ...]

)

;

;

172

So

Chapter

far

we've only seen single tags used with insert.

than one

tag,

put the tag

names

If

8:

you want

into square brackets, creating a

The Text Widget

to specify

more

list:

$t->insert 'end' "This is a very tagged line", tagl tag2 tag3 (

,

[

To use tag

'

'

,

'

,

'

'

]

'

)

you can supply additional

different sets of tags,

text lines

and additional

lists:

$t->insert 'end' (

When you ferent tags,

,

"This is the heading", ['heading', "Second line", ['bold', 'blue']);

use the insert

make

command

still

be assigned to

more than one

there will be

You can

that text.

set of text

with

dif-

in pairs: text, tags, text, tags, etc. If the

tagConf igure),

tag used isn't defined (with

the tag will

to insert

come

sure they always

'underline'],

no

on the text but later if you wish.

effect

create the tag

Deleting Text To remove

text

from the

$text->delete (indexl

The

first

index argument

then the

first

you can use the delete method:

text widget, [

index2

,

]

)

required; the second

is

index must be

less

is

optional.

If

both are specified,

than or equal to the second. All the characters

from indexl to (but not including) index2 are removed from the

you want

to

delete

delete("i.O",

text widget. If

everything from the text widget, you can use

$text->

'end').

Retrieving Text The get function index2.

If

is

index2

The usage of get

one

isn't is

you'll

use a

lot. It

returns the text located from indexl to

specified, just the character located at indexl

$t = $ text ->get (indexl

,

[

index2

]

)

string will

returned.

;

As with any index ranges, indexl must be

empty

is

as follows:

less

than or equal to index2 or an

be returned.

Translating Index Values When you work

with indexes,

it

useful to

is

be able

to convert a complicated

index form into a simpler one. The index method returns an index with the form line.

char.

$newvalue = $text->index indexl (

The indexl value can be any

)

;

valid index expression.

Getting Line Information

1

73

Comparing Index Values You can compare two index $text->coiTpare (indexl,

You

pass the

first

values by using the coitpare method. index2)

op,

;

index, the test operation to perform, and the second index.

values for op are: "search( -backwards,

$location

"

$text->search (-nocase,

"find me",

'end');

"SWITCHES",

"1.0");

Marks

1

75

Scrolling The

widget can be scrolled both horizontally and

text

so

vertically,

it

implements

both xview and yview methods. These two methods are described in Chapter

6,

Scrollbars.

Marks There are several ways to refer to different positions throughout the

text widget.

Index values refer to a character. Tags are named references to a specific charac-

The term mark is used to refer to the spaces in between characmark has a name. For example, the "insert" mark refers to the position of the insert cursor. However, tags refer to the actual characters, and if those characters are deleted, the tag is no longer associated with those characters. The mark stays in place whether the characters surrounding it are deleted or other characters are added. Marks can only refer to one location within the text widget ter

or characters.

Similar to tags, a

ters.

at a time.

Once affect

it

is

created,

on which

you can use

a

mark

default), the text will

be inserted

to the left of the

to the character to the right of the mark.

inserted to the

an index. The gravity of the mark

as

side the text will be inserted.

left

of the

If

mark and the mark

If

the gravity

mark because is left

the gravity

mark

the

'

'

,

will

'right' (the

is

is

glued

the text will be

will refer to the left of the last charac-

ter inserted.

There are two special marks

that

are

set

automatically by the

"insert" and "current". The "insert" mark

is

wherever the

The "current" mark is the position closest to the mouse and mouse moves (as long as a mouse button is pressed). Both marks internally and cannot be deleted.

You

text

widget:

insert cursor

is.

adjusts as the

are maintained

mark called "anchor" that shows up in the getNames method you click in the text widget. It always has the same index value as the "insert" mark, but "anchor" might not always exist. will also see a

after

Setting To

and

Getting the Gravity

set the gravity of the

mark, you can use inarkGravity:

$text->markGravitY (iTiarAuame

The possible values

new marks mark

is

is

,

If

direction

])

"right" and "left". The default gravity for you don't specify a gravity, the current gravity for that

for direction are

"right".

returned.

[

;

)

176

Chapter

8:

The Text Widget

Determining Mark Names To

get a

of

list

the marks in the text widget,

all

©names = $text->markNames

you can use markNames:

(

There are no arguments to the itiarkNaines function, and

example of

how

marks within the

to report the

it

returns a

list.

Here

is

an

text widget:

$f->Button(-text => "Report", -coimnand => sub { my @m = $t->markNames foreach (@m) { print "MARK: $_ at ", $t->index($_) }} ->pack(-side => 'left'); ( )

;

,

"\n";

)

The

results after clicking in the

MARK MARK MARK

to set the insertion cursor are as follows:

insert at 2.15 anchor at 2.15 current at 3 .

Creating You can

window

and Deleting Marks

create a

mark and

set

$text->markSet (markname

a specific index

at

placed. For instance,

$ text - >markSet

(

by using the markSet method.

index)

markname you want

In addition to the

mark should be end of line 3:

,

it

you always want

"3.0 lineend"

"end of line3",

$text->insert "end of line3",

if

to create, specify the to

index where the

be able

to insert at the

)

"text to insert");

(

The markUnset method removes the mark from the text widget and deletes the mark completely. It will no longer show up in the markNames list after it has been unset, and it can't be used as an index value either. You can specify more than one markname in markUnset: $text->markUnset (markname

[,

markname, markname

...

])

Embedding Widgets One

of the best things

you can do with

button or entry widgets) inside

can create Before

a scrolled set of

we go

embedded

over

widgets,

all

let's

it.

a text widget

One advantage

widgets on a line-by-line

is

of

put other widgets (such as

embedding widgets

the different functions that are available to

look

at a

data entry in a program, which

quick example.

means we need

is

you

basis.

We

often

want

a lot of label

to

work with do a lot of

and entry widgets.

Embedding Widgets

177

Sometimes there are so many of them

that

hard to

it's

them

fit

all

on the screen

without making a mess of the window. By using a scrolled text widget and putting the label

and entry widgets

inside

it,

we

can create a

lot

more widgets within

a smaller space. Here's the code:

use Tk; MainWindow->new; $mw->title "Data Entry" $f = $iTiw->Fraine->pack; -side => 'bottom'); $f->Button(-text => "Exit", -command => sub { exit; } ->pack(-side => 'left'); $f->Button(-text => "Save", -command => sub { # do something with %info; ->pack(-side => 'bottom'); } $t = $mw->Scrolled("Text", -width => 40, -wrap => 'none' ->pack(- expand => 1, -fill => 'both'); $inw =

(

)

(

)

)

)

foreach (qw/Name Address City State Zip Phone Occupation Coirpany Business_Address Business_Phone/) { $w = $t->Label (-text => "$_:", -relief => 'groove', -width => 20); $t->windowCreate( 'end' -window => $w) $w = $t->Entry( -width => 20, -textvariable => \$info{$_}); $t->windowCreate( 'end' -window -> $w) $t->insert 'end' "\n"); ,

,

(

,

}

$t->configure( -state => 'disabled');

disallows user typing

#

MainLoop Figure 8-6 shows the

Win32 version of

window.

this

^^-Inixl

i *Data Entry

"'""

"^"-"

*

Name: Address: City:

State: Zip:

Phone: -

Occupation:

Company: Business_Address:

.__..™._™JExit

j

Save

Figure 8-6, Text widget containing other widgets

1

.

178

We

Chapter

disable the text widget before running

8:

Mainloop because we

The Text Widget

want the

don't

user to be able to type text directly into the text widget. This only disables the ability to enter or delete text

—the

internal widgets

still

function normally.

We

also

turned off the -wrap option so the label and entry widgets don't accidentally drop

down

You could want

when

to the next line

window

the

is

resized.

put a text widget inside another text widget, but you probably wouldn't

to.

The window Method to insert an it

embedded

we

use the windowCreate method The widget should have already been created, and widget. The general syntax is:

As you can see from the preceding example, widget.

should be a child of the text

$widget = $text->Widget $text->windowCreate (index, -window => $widget, [option => value (

In our

;

the

embedded

insert the

-window option with

)

we used

example above,

widget index to

...

'end' index. widgets.

the reference to the

Here are the available options

for the

]

)

;

You can use any

valid text

The only option we used was

a

new $widget.

window method:

-align => where 'baseline',

Possible values of

mines where the widget

The

itself.

default

is

'

is

'bottom',

'center', or

placed within the line

center

if it is

'top'.

not as

tall

deter-

It

as the line

'

-padx => amount and -pady => amount

Add space around

the widget in the x and y directions respectively (-padx =>

10).

-stretch =>

|

1

Takes a boolean value line

(1

or

0).

A

true value will stretch the widgets to

fill

the

from top to bottom.

-window => $widget Takes a reference to another widget. There are several different forms of the window method. The ate" form, creates the

know what

widget within the

types of widgets are

@types = $text->windov*Iames

The

results .

look like

text widget.

embedded ( )

one, the "Cre-

The "Names" form

lets

in the text widget:

;

this:

text radiobutton .text. label .text. button .text. entry .

first

.

text checkbutton .

you

Internal Debug Flag

1

Use the windowCget function

when

the

window was

$value

=

$text->windowCget (index, option);

you need

to

know

occupying (each widget occupies one character it

more

takes

were used

to get information about the options that

created in the text widget:

In order to use windovtfCget

like

79

the index the widget

in the text widget,

is

even

currently if it

looks

space).

The "Configure" form of window will allow you change the options associated with the widget at index or retrieve the value of the configuration option:

$text->windowConf igure index (

Remember

[,

option => value

J

)

method are -align, -padx, windowConf igure (...) behaves just like a regular widget's configure method. To make changes on the $widget directly, use $widget->conf igure (...). -pady,

that the only options

-stretch,

and

you can use with

-window.

Other than

this

this,

Internal Debug Flag The debug function takes an optional boolean argument: $text->debug( If

[

boolean

the value passed in

is

]

true,

)

then internal consistency checks will be turned on in

the B-tree code associated with text widgets.

Without any argument, the debug method turned on, and "off"

debug

not. All text

if

If false,

the checks will be

will return the

value "on"

if it

left off.

has been

widgets in the application share the same

flag.

Scanning The scanMark and scanDragto methods are used internally within the text widget. A call to scanMark simply records the x, y passed in for use later with scanDragto. It returns an empty string: $text->scanMark(x, y)

scanDragto

also takes x,

;

y coordinates, which are compared to the scanMark x,y the text widget is adjusted by 10 times the differ-

The view within ence between the coordinates. coordinates.

$text->scanDragto(x, y)

Chapter

180

Fun Things

8:

The Text Widget

to Try

Create a scrollable text widget. Insert a button widget that has text describing the foreground color of the text widget cycle

between several

color

and

text.

and when you

click the button,

different colors, updating the button's

have

it

-foreground

For a practical application, have several buttons, each associ-

ated with a different color in your application.

When

the user clicks the

button, you can change the color to a different value (possibly using the ColorEdit composite widget).

Create a text widget that will display a read-only the

window, one

increase

it.,

file.

Create two buttons

on

to decrease the font within the text widget, the other to

The Canvas Widget

cwy«.iw^«,ftoa««»

..

.j.qj

The canvas widget

is

mainly used for drawing items such as

arcs, lines, rectangles, circles,

Red Dual

text

a

and other widgets

painter's

canvas:

something on

|l«e Oiial

blank

is

canvas

some examples

of

is

you decide

Create a drawing program.



Display a graph based on input from the user.



Create a customized

any

scrollable in

how you



Each item you create

until

draw

to

But unlike a painter's canvas, which

it.

ited in size, this

are

It

and so on. You can also place Think of it as

inside a canvas widget.

lim-

is

direction.

Here

can use a canvas widget:

slider.

canvas widget can have bindings attached to

in a

it

to allow

for easy interaction with the user.

Creating a Canvas I

recommend

you know window:

that

you always use the Scrolled method

for sure that

your canvas

$canvas = $iTiw->Canvas # or.

(

[

first

going to be a fixed size that

is

option => values,

]

)

->pack

will

fit

in the

( )

.

$canvas = $inw->Scrolled( 'Canvas'

The

to create a canvas unless

line creates just a

(See Chapter

6, Scrollbars,

Scrolled method.) To

,

[

option => values.

;

)

->pack

( )

canvas and the second creates a canvas with scrollbars. for

more information on what

else

you can do with the

create a canvas widget, use the desired parent widget to

181

182

Chapter 9: The Canvas Widget

invoke the Canvas method and pass any

initial

Canvas method

newly created canvas widget.

Before are a

we

returns a reference to the

get into the options

and methods

options in with their values.

The

available with a canvas widget, here

few miscellaneous things you should know about using

a canvas widget.

Coordinate System A

canvas widget uses a coordinate system to locate items inside of

dinate system

Figure 9-1

isn't

shows

a normal one.

It's

more

like

it,

but the coor-

an upside-down coordinate system.

a diagram that demonstrates the coordinate system a canvas wid-

get uses.


bbox( "all"

)

]

like:

;

;

;

184

;

Chapter 9: The Canvas Widget

Calling this after you add or remove items to the canvas resets the scroll region to where it needs to be. Of course, if you are adding many different items all at once, you should wait until after you have added them all and then update the scroll region.

Using Bind with a Canvas When you

try to

bind method with

use the

a canvas widget, you'll run into

unexpected problems. You'll either get an error and your script will

around

bind won't seem

run but your

need

you'll

this,

(because the canvas has

its

You can If

also use

own bind method

In order to get

effect.

that

you have

just

bind

to avoid using):

;

,

sub

{

print "bind!\n";

}

)

SUPER: :bind instead of Tk: :bind. Either way

you used the Scrolled method

difficulty; you'll

have any

some

won't run, or your

use the explicit Tk: :bind instead of

to

$canvas - $rnw->Canvas $canvas->Tk: :bind("" ( )

to

script

your canvas,

to create

will work.*

you'll

have an added

have to use the Siibwidget method to get to the canvas widget:

$canvas = $inw->Scrolled( "Canvas" $real_canvas = $canvas->Subwidget( "canvas" $real_canvas->Tk: :bind( "" sub { print "bind! \n" }); )

;

)

,

Other than

one small annoyance, bind works just as you would expect it fairly useful) example that will print out the coordi-

this

would. Here's a quick (and nate you clicked on:

$c = $inw->Scrolled( "Canvas") ->pack() $canvas = $c->Subwidget "canvas "

;

(

)

$canvas->Tk: :bind("" s\ib

print_xy

ray

($canv,

print

"

,

[

\&print_xy, Ev(

'x'

,

Ev( 'y'

]

)

$canv->canvasy($y)

,

)

)

{

$x,

(x,y)

$y)

=

",

= @_;

$canv->canvasx($x)

,

",

",

"\n";

}

This example prints out the coordinates (in canvas coordinates) the

left

mouse

when you

click

button.

Canvas Options The options within act as

*

it.

listed in this section affect the entire

Items

are circles, lines, rectangles, text,

you would expect them

For these

u.sing Tk8.0:

to (as explained in

You can use canvasBind

the rest of the chapter, but note that

you should

canvas widget and the items

or other widgets. These options

Chapter

instead of Tk: :bind.

u.se

canvasBind

3,

I'll

instead.

The Basic Button, for

refer to Tk::bind

throughout

Canvas Options

185

most options and

in

Chapter 6 for the scrollbar options): -background, -border-

width, -cursor, -height, -highlightbackground, -highlightcolor, -high-

lightthickness,

-takefocus,

-relief,

and

-xscrollcoinmand,

-width,

-yscrollcoinmand.

New When

Options selecting items in the canvas with the

mouse

mouse

cursor, the canvas widget

does

The mouse must be to the item before it "1.0", is considered inside the item. The default value for -closeenough is which is 1.0 pixels away. Any floating point number is a valid value (and will calculations to determine

-closeenough option

if

the

how

controls

cursor

inside or outside the item.

is

close the

always be in pixels) for -closeenough. I

discussed the

this chapter.

It

-scrollregion option takes a

The coordinates The coordinates

list

indicate a

that

bounding region

are in this order:

think of the coordinates as

if

[

"The Scrollable Region"

briefly in

and

reference,

earlier in

must contain four coordinates.

list

for the scrollable area in the canvas.

minx, miny, maxx, maxy

they were defining the

[

left,

]

.

You can

top, right,

also

bottom

]

edges of the scrollable region. Normally, the canvas widget limits the user to seeing only the area defined by the

-scrollregion

option.

using -confine =>

You can allow

The

0.

default for

the user to scroll

-confine

beyond

this area

by

is 1.

Additional Scrolling Options The -xscrollcoinmand and -yscrollcoinmand options both work as described in Chapter 6, but there are two additional options that affect how the canvas scrolls its contents: -xscrollincrement and -yscrollincrement. Each option takes a valid screen distance for a value. This distance scroll in the associated direction.

ment

=>

10,

each time you

For instance,

click

the unit the canvas will use to

is if

you specify -xscrollincre-

an arrow on the horizontal

contents of the canvas will shift so that the

left

scrollbar,

edge of the contents

multiple of 10. Essentially, the canvas will shift the contents

is

the

an even

10 pixels in the

arrow's direction. If

the value associated with

less, scrolling is

done

in

-xscrollincrement

normal increments.

or

-yscrollincrement

is

or

.

186

Chapter 9: The Canvas Widget

Options for Text Items The following options

are applied to the entire canvas widget, but they really only

canvas widget: -insertbackground, -insertbor-

affect the text items inside the

derwidth, -insertofftime, -insertontime, -insertwidth, -select±>ack:gro\ind, -selectborderwidth, and -selectforeground. These options work the

same

as they

and Entry

would for an entry widget or a text widget. See Chapter and Chapter 8, The Text Widget, for more details.

5,

Label

Widgets,

Canvas Widget Option These options

all

are used with the

-background => Sets the

List Canvas method:

color

background of the canvas

to color.

-bordeirwidth => amount

Changes the width of the edges of the canvas

-closeenough => float_amount Sets the amount of distance from

the item

to

amount

when

the cursor

is

considered

inside the item.

-confine => 1

|

Indicates that the canvas will limit

region

if

set to

1

.

Default

itself

to the area defined

by -scroll-

is 1

-cursor => cursomame Indicates that the cursor will change to

cursomame when

it

is

over the canvas.

-height => amount Sets the height of the canvas to

-highlightbackground =>

amount.

color

Sets the color the highlight rectangle should

be

when

the canvas does not

have the keyboard focus.

-highlightcolor =>

color

Sets the color the highlight rectangle should be

when

the keyboard focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle. Default

-insertbackground =>

is 2.

color

Sets the color of the area

behind the

-insertborderwidth => amount Sets the width of the borders on

text insert cursor.

the insert cursor.

the canvas does have

187

Canvas Options

-insertofftime => milliseconds Sets the amount of time the cursor disappears from blinking

when

the screen

is

it

off.

-insertontime => Sets the amount

milliseconds of time the cursor appears

on the screen when

it

is

blinking

on.

-insertwidth => amount Sets the

width of the

-relief => 'flat' Indicates the

way

-scrollregion =>

|

insert cursor.

'groove'

'raised'

|

|

the edges of the canvas are

Defines the area the user

is

bottom,

right,

top,

left,

[

allowed to

'sunken' 'solid' drawn. Default is flat

'ridge'

|

|

'

'

]

scroll.

-select-background => color Sets the color of the area

behind any selected

text.

-selectborderwidth => amount Sets the

width of the border of the selected area.

-selectforeground =>

color

Sets the color of the selected text.

-takefocus =>

|

1

|

xondef

Determines whether or not the canvas can get keyboard focus. Default

is

for

the application to decide.

-width => amount Sets the

width of the canvas to

amount

-xscrollcommand => callback

when the canvas is scrolled horizontally (autowhen the Scrolled method is used).

Determines the callback used

matically set to the correct callback

-xscroll increment => amount Sets the distance the canvas contents

scrollbar

is

move when

the arrow

on the horizontal

clicked.

-yscrollcoinmand => callback Determines the callback used

when

the canvas

is

scrolled vertically.

-yscroll increment => amount Sets the distance the canvas contents

scrollbar

is

clicked.

move when

the arrow

on the

vertical

188

Chapter 9: The Canvas Widget

Creating Items in a Canvas The whole point of having

a canvas

is

to put items in

it.

You can

create arcs, bit-

and widgets. Each has an associated createXXX method, where the type of item you want to create maps, images,

XXX.

replaces the

used to

lines, rectangles, ovals (circles),

polygons,

text,

create methods return a unique ID, which can be When you see a method that takes a tag or an ID as one returned from the create method.

All of the

refer to the item later.

an argument, the ID

is

the

The Arc Item When you

tional options that will

The

shortly.

you specify a bounding rectangle with two sets of x and drawn within the confines of the bounding box. Addichange how the arc is drawn in the canvas are explained

create an arc,

y coordinates. The arc basic

is

createArc statement

$id = $canvas->createArc

Any

(jcl,

is

as follows:

yl, x2, y2)

additional options used in the

;

createArc method

are specified after the

coordinates: $id = $canvas->createArc (xl, yl, x2, y2, option => value);

Each option

for the arc item

f igure canvas methods.

-extent => degrees The length of the arc The default -extent starting

point (see

can be used

The options

is

later

with the itemcget and itemcon-

are:

specified in degrees

(or length)

-start

is

by using the -extent option. The arc is drawn from the

90 degrees.

option) counterclockwise within the rectangle

defined by Cxi, yl) and (x2, y2). The degrees value should be between -360

and

360.

If

it

is

more or

less,

then the value used

is

the specified

number of

degrees modulo 360.

Here are some examples of the -extent option: This draws half of an oval $canvas->createArc(0,0,100,150, -extent => 180); # This will draw _ of an oval $canvas->createArc(0,0,100,150, -extent => 270); #

-fill => color

To

fill

the arc with the specified color.

By

default, there

is

no

fill

color for an

arc.

-outline => color drawn with a black outline. To change the default, use the The outline color is separate from the fill color, so to make completely solid object, make the color for -outline and -fill the

Normally the arc

-outline it

a

same.

is

option.

189

Creating Items in a Canvas

-outlinestipple => bitmap To use -outlinestipple, you must also use the -outline option. Normally, the outline of the arc is drawn solid. Use a bitmap with -outlinestipple to make the outline nonsolid; the specified bitmap pattern will be used to draw the outline of the arc. -start => degrees The value associated with the -start option determines where Perl/Tk starts drawing the arc. The default start position is at three o'clock (0 degrees). The degrees specified are added to this position, but in a counterclockwise direction. Use -start => 90 to make the arc start at the twelve o'clock position, use -start => 180 to

make

the arc start at the nine o'clock position,

and so

on.

-stipple => bitmap The -stipple option causes the only if the -fill option has been -style => "pieslice" The -style of the

"chord"

|

arc to

filled

with a bitmap pattern, but

"arc"

|

determines

arc

be

specified as well.

"pieslice", draws the arc and two

how

lines

the

arc

is

drawn. The default,

from the center of the oval ends of

The "chord" value draws the arc and a line connecting the two end points of the arc segment. The "arc" value draws just the arc portion with no other lines. The -fill and -stipple options are ignored if the arc segment.

"arc"

-tags =>

is

used.

taglist

When you

you use the -tags option to assign The value associated with -tags is an anonymous list of create an arc,

tag

names

to

it.

tag names; for

example: $canvas->createArc(0,

You

don't

need

to use

0, 10, 140,

-tags => ["arc",

an anonymous

list if

you

"tall"]);

are only specifying

one tag

name: $canvas->createArc

-width => amount The width of the

(0, 0, 10,

outline

is

140, -tags => "arc");

specified

by using -width. The

default

-width

is

1.

The Bitmap Item A

canvas widget can display a bitmap instead of text

You can

just as a

button or label can.

use createBitmap to insert a bitmap into your canvas widget:

$id = $canvas->createBitmap(x, y)

;

190

Chapter 9: The Canvas Widget

Of course, you must use the -bitmap option to specify which bitmap you won't see anything. So we really create a bitmap like this:

to display or

$id - $canvas->createBit:iTiap(x, y, -bitmap => bitmap);

Why the

they didn't

way

it is.

make

just

the bitmap the third argument,

The other captions

-anchor => "center"

|

"n"

"e"

|

|

I

don't

createBitimap

available for

"s"

|

"w"

"ne"

|

know.

That's just

are:

|

"nw"

|

"se"

"sw" I

The -anchor option determines how

the bitmap

is

placed on the canvas

rela-

coordinates indicated. The default for

-anchor is "center", which puts the center of the image at the x,y coordinates. Using a single cardinal direction (for example, "e") would place the center of that edge at the x,y tive to the x,y

coordinates.

-background => color The -background option specifies the color to use for all the (zero) bitmap pixels. If you don't specify a background color or use an empty string (""), the

be transparent.

pixels will

-bitmap => hitmapname You must use the -bitmap option

You can

to

tell

the canvas

which bitmap

use the built-in bitmaps such as 'info' or 'warning'

to display. just as

you

can with the button widget, or you can specify a filename. Remember, to specify a bitmap

file,

use an @ sign in front of the bitmap filename.

-foregroiond => color

The foreground color of definition,

color

all

-tags =>

background

color.

(By

bitmaps can only have two colors.) The -foreground option

will

the

1

a

bitmap

is

pixels with this color.

the opposite of the

The

default for

-foreground

is

black.

taglist

When you option. for

create a bitmap, you can assign tag names to it by using the -tags The value associated with -tags is an anonymous list of tag names;

example: $canvas->createBitmap(0, 0, -bitmap => 'info', -tags => ["info", "bitmap"]);

You

don't

need

to use the

you are only specifying one tag name:

list if

$canvas->createBitmap(0,

0,

-bitmap => 'info', -tags => "bitmap");

The Image Item If

we

can create a bitmap on a canvas,

as well.

We

it

makes sense

can do so with the createlmage method:

$id = $canvas->createlmage(x, y,

-image => image);

that

we

can create an image

191

Creating Items in a Canvas

Again, you have to specify an image to display or you won't see anything.

createlmage

other options available for

-anchor => "center"

"n"

|

"e"

|

The

are:

"s"

|

|

"w"

"ne"

|

|

"nw"

|

"se"

"sw" I

The -anchor option for an image works the same as it does for a bitmap. The -anchor option is how the image is positioned around the x,y coordinates. The default for -anchor is center '

-image => $iinage The -image option

'

which image to display. The image value is actually a reference to an image created with Photo or Bitmap methods. (See Chapter 3 for more information on how to specify an image file.) indicates

-tags => taglist Use the -tags option to assign tag names to an image. The value associated with -tags is an anonymous list of tag names; for example: -image => $ixngptr, -tags => ["image", "blue"]);

$canvas->createlitiage(0,0,

You

need

don't

to use the

list if

$canvas->createlinage(0,

you

are only specifying

one tag name:

-image => $iingptr, -tags => "image");

0,

The Line Item The createLine method can actually create one. The first two coordinate sets you supply

multiple connected lines, not just create the

first line,

and any addi-

tional coordinates will continue the line to that point:

$id = $canvas->createLine(0, $id = $ canvas - >createLine (

,

# creates one line 400,400); 400,400, -50, 240); # creates two lines

0, ,

you can specify any options and values you wish the options and values are as follows:

After the coordinates,

ure the

line(s);

-arrow => "none"

You can

"first"

place arrowheads

]

"last"

at either

|

"both"

end of the

line (or

both) by using the

you have more than one line in your createLine method, last point can be made into an arrow. If you want each have an arrowhead, then use multiple createLine statements.

-arrow

only the line to

|

to config-

option. first

If

and/or

distl dist2, distS -arrowshape => The -arrowshape option only applies if you use Figure 9-3 shows what the distance values mean. [

,

Specify the three distances

]

by using an anonymous

the

list

-arrow option

such as

$canvas->createLine(10, 10, 200, -40, -arrow => "both", -arrowshape => 20, 20, 20]); [

this:

as well.

192

Chapter 9: The Canvas Widget

dist2 1

1

distS-

/

^^ dist1

Figure 9-3- Definition of arrowhead

-capstyle => "butt"

"projecting" "roiond" Instead of arrowheads, you can make the ends of the |

|

line

have one of these

styles.

-fill => color The -fill option is misnamed because it isn't actually line is simply drawn with this color instead of black.

filling

anything.

The

"miter" -joinstyle => "bevel" "round" The -joinstyle option affects how multiple lines are joined together. The default is "miter". If there is only one line created, this option has no effect. |

|

-smooth => 1 If -smooth has a value of 1, then, using Bezier spline(s), the line(s) will be drawn as a curve. The first two lines make the first spline, the second and third line make up the second spline, and so on. To make a straight line, repeat the end points of the desired straight line (or use createLine again to make a separate line). I

-splinesteps => count When you use the -smooth option, the more -splinesteps you use, the smoother the curve. To find out how many steps create the desired effect, you'll

have

to

experiment with different values.

-stipple => bitmap To have the line drawn with a bitmap pattern (Is in the bitmap have color, Os are transparent), use the -stipple option. The bitmap can be a default bitmap name or a filename. The wider the line (see -width), the more the stipple design will show up.

Creating Items in a Canvas

-tags =>

193

taglist

When you

names to them by using The value associated with -tags is an anonymous list of

create a line (or lines), assign tag

-tags

option.

names;

for

need

don't

tag

example:

$canvas->createLine(0,

You

the

to use a

0,

list if

$canvas->createLine(0,

0,

-tags => ["line",

100,100,

you

100,

are only specifying 100,

"blue"]);

one tag name:

-tags => "line");

-width => amount You can make the line(s) thicker by using the -width option. Normally the line is drawn only 1 pixel wide. The amount can be any valid screen distance (e.g.,

centimeters, inches).

The Oval Item An

you draw it just right. To create a circle/oval, use the createOval method and specify two sets of points that indicate a rectangle (or square) in which to draw the circle/oval. Here is a simple example: oval can be a circle

if

$id = $canvas->createOval $id = $canvas->createOval

The options

for the oval will

-fill => color The oval will be the outline color.

-outline => color The outline is the outline

make

the outline

50,

# creates a circle 50); 100); # creates an oval

familiar,

so we'll

it

just

cover them

briefly:

with the specified color. This color

default, the oval

line

black, but

is

50,

(0, 0,

be

filled in

By

(0, 0,

is

not

is

different than

circle.

Normally the

filled.

drawn around the outside of the

can be changed by using the -outline option.

and the

fill

If

you

color the same, the oval appears solid.

-stipple => bitmap

To

fill

the oval with a bitmap pattern (1 values in bitmap are colored,

ues are transparent), use the -stipple option.

-stipple has no a

bitmap

-tags =>

in

effect,

-stipple

If

the

-fill option

takes a default bitmap

name

isn't

or a

file

val-

used,

with

it.

taglist

When you The value

create an oval, use the

associated with

-tags

is

-tags option to assign tag names to them. an anonymous list of tag names; for exam-

ple:

$canvas->createOval(0,0, 100,100, -tags => ["oval",

"blue"]);

194

Chapter 9: The Canvas Widget

You

don't

need

to use a

$canvas->createOval

list if

(

,

,

you

are only specifying

-tags => "oval");

100,

100,

one tag name:

-width => amount The -width option changes how wide default for -width is 1 pixel.

the outline of the oval

is

drawn. The

The Polygon Item A

polygon

is

merely a bunch of

lines

where the

first

point automatically to create an enclosed area.

point

is

connected to the

last

The createPolygon method

requires at least three x,y coordinate pairs. For instance, the following piece of

code

will create a three-sided

polygon:

$id = $canvas->createPolygon( 1000, 1000, 850,950, 30,40);

Additional x,y coordinate pairs can be specified as well; for example: $id = $canvas->createPolygon( 1000, 1000, 850,950, 30,40, 500,500);

The options you can specify with createPolygon are the same as those you use with createLine: -fill, -outline, -smooth, -splinesteps, -stipple, -tags, and -width. Just remember that createPolygon connects the first point to the last point to enclose the area.

The Rectangle Item As

if

being able to create a rectangle using createLine or createPolygon

weren't enough,

y coordinate

we

sets,

also

have the createRectangle method.

It

only takes two x

which are the opposite corners of the rectangular

area:

$id = $canvas->createRectangle(10, 10, 50, 150);

we have seen the options available for createRectangle with the other create methods: -fill, -outline, -stipple, -tags, and -width. Although

Again,

I've

covered these options already, here are a few examples: A blue rectangle with black outline: $canvas->createRectangle(10,10, 50, 150, -fill => 'blue'); # A blue rectangle with a thicker outline: $canvas->createRectangle(10,10, 50, 150, -fill => 'blue', -width => 10); #

The Text Item Finally,

an item type that doesn't have

lines in

widget by using the createText method.

It

it!

You can add

text to a

requires an x,y coordinate pair,

canvas

which

determines where you place the text in the canvas, and the text to be displayed: $id = $canvas->createText

(0, 0,

-text => "origin");

Creating Items in a Canvas

195

you wouldn't see any text on the Because there is no point in that, we will assume that you will always -text with a text value to display. The other options available for text

The -text option screen.

specify

actually optional, but then

is

items are as follows:

-anchor => "center"

"n"

|

|

"e"

"s"

|

"w"

|

"ne"

|

|

"nw"

"se"

|

"sw" I

The -anchor option determines where the text is placed in relation coordinate. The default is centered: The text will be centered over no matter how large the piece of text is.

to the x,y that point

-fill => color The text is normally drawn in black; you can change this by using the -fill option. The name of this option doesn't make much sense when you think about it in terms of text (normally our widgets use -foreground to change the color of the text). For example, -fill => 'blue' will draw blue text.

-font => fontname

You can change

-justify => "left" If

to

by using the -font option.

the font for the displayed text

"center" more than one line, the -justify option specified. The default justification is to the left. |

"right"

|

the displayed text has

be

justified as

cause

will

it

-stipple => bitmap This option

name

(or

is

file)

a bit strange, but here

bitmap pattern. Most of the time, use

it

is

anyway.

If

you specify

a bitmap

with the -stipple option, the text will be drawn by using the this will

make

the text unreadable, so don't

unless you're using a large font.

it

-tags => taglist The taglist assigned to

-text =>

is

a single tag

name

or an

anonymous

list

of tag

names

to

be

this item.

string

This option

is

not optional. The specified string

is

displayed in the canvas wid-

get at the x,y coordinate.

-width => amount another misnamed option because

This

is

each

text character.

the text line.

is

The

It

determines the

it

does not change the width of

maximum

length of each line of

text. If

longer than this length, the line will automatically wrap to a second

default value for

amount

characters. Lines are always

broken

is 0,

at

which

will only

break lines

at

spaces so words won't be cut in

newline half.

"

;

196

Chapter 9: The Canvas Widget

Text item indexes

Methods

that affect text items will

for the regular text

canvas text item are only one line (even

sometimes ask

for

widget were covered in Chapter similar.

if it

The only

difference

has "\n" characters in

it).

is

an index value. Text indexes 8,

and the index values

that

each item

is

for a

considered

Index values are as follows:

n

A number

value: for example,

or 12.

is

the

character, 1

first

is

the second,

and so on. "end"

The character directly after the to add to the end of the string. "

insert The character

last

one. Often used with the

insert method

directly before the insertion cursor.

"sel. first"

The

first

character of the selected text. Only valid

if

there

is

a selection.

"sel. last"

The

last

character of the selected text.

Only

valid

if

there

is

a selection.

"©a:, J"

The character

closest to the point x,y of the canvas (not screen coordinates).

Deleting characters

To delete characters from within a text item, use the debars method: $canvas-> debars tag/id, first [, last ]) Specify a tag or ID to match the text item(s) and .

(

the index at which to ters to the

end of the

start deleting. If

string will

the

end index

isn't

specified,

all

the charac-

be deleted (including any "\n" characters).

Positioning the cursor

You can

xcvocsoic {tag/id

index).

,

fied item has the current

sor

if it

by using ieursor: $eanvas-> only show up immediately if the speci-

specifically place the blinking text cursor

doesn't,

it

just

The cursor

will

keyboard focus. You can

won't display

until the

still

set the position of the cur-

item does get the keyboard focus.

Index information

You can

find out an index

Don't get confused

based on another index by using the index method.

yet; here's

an example:

$index = $canvas->index("textitem"

,

"sel. first"

)

Creating Items in a Canvas

197

This will return the numerical index associated with the the text item. it's

a tag

Adding

If

will

named "textitem"), then

the

first

selected character in

match the tag or ID indicated first

one found

will

(in this case

be used.

text

To add more id,

more than one item

index,

use the insert method: $canvas->insert tag/

text to a text item,

string)

.

The

first

(

argument

is

the tag or ID,

which can match multiple

items. The second argument is the index before which to insert the new and the last argument is the actual string to insert into the text item.

string,

Selecting text

There are several methods you can use to programmatically select portions of the

To clear the selection (any selection; there are no tags or IDs sent with this command), use $canvas->selectClear To select a portion of text, use selectFrom and selectTo. The following two lines of code select the text from beginning to end for the first item that matches the tag "text tag": text.

( )

$canvas->selectFrom( "texttag" 0) $canvas->selectTo "texttag" "end"

.

,

(

,

You can add

to the selection

just ("adjust"

,

tag/id,

has the selection in

it

)

by using selectAdjust: $canvas->selectAd-

index).

You can

get the ID of the item that currently

by using $id = $canvas->selectltem()

The Widget Item You can gets, or

put any type of widget inside a canvas

at eWindow method. Before

calling

—buttons, checkbuttons, wid—by using the Gretext

you are a little crazy) createWindow, you must

even another canvas widget

(if

create the widget to

put into the canvas. Here's an example: $bttn = $canvas->Button(-text => "Button", -command => sub { print "Button in canvasXn"; $id = $canvas->createWindow(0, 0, -window => $bttn)

There are a few things you should note about

this

example (which

}

is fairly

)

typical

except the subroutine associated with the button doesn't do anything useful): •

The button

is

a child of the canvas widget.

The button could be

canvas

is

also a child of the

be a child of a •

a child of an

window

ancestor of the canvas (the button could be a child of the main

if

the

main window). However, the button should not

different toplevel

widget that has nothing to with the canvas.

The createWindow method doesn't actually create the widget; the canvas. The button is placed at the specified coordinates vas and has not been placed on the screen with pack grid ( )

,

just

it

puts

it

in

inside the can( )

,

or

place

( )

;

Chapter 9: The Canvas Widget

198



The widget must be created before you



You can

When you figure (e.g.,

createWindow.

and the callback associated with

it

will

be invoked,

with any other button.

just as •

click the button

call

it.

you can use any of

create the widget,

You can

that widget's options to con-

continue to configure the widget by using the reference to

it

$bttn).

The following options which you can use when you call createWindow than widget options: like options you use with pack

are

more

( )

-anchor => "center"

|

"n"

"e"

|

"s"

|

|

"w"

|

"ne"

|

"nw"

|

"se"

"sw" I

The widget will be placed at the x,y coordinates according to the -anchor value. The defauk is "center", which means that the widget will have its center point placed on x,y. -height => amount The widget will be given this height. If you don't use -height, the widget will have the height it was created with (usually the natural size of the widget).

-tags => taglist The taglist associates a tag with the widget. You can specify string, or an anonymous list of tag names.

-width => amount The widget will be given widget

will

this

have the width

it

width.

If

either a single tag

you don't use the -width

was created with

option, the

(the natural size of the widget).

-window => $widget This

is

you don't $widget is The

a nonoptional option. If

widget put in the canvas.

specify -window, there will be a reference to a widget item.

no

You

can create the widget beforehand or inline as follows: $canvas->createWindow(0, 0, -window => $canvas->Button(-text => "Button", -command => sub { print " Button \ " } !

It

makes sense

fancy with

to create the widget inline

if

;

)

)

you don't need

to

do anything

it.

Configuring the Canvas Widget As

usual, to configure or get information about the canvas widget,

you can use the

configure and cget methods, explained in detail in Appendix A, Configuring Widgets with configure and cget. Remember, configure and cget operate on the entire canvas

widget (possibly affecting the items within

it).

199

Tags

Conflguring Items in the Canvas Widget To change

the configuration options of any of the items within the canvas,

know

only need to

the tag

name

or the ID for that item.

You can

you

then use the

itemcget and itemconfigure methods. They behave just like the cget and configure methods, except as a first argument, they take the tag or ID of the item(s). I use the term "item(s)" because a tag can refer to more than one item. Here are some examples: $color = $canvas->itemcget "circle" -fill) $canvas->itemconfigure($id_number, -fill => "yellow", -outline => (

,

Make

sure the options

Each item type has a

list

5)

you use with itemconfigure and itemcget

are valid.

of valid options; they are listed earlier in this chapter with

each create method.

When you

-tags option, the itemconfigure method will replace any curThe taglist associated with -tags can also be empty, essentially remove all tags.

set the

rently set tags for the item.

which

will

Tags Each item can also have a tag (or more than one seen tags used before in the a tag.

A

method

tag can

be assigned

text widget,

when

where

the item

to assign a tag after the item has

is

been

tag) associated with

created, or

We

have

you can use the addtag

created.

There are two special tags

that are automatically assigned

"current" and "all"

The "all"

tag.

it.

sections of text could be assigned

tag refers to

all

and maintained: the

the items in the canvas.

The " current " tag refers to the topmost item that the mouse cursor is over. If the mouse cursor is outside of the canvas widget or not over an item, then the " current" tag does not exist.

You can use

tags to

you want

all circles

from time

to time,

make changes to

to

many

have the same

then give

all

different items at once. For instance,

if

you want to be able to change it a "circle" tag when you create them. change the configuration options of the

color, but

circles

Using the itemconfigure method to items with the "circle" tag.

The following

are

some sample syntax

lines for creating tags.

$canvas->addtag( "newtag" tag/id) "above" The "newtag" tag is added to the item that is above the tag/ID item. If there is more than one match for tag/ID, the last item found will be used so the "newtag" is directly above the tag/ID item in the display list. The display list ,

,

;

;;

;

200

Chapter 9: The Canvas Widget

created as you add items raise and lower methods.

to the canvas

is

$ canvas - >addt ag

(

"

newt ag "

"

,

al 1 "

and can be manipulated with the

)

The keyword "all" is a special tag canvas. Items added to the canvas "newtag" in their taglist.

that includes every item currently in the after the call to addtag will

not contain

$canvas->addtag("newtag" "below", tag/id); The "newtag" tag is added to the item that is directly below the tag/ID item. If more than one item matches the below tag/ID search, the lowest item in the ,

list

will

be used.

$canvas->addtag "newtag"

"closest"

(

Use the "closest" tag canvas coordinates).

If

,

x,

,

y)

;

to select the item closest to the x,y coordinates (in

more than one item matches,

the last

one found

is

used.

There are two more possible arguments for specify a to

number

that indicates

be considered. For instance,

how if

You can look

,

this

form of addtag. You can

out from the x,y coordinates items are

you want an item

be considered "closest", make the $canvas->addtag( "newtag"

far

that

is

within 10 pixels to

call as follows:

"closest",

50,

100,

10);

also specify a starting tag/ID to start a search.

The

call

would then

like this:

$canvas->addtag( "newtag"

By using

this

,

"closest", x, y,

form, you can loop through

all

10,

$tag_or_id)

the closest items.

$canvas->addtag "newtag" "enclosed", xl yl, x2, y2) You can assign the same tag to several items within the area bounded by ixl,yT) to (,x2,y2) by using the "enclosed" form of addtag. Items will only be given "newtag" if they are completely within the area. The coordinates must make sense when you specify them: xl < x2 and yl < y2. (

,

,

"overlapping", xl, yl, x2, y2) $canvas->addtag "newtag" To assign tags to any item that has any part inside a bounded region, use "overlapping" instead of "enclosed". Even if the item has only one pixel (

inside this area,

same

as for

,

it

will

;

count. All other rules for the bounding area are the

still

"enclosed".

$canvas->addtag "newtag" (

Assigns "newtag" to

all

,

"withtag"

,

tag/id)

;

the items with the tag or ID specified.

201

Tags

Binding Items Using Tags Each item will

in a

canvas can have an event sequence bound to

be invoked

when

that event

sequence happens. This

is

it

so that a callback

similar to

adding an

event sequence binding for widgets except item tags or item IDs are used.

(Remember,

if

you want

add a normal binding

to

must use Tk: :bind (or canvasBind

The general form of bind $canvas->Tk:

The sequence would be inition

[

,

similar to

are available for

the

command

is

all

]

)

You

keep can't

is

is

over

def-

Binding Events.

available in Chapter 14,

in mind that only mouse and keyboard do any of the weird esoteric bindings that

widgets.

an example that changes the color of any items tagged with "blue"

mouse

you

;

"" or "". A complete

create item bindings,

bindings are valid for items.

Here

sequence,

and explanation of event sequences

When you

itself,

as follows:

is

:bind(fc?g/iirf

widget

to the canvas

for TkS.O users) instead of just bind.)

when

it:

When the mouse is over the item, color it blue $c->Tk: :bind( "blue" "" sub { $c->itemconfigure("blue" -fill => "blue"); # When the mouse is not over, color it black. " $c->Tk bind "blue " " sub { $c->itemconfigure( "blue" -fill => "black"); #

,

,

}

)

(

:

:

,

,

});

Finding Tags find command to determine which items have a certain tag. The find are the same as those of addtag (except for the newtag argument). Here are the basic formats (see "Tags" earlier in this chapter for more details on what they mean and how they work):

You can use possible

the

ways

to call

$canvas->f ind( $canvas->f ind( $canvas->find( $canvas->find( $canvas->find( $canvas->find( $canvas->find(

"above" tag/ id) "all" "below" tag/ id) "closest" x, y [ , additional_area "enclosed" xl, yl, x2, y2) "overlapping", xl, yl, x2, y2) "withtag" tag/ id) ,

)

,

,

]

[

,

tag/id ]);

,

,

;

Getting Tags from a Specific Item To

get a

list

of

all

the tags associated with an item, use:

©list = $canvas->gettags tag/ id) If

the tag/ID matches

;

more than one item, then the first item found empty string is returned.

tag/ID doesn't match anything, an

is

used.

If

the

(

;

;

202

Chapter 9: The Canvas Widget

Retrieving when we

Bounding Box Coordinates

talked about the scrolling region of a canvas,

bbox method. The bbox method area in which

returns a

list

we saw

an example of the

with four elements that define the

The example used the special "all" tag, which refers to every item in the canvas. This was how we used it to define our scrolling region. You can specify more than one tag/ID to search for as follows: ($1,

$r,

Assuming

all

$t,

that

the specified tags exist.

$b)

= $canvas->bbox("blue"

,

"red");

you have been assigning the tags "blue" and "red" to appropricode would return the region in the canvas that encloses all

ately color items, this

blue and red items.

Translating Coordinates When you

up a callback and use the Ev( 'x' and/or Ev( 'y' arguments to find out where the user clicked, you must translate that information into canvas coordinates (Ev is explained in Chapter 14). To do this, use the canvasx and canvasy methods: set

)

$x = $canvas->canvasx (screenx $y = $canvas->canvasy (screeny

[,

[,

)

gridspacing ]) gridspacing ]);

Each method takes an optional gridspacing argument; then the canvas coordinate value will be rounded to the nearest value to

fit

the grid.

Moving Items Around Once an item has been created on the canvas, you can move it by using one of two methods: move or coords. The move method takes a tag or ID to indicate which items to move and the amounts to add to the x and y coordinates: $ canvas ->move

(

tag/id, xdistance, ydistance)

For instance, the following code will

move

;

items with the "blue" tag 100 pixels in

the x direction and 100 pixels in the y direction: $ canvas ->move

To move an

(

"blue"

,

100

,

100

)

item in the negative direction, simply specify a negative value for the

xdistance and/or ydistance. The other method, coords, allows you to explicitly specify a

new

x and y location for the

first

or ID: $canvas->coords tag/id, newx, newy)

;

item found that

is

identified

by the tag

203

Deleting Items

If

more than one

the item requires

you simply continue

set of x,y coordinates,

to

specify them:

$canvas->coords

You can

newxl,

(to^2coords

(tog/zlav!ex (tag/id,

move

The display

the ones created earlier

^canva.s->Ta.i.sB

The

the items in the canvas for a specific tag or

all

list.

all

the

If

first

tag

you want to which the first item or ID matches more than

moved.

you use the Scrolled method

to create the canvas,

you

can't

use the

item returned by that method to invoke either raise or lower; you'll get a nasty error about the

sion of

raise

wrong argument types because Scrolled

is

not invoking

this ver-

or lower, but another one. Use the subwidget to get the actual can-

vas reference and the

call to

raise and lower

will

work.

Deleting Items To remove an item delete method. It delete

all

matches

(or

more than one

takes a

it

list

item) from the canvas completely, use the

remove from the canvas. It will that you aren't deleting an example that uses three separate

of tag or IDs to

finds for the tag names, so

something you don't want to

Here

delete.

is

be careful

tag/IDs:

$canvas->delete "blue" (

You can

specify only

,

"circle"

one tag/ID or

,

as

$id_nuin)

many

as

;

you want.

;

(

;

204

Chapter 9: The Canvas Widget

Deleting Tags You can remove

tags

from items by using the dtag method. There are two forms:

$canvas->dtag tag) $canvas->dtag tag/ id, del tag) (

;

(

;

The first one will search for items with the specified tag and then delete the tag. The second will search for items that match the tag or ID and then delete the del tag (if it exists) from that item. This allows you to delete a subset of the tabs, rather than every single tag.

Determining Item Type To determine an

item's type, call the

$canvas->type tag/ id) {

type method:

;

more than one item, only the type of the first item is The returned value will be a string describing the item type: "oval", "text", "rectangle", and so on. the tag or ID matches

If

returned.

Set To

Keyboard Focus

assign the keyboard focus to an item, use the

focus method:

$canvas->f ocus tag/id) If

the item doesn't

know what

to

do with the keyboard

focus, nothing will hap-

pen. You'll use this to change the focus to a widget within the canvas.

Rendering the Canvas as PostScript You can It

get a

copy of the canvas

in a

as postscript

output

will either return the PostScript

or, if

by using the postscript method. -file option is specified, put it

the

file:

$postscript = $canvas->postscript $canvas->postscript (-file => "ps.out"); (

The following options allow you

)

to control the output of the PostScript.

-colonnap => \@array Specifies that each element in setting color values; e.g.,

-colormode => "color"

|

Creates the postscript in

("mono").

@array must be a valid postscript command

for

"1.0 1.0 0.0 setrgbcolor".

"gray" full

|

"mono"

color, grayscale ("gray"), or black

and white

205

Scaling the Canvas

-file => filename Specifies the

file in

which

to put the PostScript output.

-fontmap => \@array Each element

in

@array

is

two-element array that contains a fontname and

a

The fontname should be a complete font name so Tk *-140-*"). (e.g., "-*-Helvetica-Bold-0-Normal

point size. correctly

-height =>



will parse

a it

size

Sets the height of the area to print.

The

default height

is

the canvas height.

"center" -pageanchor => "n" "e" "s" "w" Indicates where the page should be placed over the positioning point fied by -pagex and -pagey options. Default is "center". |

|

|

|

speci-

-pageheight => height Sets the height of the printed page.

height

The canvas image

will

be scaled to

fit.

any valid screen distance.

is

-pagewidth => width width of the printed page. The canvas image

Sets the

will

be scaled

to

fit.

-pagex => x Sets the coordinate for the

x positioning

point.

Can be any

valid screen

distance.

-pagey => y Sets the coordinate for the

-rotate => page

-width =>

size

Sets the

point.

Can be any

valid screen distance.

1

|

If 1, tlie

y positioning

is

rotated into a landscape orientation. Default

is

portrait orientation.

width of the canvas area to be printed. Defaults to the width of the

canvas.

-X => X Sets the left

the

left

edge of the area

to

be printed

(in

canvas coordinates). Default

is

to

be printed

(in

canvas coordinates). Default

is

edge of the window.

-y => y Sets the top

the

left

edge of the area

edge of the window.

Scaling the Canvas When you them

all

put a large number of items on the canvas,

without scrolling

all

over the place.

It's

it's

sometimes hard to see

possible to scale the canvas, for

;

,

;

;

206

Chapter 9: The Canvas Widget

example, so

The usage

it

for

will shrink everything in half or

scale

explode

it

to twice the original size.

as follows:

is

$canvas->scale( tag/id, xorigin, yorigin, xscale, yscale)

The

scaling

is

centered around the xorigin and yorigin.

I

suggest using the real

you can come up with a good reason not to. Both xscale and the scaling factors used on each coordinate in each item. Here are some

origin (0, 0) unless

yscale are

examples: $canvas->scale{ "all" $canvas->scale( "all" $canvas->scale( "all" $canvas->scale("all" a great idea to

It's

Keep

ing for you. set

it

to

1

add

1,

0,

.5,

0,

0,

2,

2);

#

0,

0,

3,

3);

#

In

#

.5);

and

Zoom Out

button that takes care of the scal-

track of the scaling factor in a variable ($scale, for instance);

to start with. Multiply

thing you'll need to vas,

0,

0,

Zoom

a

no change! make all 1/2 size double everything triple everything!

#

1);

0,

do

make

is

it

by

.5

zoom

to

sure that,

you

if

you multiply those coordinates by the

out and by 2 to insert

zoom

any new items

in.

The

last

into the can-

scale factor as well (otherwise they will

look either too large or too small compared to the

rest

of the canvas items).

Scanning Use the scan method to implement scanning of the canvas: $canvas->scanMark (x, y) $canvas->scanDragto (x, y)

The

first call,

$ canvas ->scanMark(x,

the current canvas view.

The second

y)

call,

,

records the x and y coordinates and

$canvas->scanDragto (x, y) causes ,

the view in the canvas to be adjusted by 10 times the difference between these

coordinates and the previous ones sent with scanMark. This makes the canvas

look as

if it

was moved

Scrolling

at

high speed.

Methods

The canvas widget can be scrolled both horizontally and vertically. The methods xview and yview are used to communicate with the scrollbars. See Chapter 6 for more information on how these methods work.

A Drawing Program Example The canvas widget

is

very versatile and can be useful for displaying different types

mind when people

of items.

One

vas

drawing program. To save you the trouble,

is

a

of the

first

things that

comes

to

think of a can-

I've written a

rudimentary

A Drawing Program Example

207

drawing program called Quick Draw you can use to draw rectangles, ovals, and lines.

You can

also

change the thickness of the objects before you draw them.

only requires a tiny bit of error-checking to

make

it

It

a slicker program. Here's the

code: use Tk; $inw =

MainWindow->new;

$nTw->title( "Quick Draw");

$f = $inw->Frame( -relief => 'groove', -bd => 2, -label => "Draw: ") ->pack( -side => 'left',

-fill => 'y'); $draw_item - "rectangle"; $f->Radiobutton( -variable => \$draw_item, -text => "Rectangle", -value => "rectangle", -command => \&bind_start) ->pack( -anchor => 'w'); $f->Radiobutton( -variable => \$draw_item, -text => "Oval", -value => " oval " -command => \&bind_start) ->pack( -anchor => 'w'); $f->Radiobutton( -variable => \$draw_item, -text => "Line", -value => "line", -command => \&bind_start) ->pack( -anchor => 'w'); $f->Label(-text => "Line Width: ") ->pack( -anchor => 'w'); $thickness = 1; $f->Entry(-textvariable => \$thickness) ->pack( -anchor => 'w' )

-cursor => "crosshair" ->pack( $c = $mw->Scrolled( "Canvas" -side => "left", -fill => 'both', -expand => 1); )

,

$canvas = $c->Subwidget

&bind_start

(

"

canvas "

)

( )

MainLoop;

sub bind_start { # If there is a "Motion" binding, we need to allow the user # to finish drawing the item before rebinding Button-1 # this fen gets called when the finish drawing the item again ©bindings = $canvas->Tk: :bind("") return if ($#bindings >= 0); if

($draw_item eq "rectangle" $draw_item eq "oval" |$draw_item eq "line") $canvas->Tk: :bind( "" [\&start_drawing, Ev( 'x' Ev( 'y' |

|

|

,

}

}

)

,

)

]

)

{

;

;

;

;

;

208

;;

;

Chapter 9: The Canvas Widget

sub start_drawing

my ($canv,

{

= @_ $x = $canv->canvasx($x) $x,

$y)

$y = $canv->canvasy ($y) Do a little error checking $thickness = 1 if ($thickness #

if

/[0-9]+/);

!~

($draw_item eq "rectangle") { $canvas->createRectangle($x, $y, $x, $y, -width => $thickness, -tags => "drawmenow" elsif {$draw_item eq "oval") { $canvas->createOval ($x, $y, $x, $y, -width => $thic)cness, -tags => "drawmenow"): elsif ($draw_item eq "line") { $canvas->createLine($x, $y, $x, $y, -width => $thickness, -tags => "drawmenow"); )

}

}

}

$startx = $x; $starty = $y; Map the Button-1 binding to &end_drawing instead of start drawing $canvas->Tk: :bind( "" [\&size_item, Ev('x'), Ev{'y')]); $canvas->Tk bind " " \&end_drawing Ev x Ev y

#

,

(

:

(

:

[

,

(

'

,

'

)

,

'

'

)

]

)

}

siib

size_item

my ($canv,

{

$x,

$y)

= @_;

$x = $canv->canvasx $x) (

$y = $canv->canvasy ($y)

$canvas->coords "drawmenow"

$startx,

(

,

$starty,

$x,

$y)

}

sub end_drawing

my ($canv,

{

$x,

$y)

= @_;

$x = $canv->canvasx($x) $y - $canv->canvasy $y (

)

and remove the tag from the item

# finalize the size of the item,

$canvas->coords "drawmenow" $canvas->dtag "drawmenow"

$startx,

(

,

$starty, $x, $y)

(

)

remove motion binding. $canvas->Tk bind " " &bind_start #

"

(

:

:

,

"

)

( )

}

Note less

ality:

a

that

I

didn't set the

drawing space

Do

few

after a

nothing!)

-scrollregion was

for the user. (This It's

a cute

little

program

of the canvas methods. Figure 9-4

few items have been drawn on

it.

at all

because

the easiest that

I

way

wanted

to create a limit-

to provide this function-

demonstrates

how

to use

bind and

shows a screen shot of the application

Fun Things

209

to Try

QtickDraw

ilia

Draw: V' Rectangle

V

Oval

#

Une

Une

VWdth:

hi Figure 9-4. Quick

Draw application

Fun Things

screen

to Try

The Quick Draw application doesn't do much ideas for features to add to the application:

that

is

useful, but here are



Add



Create a Save Drawing feature that will loop through

the capability to print to a PostScript

file.

out their types and coordinates to a text

Drawing feature •

Allow the user



Add an

some

file.

Of

all

the items

course, you'll

and write

need

a

Load

as well.

to create text items.

entry widget that lets

name) with which

to

draw the

you change the color (by typing items.

in a color-

The Scale Widget

-7

A

scale widget

is

a strange

little

widget.

It's

thing other than

When you -

itself.

It

because

similar to a scrollbar

long and skinny with a button in the middle of

but

it,

it



does keep track of something though

change the position of the button

I with the scale changes. Here are

some

things

it is

doesn't scroll anya

number.

in the scale, the value associated

you can do with a

number between



Create a widget from which a user can select a



Create three scales, each representing a value in an

RGB

scale widget: 1

and

100.

(red, green, blue)

number. •

Create four sliders, each representing a portion of an IP address. Each scale

can go from a label

to 255,

and

it

would probably be smart

to start

widget to show the completed IP address, periods and



Create a temperature scale that



Show

the

amount of

rainfall

starts at

so far

them

at 255.

Use

all.

-50 and goes to 130 degrees.

this year.

The

scale can

be marked to show

every five inches.

The

scale widget can

have the most room

be placed horizontally or

in

vertically,

depending on where you

your application window.

Creating a Scale As with other widgets, you can create ing options to the scale to change

$parent->Scale

(

[

its

a scale

by using

210

it

option => value

on the screen (such

and pass-

configuration: ]

)

->pack;

Use one of the geometry managers discussed ment, to place

a parent widget

as pack, as

in

Chapter

shown

2,

in the

Geometry Managepreceding code).

211

Creating a Scale

Most of the options associated with the scale widget are the standard options used with

all

other widgets. All of the possible options are in the following

that

list.

A

discussion of special options that have a slightly different meaning for the scale

and options

that are specific to the scale

-activebackground => -state

-background =>

is

background should be when the cursor

is

over the

is

not over

'active').

color

background should be when the cursor

Sets the color the slider's

the slider

list.

color

Sets the color the slider's slider (the

widget follows the

(-state

is

'normal').

-bigincrement => amount Sets the amount by which

the slider will change value

in large increments. Default

is 0,

when

required to do so

causing the value to change by 1/10 the top

value of the scale.

-borderwidth => amount Sets the

width of the edges of the widget. Default

is 2.

-command => callback Sets the callback

invoked

when

the slider

is

moved.

-cursor => cursomame Determines the cursor to display

when

the

mouse

is

over the

scale.

-digits => amount Indicates

how many

significant digits to retain

when

conversion from a num-

ber to a string takes place.

-font => fontname Sets the font

used to display any

-foreground =>

text in the scale.

color

Sets the color of the text displayed in the scale.

-from => value Indicates the

low end of the

-highlightbackground =>

scale values. Default

is 0.

color

Sets the color of the highlight rectangle displayed

around the scale when

it

does not have the keyboard focus.

-highlightcolor =>

color

Sets the color of the highlight rectangle displayed

around the scale when

the keyboard focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle displayed

around the

scale.

it

has

|

.

.

212

Chapter 10: The Scale Widget

-label =>

labelstring

Describes a label for the scale. Default

is

no

label.

-length => amount Sets the length of the slider (the long direction, regardless of the value of

ent)

-orient => 'vertical'

'horizontal'

|

Sets the direction the scale

-relief => 'raised' Determines

-ori-

screen distance.

in a valid

how

|

drawn. Default

is

'sunken'

'flat'

|

is

'ridge'

'groove' 'solid' drawn. Default is flat

the edges of the widget are

-repeatdelay => milliseconds Sets the number of milliseconds

'vertical'. |

|

'

'

the widget waits before repeating.

-repeatinterval => milliseconds Sets the number of milliseconds the widget delays between

repeats.

-resolution => value by which the value

Sets the increments

-showvalue => If set

in the scale will

change. Default

is 1.

1

|

to 0, the value of the slider setting

is

not

shown

at all.

Default

is 1.

-sliderlength => value Sets the size of the slider (inside the widget). Default

-state => 'normal' Determines the with

it.

Default

'active'

|

state of the is

-takefocus => 1

'

normal |

|

|

is

25.

'disabled'

widget and whether or not the user can interact

'

\inde£

Determines whether or not the widget can receive keyboard focus. Default to let the

is

program decide.

-tickinterval => value Describes the labels drawn by the right (or on the bottom) of the scale. Labels means no labels will be drawn at all. are drawn for every value. A value of Default

is 0.

-to => value Sets the top value of the scale. Default

-troughcolor=>

is

100.

color

Sets the color of the area

behind the

slider button

(same as

a scrollbar).

-variable => \$ variable Sets the variable in

which the

slider value

is

stored.

-width => amount Sets the width of the skinny part of the slider (regardless of the value associ-

ated with -orient).

Minimum and Maximum

213

Values

Assigning a Callback The callyou change the value from 50 to 100 and the scale increment is 1, the callback will be invoked 50 times. The callback is also called when the widget is created. My recommendation is not As

usual, use the

back

to assign a callback for the widget.

invoked every time the scale value

is

to use

-command option

-command unless you have

a small

is

changed. So

number

if

of possible values.

Orientation To change

-orient

the orientation of the scale, use the

option.

It

takes a string

value that should contain either "horizontal" or "vertical". The default for this

option

is

"vertical". Figure 10-1 shows both

a horizontal scale

and a

verti-

cal scale.

1

-Si^.

J

abBBHuta „J

Figure 10-1. Vertical scale (the default orientation)

and horizontal scale

Minimum and Maximum Values Use the -from and -to options scale. Usually the

with -to.

If

to

change the possible range of values

value associated with

you happen

-from

is

to switch them, the scale will

value on the right and the lower value on the negative.

left.

still

display with the higher

Either or both values can

be

Here are some examples:

$inw->Scale(-from => $iTiw->Scale(-from => $inw->Scale(-from => $inw->Scale(-from =>

As you can

whole

for the

smaller than the value associated

-to => 10)->pack; -to => -100) ->pack; -100, -to => -50)->pack; -0.5, -to => 0.5, -resolution => 0.1)->pack; -10, 10,

see, the values assigned to

integers.

-from and -to

also don't

need

to

be

214

Chapter 10: The Scale Widget

Displayed Versus Stored Value Sometimes the value you are searching very

far apart,

and

such as

by one would be

tedious.

between two numbers

for resides

1,000,000. Stepping through each of those values

You can change

the step value of the displayed

ber using the -resolution option. The default for -resolution

be changed

to

Note

the resolution

that

if

any value

that is

that are

is

less or greater

larger than

1,

than

it

but

1,

it

can

that.

possible for the slider to have a

is

value (set by the program, for example) that

is

one

num-

smaller or larger than the dis-

is

played value.

Adding a Label You can add in

a

your scale by using the -label option. The label

a label to

different location

is

placed

depending on the value associated with -orient (see

Figure 10-2).

^

S(E9IR^fiiSSpte

-J

4

vertical

J

horizontal

l-j-i

Figure 10-2. Two scales with labels

Displaying Value Increments The

scale displays

its

current value above or to the

left

of

itself

(depending on the

value associated with -orient). Suppose you want to display labels (such as 10, 20,

...

100) that

show

the user approximately

where the button needs

to

0,

be to

them underneath or to the left of the and no scale, you can use the -tickinterval option. By default, it is set to numbers are displayed. To show the values every 10 numbers, use -tickinterval => 10. The larger the range of values from which the scale can select, the larger the value this should be, or you'll end up with a bunch of numbers so close select those values. If

you want

to display

together that you won't be able to

tell

what they

are.

See Figure 10-3.

options You'll Probably Never Need

215

vertical

-0.5

horizontal

30 0.0

0.0

J 40

ZO

80

60

100

0.5

Figure 10-3- Using -tickinterual with both horizontal

Changing the

and vertical scales

Size of the Scale

You can change the size of the scale by using the -length and -width options. You can also change the size of the button displayed in the slider widget; to do so,

will

use the -sliderlength option.

change the length of the

It

takes a value specified in screen units

slider button.

$itiw->Scale( -sliderlength => 100);

f^{

#

and

See Figure 10-4.

make the button 100 pixels.

Scale exani}ile ,

1

^

Jl

Default slidertength: '^^"

r"~~r'™

'""""

~" ~

Sliderfengthof 100:

jl

Slideriengthof 10:

Hi

Figure 10-4. Different -sliderlength values

Options You'll Probably Never Need The two final options for the Scale widget creation method are -bigincrement and -digits. The -bigincrement option specifies the size of jumps when using really large numbers. The default for -bigincrement is 0, which means it will jump in increments that are 1/10 the total range. The -digits option represents how many digits will be used when converting from a number to a string. The default (0) forces the scale to use a precision that allows for a different string for every possible value on the scale.

;

;

;

216

Chapter 10: The Scale Widget

Configuring a Scale As

configure and cget methods, which let you query scale widget. See Appendix A for more details on how to

usual, the scale has both

and

options for the

set

use these methods.

Getting the Value of a Scale The get method $value

You can

=

will return the current value of the scale:

$scale->get

also specify

(

)

x and y coordinates and

retrieve the value of the scale at that

point:

$value = $scale->get

(x,

y)

;

Setting the Value of a Scale You can

force the value associated with the scale

by using the set method:

$scale->set (value)

This

method

option

great for setting an

is

at all. If

initial

value

you were using -variable,

if

you

aren't using the

-variable

just set that variable to the

desired

starting value.

Determining Coordinates The coords method ($x,

$y)

=

$scale->coords

The coordinates scale.

You can

($x,

$y)

=

returns a

list

containing x and y coordinates:

;

indicate the position in

which the current value

is

located in the

also pass in a value to find the coordinates of:

$scale->coords (value)

Identifying Parts of a Scale You can

find out

what

part of the scale a coordinate resides in

by using the iden-

tify method: $value

=

$scale->identify(x, y)

The identify method

;

returns a string containing

"slider", "troughl", "trough2", or an empty refer to

any of these

parts).

one of the following

values:

string (if the coordinates don't

Fun Things

217

to Try

Fun Things

to Try

Create a survey form that contains scale widgets for user information. Items

such as age (0-150 would be a safe range), income, and number of children the household can

all

be entered

into a scale.

Make good use

in

of the -reso-

lution, -to, and -from options to make the job easier for the user. Create a ping application that uses scale widgets (one for each portion of the IP address) to request

an IP address from the

user.

Menus

Different Types of Menus There are several ways to create and

Here are some examples of

application. •

Create



Display a

File, Edit, list

utilize a

menu from

how you

can use a menu-type widget:*

and Help menus across the top of your

within your Perl/Tk

application.

of fonts from which the user can choose (the selected font can

be marked with a checkmark). Display a



right-clicks

list

of editing

on another

commands

that

become

available

when

object (such as a listbox or entry widget) in your

the

user

window.

You can build each of these different types of menus with the basic menu widget. The menu widget itself is a list of items that are displayed one item per line in a box. Each item can have an associated callback that is called when the menu item is

invoked or selected. Unlike the other widgets

we have

seen so

far,

you cannot

use any of the geometry managers on a menu. Instead, you must use a method called

post

to display

your

menu widget (post

will

be discussed

later in this

chapter).

shows the contents of a typical menu widget. It contains several items, and a few more items. Separators are useful for grouping together related commands and providing a visual break if one menu contains a number of commands. Figure 11-1

a separator,

*

contains commands that aren't used frequently, such as configuration options, File Help, and .so on. You would be wise to put frequently accessed commands in the winto provide easier access for the user.

Typically, a

Open,

dow

218

menu

File Close,

219

Different Types of Menus

menu widget Item1

Item2 Items Item4

Figure 11-1. Simple

Menus

menu

are a great

radiobuttons,

way

widget with five items: Iteml, Item2, Separator, ItemS, to replace checkbuttons

you can place them on

and radiobuttons.

menu and

a

and Item4

you have

If

five

save a ton of screen space for

more important widgets.

A menubutton when

the

widget

menu

is

is

based on the menu widget and has a button

displayed.

When

the button

is

pressed, the

menu

that controls is

displayed

below the button. The button contains a text string that describes the items in the menu. A menubutton is the type of menu you'll use 90% of the time. Figure 11-2 shows a block diagram of a menubutton after the button has been pressed. The button part of the menubutton is the where the word "File" appears. directly

Figure 11-2.

A menubutton

menu

widget that uses a

widget

The main advantage of using a menubutton widget is that it handles the display functions of the menu. Because this is the most frequently used menu-related widget,

The

it

will

last

be covered

first.

menu-related widget covered

ently than the other type of

item from a

list

is

the optionmenu,

which behaves

menus. The optionmenu allows the user

differ-

to select

one

of items. For example, you can use an optionmenu to add the

following options to your program: •

Allow users to



Allow users



Allow users to choose Silent,

select a favorite color

to select the country in

how

from a

list

which they

of colors. live.

verbose they would

Semi-Verbose, and Verbose.

like the application to be:

Chapter 11: Menus

220

Figure 11-3 shows a block diagram of an optionmenu with Item3 selected.

Optionmenu widget (or popup menu)

Item1

Item2

Items Select Value:

Item4

Figure 11-3- Example of an optionmenu widget

Menus simply give you a way to group related tasks together, and the optionmenu allows you to group several choices together. There is a callback associated with each

menu

much

item,

like the callbacks associated

using 10 separate buttons, you can create 2

menus

with button widgets. Instead of

that

each contain 5

menu

items.

on display space and helps users understand that those items have a purpose and have been grouped together for their convenience.

This saves lar

simi-

The Menubutton Widget wMB^WIWi \

Item

1

..1

^ As described earlier, the menubutton widget has a down from a button when the button is pressed. The

from the window when an item from the menu

is

menu menu

that is

selected or

drops

removed

when

the

user clicks elsewhere in the application.

Many

applications use a menubutton-type construct.

The menubuttons

grouped across the top of the application and have names like File, Options, and Help. Figure 11-4 shows an example of several menubuttons

are normally Edit,

grouped together

in a frame.*

Creating a Menubutton when you

create a

menubutton widget, use the parent widget

Menubutton method, which then creates a menubutton widget options you send with the Menubutton method can configure both is initially displayed on the screen and the actual menu items: $itibutton =

$parent->Menubutton

(

[

options...

]

)

to invoke the

reference.

The

the button that

->pack;

this same look in a window by using a menubar widget. However, the additional provides is minimal, so we won't be covering it in this book. To get this look, create a frame widget with a relief of "ridge" and borderwidth of 2. Pack the menubuttons with -side => "left" for ail but the help menu, which has -side => "right".



You can accomplish

functionality that

it

221

The Menubutton Widget

— RIe

^ Jl

M^mftRittofi Edit

Options

Help

Exit 1

Figure 11-4. Example of window with several menubuttons across the top

When

it

is first

displayed with one of the geometry managers, you will only see

which is a button with "flat" relief. The menu menubutton won't appear until you press the button. Figure 11-5 shows the menubutton widget before and after the button is pressed. Notice how the button part of the menubutton, part of the

the relief of the button changes after

it

is

pressed.

^ mmii

^

Jl

'

3 Menuil

^J4

Menubutton

L

Menubutton =*



^^

1

Itemi torn 7 Item 3

Item

Figure 11-5- Menubutton before

and after the

button

4

is pressed

Menubutton Options The options specified with the Menubutton command (or via the configure method) can affect only the button part of the menubutton, both the button and the menu, or just the menu.* The options that affect the menu are valid for the menu widget as well as the menubutton widget. We will cover the available options briefly (and some not so briefly) in order to discuss the effects of each. The brief synopsis of all the options and their effects appears first.

When

the description says "Affects the button only," the behavior

would be

*

The menubutton widget comprises other widgets

functionality.

is

the

same

as

it

for a button widget.

(in this case,

button and menu) to provide the overall

.

222

Chapter

-activebackgroimd => Affects the

1 1:

Menus

color

background color of the button and the currently highlighted menu

item.

-activeforeground =>

color

Affects the text color of the button

-anchor => center '

'n'

|

'ne'

|

'se'

's'

|

'sW

|

'w'

|

|

item.

'nw'

|

'

Affects the button only.

-background =>

Changes the position of the

text within the button.

color

Affects the button

when

'e'

|

and the currently highlighted menu

and the menu.

the state of the button

All the

background color changes

and menuitems

is

'

normal

to color

'

-bitmap => bitmapname Affects the button only. Displays bitmap instead of text.

-borderwidth => amount Affects the button only.

Changes the width of the button edges.

-cursor => cursomame Changes the cursor when

Affects the button only.

it's

over the button part of

the menubutton.

-disabledforeground => Affects the button

color

and the menu item

text

when

-state

the

for either

is

'disabled'.

"below" "left" "right" "flush" -direction => "above" TkS.O option only. The value "above" puts the menu above the menubutton, "below" puts it below the button, and "left" and "right" puts it on the |

|

appropriate side of the button,

|

|

"flush" puts the menu

directly over the

button.

-font => fontname Affects the button only.

-foreground =>

Changes the font of any

text displayed in the button.

color

Affects the button only.

Changes the color of any

text or

bitmap to

color.

-height => amount Affects the button only.

Changes the height of the button.

-highlightbackground =>

color

Changes the color of the highlight rectangle displayed around the button when the button does not have the keyboard focus.

Affects the button only.

-highlightcolor =>

color

Changes the color of the highlight rectangle displayed around the button when the button does have the keyboard focus.

Affects the button only.

223

The Menubutton Widget

-highlightthickness => amount Affects the button only. Default

gle

around

Changes the width of the highlight rectan-

is 0.

edges of the button.

all

-image => imgptr image instead of

Affects the button only. Displays an

-indicatoron =>

1

|

mechanism

Affects the button; indirectly affects the display

When text,

set to 1

,

text.

on

a small bar appears

for the

menu.

the right side of the button next to any

bitmap, or image.

-justify => 'left'

'right'

|

Changes the

Affects the button only.

-menu => $menu Tells the menubutton

'center'

|

justification of the text

to display the

menu

within the button.

associated with

$menu instead of

anything specified via the -menuitems option.

-menuitems => Causes the

list

menu

to display a

of items to create.

list

-padx => amount Adds

Affects the button only.

extra space to the

left

and

right of the button

inside the button edge.

-pady => amount Affects the button only.

Adds

extra space to the top

and bottom of the button

inside the button edge.

-relief => 'flat'

'groove'

|

Affects the button only. Default

'raised' when the button

-state => 'normal'

is

'raised'

|

'

is

.

The

relief

'sunken'

of the button changes to

'disabled'

|

menu (menu

Affects the button; indirectly affects is

'

|

pressed.

'active'

|

flat

'ridge'

|

cannot be displayed

if

state

'disabled').

-takefocus =>

|

1

|

xmdef

Affects the button only. Default

is

0.

Determines whether or not the button

can have the keyboard focus.

-tearoff => Affects the

dashed

-text =>

|

1

menu

line in the

only. Default

is

1.

If set

to 0,

does not display the

tear-off

menu.

text string

Affects the button only. Displays the specified string

the -bitmiap or

-image option

is

used).

on the button (ignored

if

224

Chapter 11: Menus

-textvariable => \$variable Affects the button only. The information displayed on the button.

in

$variable

is

displayed

-underline => charpos The character

Affects the button only.

at

the integer charpos

is

underlined.

If

the button has the keyboard focus, pressing the key causes the button that

corresponds to the underlined character to be pressed.

-width => amount Affects the button only.

Changes width of the button

to

amount.

-wraplength => pos Affects the button only. Default

maximum amount

0.

is

Determines the screen distance for the

on one

of text displayed

line.

Button-Only Options The following options behave exactly

only the button portion of the menubutton, and

affect

as described in

Chapter

3:

-cursor, -anchor, -bitmiap, -border-

width, -font, -foreground, -height, -highlightbackground, -highlight-

-highlightthickness, -image, -justify, -padx, -pady, -relief, -takefocus, -text, -textvariable, -underline, -width, and -wraplength.

color,

-state,

Tear-off Items Each menu you create can be "torn off from

menu get

is

a

dashed

becomes

dow

its

line (see Figure 11-6);

own window and

its

when you

remains present

window. The

first

item on the

select this item, the until

you close

it

menu

wid-

with the win-

manager.

The other You can move the menu around on the screen, but you can't resize menu items will behave normally when they are selected. Be careful; you can tear off the same menu multiple times. Tom-off menus won't be updated when other events it.

in the

program are updated, so

it

is

a

good

idea to limit your use of tear-off menus.

with your list of arguments To remove the tear-off ability, use -tearof f => when you create the menu and the dashed line will no longer appear.

The

tear-off line in the

so your

menu

actually counts as

an item.

menu items will then number from 1 and menu items will number from and up.

then your

up.

It

If

uses index

if it

exists,

you use -tearof f=>0,

225

The Menubutton Widget

Menid)

3^§^

J

J

Menubutton

Menubutton

Itemi

Itemi

ItemZ

item 2 Item 3

Item 3

Item 4

Item 4

Figure 11-6.

Menu

with tear-off item

and menu

without tear-off item

Color Options options that determine

Several

color

both the button and the menu:

affect

-activebackground, -activeforeground, -background, and -disabledforeground.

Both -activebackground and -activeforeground played in the button and

menu

the currently active

affect the text/bitmap dis-

item in the menu. The cur-

menu item is the one that the mouse cursor is currently over. The becomes slightly raised and might change color depending on these The effect of these options on the button is the same as it is for a normal

rently active

menu

item

options.

button widget.

The -backgroimd option affects the entire menu and button background. The -disabledforeground option changes the color of the text of any menu items that have their own -state of 'disabled'; it also changes the text/bitmap color of the button if its -state is 'disabled'

Button Indicator In Chapter 4, their

own

tor that

we saw how

the radiobutton and checkbutton widgets each have

type of indicator. The button part of a menubutton also has an indica-

can be displayed on

right of the text, bitmap, or

indicator

button.

used

is

used to show

The option

that

it.

The

indicator

is

a small

3D

bar displayed to the

image on the button (see Figure something

to display the indicator

is

to display the indicator for the radiobutton

^

11-7). Usually the

happen when you press the -indicatoron, the same option

different will

fctefKUtNitton

^

and checkbutton widgets.

j|

'

Indicatoron

Figure 11-7. Menubutton with indicator shown

Menu

-^

,

,

226

Chapter

1 1:

Menus

-indicatoron to 1 does not change the appearance of the menu at you would not use the -indicatoron option unless you were using menubutton as a type of option menu or in a non-standard fashion. Setting

all.

Usually,

the

Specifying Items for the

Menu

Everything in this section will also apply to using the -menui terns option with the

menu widget

in addition to the

menubutton widget.

The easiest way to add items to the menu in a menubutton is to use the -menuitems option. The value sent with the -menui t ems option is a list of lists* that

menu but also any possible configuraway to illustrate this is with an example.

indicates not only the order of items in the tion options for that

menu

item.

The

best

$menub = $mw->Menubutton(-text => "Menubutton", -menuitems => [[ 'coitimand' => "Item 1"], 'command' => "Item 2"], [

[

[

In this snippet of code,

we

'command' => "Item 3"], 'command' => "Item 4"]]);

same menu

are creating the

that

we

displayed in

Figure 11-5. Here's a

breakdown of

the elements of the

list

and what they mean. The -menu-

items option expects a list of lists. It is the sub-lists that contain information about menu item. Each list that configures a menu item has a specified order to it. The first thing in the list is a string that will determine what type of menu item is created. The available types of menu items are "command", "radiobutton", "checkbutton", and "cascade". The second thing in the item list is a string that is displayed on the menu. After that, the options that affect that menu item type can be specified. To create a separator, use a string in place of an anonymous list. each

As you can

menu

-menuitems, I didn't assign any callbacks for any of the you selected one, nothing would happen. To assign callbacks, we

see, after

items. If

would change

the statement to look like

this:

$meniib = $mw->Menubutton(-text => "Menxibutton"

-menuitems =>

[[

[



is

If

]

]

you don't know what I mean by "list of list.s," you'll find that the Camel book (Programming Perl) The new version contains more information than you'll ever need to know about hashes, and creating anonymous lists.

a u.seful reference.

lists,

'command' => "Item 1", -command => \&do_iteml 'command' => "Item 2", -command => \&do_item2

227

The Menubutton Widget

'coinmand'

[

[

I

]

,

'command' => "Item 4", -command -> \&do_item4

]

]

used the -command option to add the callbacks, and

tine for

menu

each

item.

It

doesn't

=> "Item 3",

-coinmand => \&do_item3

make any

I

)

used a different subrou-

sense to specify a callback for the

separator item.

The

first

diately

two items

by

for

each item

a text string that will

list

must be the item type

be displayed

in the

play a different text string by using the -label option or to

second argument It

in this

list

might be confusing that

must be a

we

followed immeyou plan to disdisplay an image, the

string

menu. Even

if

string.

use both "command" and -coinroand. The

item type string and the second

is

first is

the option (which should be followed

the

by a

callback).

You can

method to add items to the menu: $menub-> also use the Addl terns -label => "Iteml", -command => \&do_iteml) ;. Addltems "command" The argument list is slightly different (you send only the type, and then you must use the -label option to specify the text to appear on the menu, but all the ( )

(

,

options for each

menu

item type are exactly the same).

menu

Certain options only apply to certain

item types, which are discussed in the

following sections.

Command item, So

far,

type

each example of a

menu

has had only "command" and "separator" types

of items. Usually, you'll also use the

pen when

the

Radiobutton It is

menu

item

is

-command option so

that

something

will

hap-

selected.

item, type

possible to put radiobuttons in a

menu

rather than inside the

window where

radiobutton would in the winThe same radiobutton rules apply: You should always have at least two radiobuttons and they should be grouped logically by using the same -variable => $variable option for each group. Figure 11-8 shows an example of the placement of radiobuttons in a menu.

they take up space. They look and act

dow

except they are

listed in the

menu

just like a

instead.

;

;

;

;

228

Chapter

Menut

-J

1 1:

Menus

J

J

Menubutton

^ Radio

1

# Radio 2 ^ Radio 3 '^

Radio 4

-*"

Radio 5

"^

Radio 6 1

Figure 11-8. Radiobuttons as

example

In an

in

menu

Chapter

4,

items

Checkbuttons

and

Radiobuttons,

tons to select the background color of the window.

radiobuttons in a #

!

menu and

We

we

used radiobut-

could also use those

save space in our application:

/usr/bin/perl -w

use Tk;

my

MainWindow->new;

$inw =

$iTiw->title "Menubutton" (

)

;

$inw->Menubutton(-text => "Color" ->pack( -side => 'left', -anchor => n foreach (qw/red yellow green blue grey/) { $menub->radiobutton( -label => $_, -coinmand => \&set_bg, -variable => \$background_color, -value -> $_)

$menub

=

)

'

'

)

}

MainLoop;

sub set_bg { print "Background value is now: $background_color\n" $inw->configure( -background => $background_color) }

Figure 11-9

menu

shows what the window looks

like after

it

has been resized and the

has been posted.

Checkbutton item type

You can

also put checkbuttons in a

menu

to

keep them out of the way. Use the

-coitimand option to configure the checkbutton to perform an action selected. Figure 11-10

Remember

shows what checkbuttons look

like in a

when

not.

is

menu.

the checkbutton guidelines: each checkbutton should have

-variable, because each can be selected or

it

its

own

229

The Menubutton Widget

^

~

^

-

N

color

-

sWiEiiRi^ptoii

^^^^^^^^-^8

red *^

"^

yellow

green blue

grev ™™* 1

Figure 11-9- Using radiobuttons in a

menu

^

to set

background color

Menu^

^

4

Menubutton

rm W Check

1

r

Check 2

pr

Check 3

r Check 4 m Check S r Check 6 Figure 11-10. Checkbuttons in a

menu

(1, 3,

and 5 selected manually)

Cascade item type

A

menu item points to another menu. When you select this type another menu will pop up to the right of the current menu. This is

cascade

item,

of

menu

the most

complicated item type to implement because you have to create another entire

menu

to display (the next major section in this chapter covers the

Figure 11-11 shows what a cascade

menu

item looks

like.

Menubutton

Figure 11-11. Cascade

menu

item inside a menubutton widget

menu

widget).

;

;

;

;

Chapter 11: Menus

230

The submenu must be a child of the menu within the menubutton widget. This allows Peri Tk to keep track of the correct hierarchy of the menus. The best way to create a submenu is to create the menubutton first and then create the submenu. $inenub = $inw->Menubutton(-text => "liy Menu",

-menuitems => [["cascade" => "Submenu"]]); $suhinenu - $inenub->inenu->Menu( -menuitems =>

We

can use the menubutton widget"s menu

item and then create the

new menu

$menub->entryconfigure( "Suimenu"

,

-menu =>

program

cade menus.

#! /tisr /bin/perl

item.

Now we

to point to the

is

it

can add

new submenu:

;

necessary to

menu

with the actual

menu

to return the actual

menu

it

first

will display.

you to play around with so you can get the two submenus, one with numbers and one with

for

creates

It

it

it

;

)

$ submenu )

Because of some problems with cascade menus, cascade entry and then configure

]

method

( )

as a child of the

menubutton and configure

the cascade item to the

entire Perl

...

[

create the

Here

is

an

feel of casletters:

-w

use Tk;

my $mw

= MainWindow->new; $mw->title "Menubutton" # Create menubutton and put on the screen $menub = $mw->Menubutton -text => "Menubutton" ->pack; (

)

)

(

make our suh menu to be cascaded a child of upper menu. $menul = $menub->menu->Menu; foreach (qw/one two three four/) { -label => $_) $menul->add( 'command' #

,

}

#

make second sub menu also a child of the upper menu

$men\i2 = $menub->menu->Menu;

foreach (qw/A BCD/) { $menu2->radiobutton (-label => $_) }

now add the cascade items to the main menu $menub->cascade( -label => "Numbers"); $menub->cascade( -label => "Letters"); #

now configure those cascade entries to point to correct submenu $menub->entryconfigure( "Numbers" -menu => $menul) $menub->entryconfigure( "Letters", -menu => $menu2); #

,

MainLoop;

You can

also create cascade

menu, but remember

to create

menu it

items

on

a

menu

as a child of that

that cascades

menu's menu.

from another

The Menubutton Widget

231

Separator item type Separators are noninteractive portions of a menu.

between menu items. To method on the menubutton widget or use a visual break

of another

They do nothing except provide separator

create one, either call the a string in the

-menuiteras

list

instead

list.

ImU

Mi^ii^

J

a

Menubutton

j

Itemi

ItemZ Item 3 Item 4

Seoarator

line 1

Figure 11-12. Separator in a menubutton widget

Figure 11-12 shows the separator

which

is

a

to create the

line (not

$niw->Menubutton(-tearoff =>

0,

unlike the tear-off menu, The following code was used

line. It is a solid line,

shown menubutton shown in

dashed

in Figure 11-12).

Figure 11-12:

-menui terns =>

[

['command' => "Item 1"], ['command' => "Item 2"], ^'command' => "Item 3"], ;'

We

could have used any string

style to is

at all in

always use the same string so

command' => "Item 4"]

place of the "-"

it is

line.

easy to recognize

However,

when

]

it

->pack; is

good

a separator item

created.

Accelerators The -accelerator option allows you to place a text string to the right of the text or image displayed in the menu. The string usually contains a clue to a quick-key combination that Figure 11-13, Item

will 1

execute the

command

associated with the

-menui terns

created by using this

list

-accelerator =>

"Alt+1"]. To make the

form an

need

action, you'll

in the

to use

bind

option: Alt-1

[

menu

item. In

The menuitem was 'command' => 'Item 1',

has the accelerator string Alt+1 next to

it.

key combination actually per-

(see Chapter 14, Binding Events).

;

,

252

Chapter 11: Menus

.

.

PI Meiiii^

.

1

1

^

Menubutton falBH

Item

1

AIU1

Item 2

items Item 4 1

Figure 11-13-

Menu

with accelerator next to Item 1

Menu Item

Displaying an Image in a Each menu item

is

image instead of

text.

the

-image

option.

a type of button, so

it

makes sense

Figure 11-14 shows what happens

The code

that created the

menu

is

that

you can display an

when you

also specify

as follows:

$imgl = $rnw->Bitmap(-file => "/usr/XllRe/include/Xll/bitmaps/lineOp.xbm" $inw->Men\ibutton(-text => "Menubutton", -menuitems => [[ 'coinmand' => "Item 1"], 'command' => "Item 2", -image => $imgl] )

[

'command' => "Item 3"], 'command' => "Item 4"] ->pack(-side => 'left');

[

[ )

]

g^MCTtrt^

-ijj

Menubutton

fteml

\ Item 3 Item 4

Figure 11-14.

An image displayed instead of text

In Chapter 4,

I

discussed using icons and

how

they can

make

options easier to

understand. Try to use good judgement and not go crazy with the picture items.

Too many vague

make an

menu

icons (such as the one displayed in Figure 11-14) can

application confusing.

The Menubutton Widget

233

Assigning a Different Menu By

default,

create your

But there

when you use the -menuitems option, a menu is own menu widget and tell the menubutton widget

is

a trick involved.

It's

You can

created. to use

a chicken-before-the-egg problem.

it

instead.

You need

to

menubutton and then create the menu widget as a child of the menubutton. Use configure to assign the new menu to the menubutton. Here is the

create

a

code example: create menubutton w/ some fake menu items $ml = $mw->Men\ibutton(-text => "Text Menul", -menuitems => [[ 'command' => "Item 1"], 'command' => "Item 2"],

#

[

[

[ )

]

'command' => "Item 3"], 'command' => "Item 4"] ->pack -side => "left", -expand => 'y' -fill => 'both' (

)

Create a Menu as a child of the Menubutton $ml $menu = $ml->Menu( -menuitems => [[ 'command' => "Item 1"], 'command' => "Item 2"], 'command' => "Item 3"]]); #

[

[

Now use the $menu with the Menubutton $ml->configure(-menu => $menu) #

MainLoop

As mentioned, you need to create the menubutton first and make it a child of $itM (the MainWindow). I created some menu items that will be different on the new

menu

so you can

tell

which menu the menubutton

is

using.

Configuring a Menubutton The cget method allows you

to get configuration information about

options associated with a menubutton.

You can use configure

any of the

to query or

change any of the options. Both configure and cget are explained

Appendix A, Configuring Widgets with configure

fully in

and cget.

Configuring Menubutton Items The menubutton widget has an entrycget method widget's entrycget method.

that

is

the

same

as the

menu

$value = $menub->entrycget index, option); (

The arguments cussed

in

"The

are an index

Menu Widget"

and the option

to query. Valid index values are dis-

later in this chapter.

;

;

,

; ;,

;

234

Chapter 11: Menus

The entryconf igure method is also provided by the menubutton widget. It performs the same function the menu widget's entryconf igure method performs: $men\ib->entrYconf igure index, (

Adding Items

to

option

[

])

;

a Menubutton

The Addl terns method gives you another way to put new items in the menu. It will always add the new item(s) to the end of the menu in the order they appear in the list. Similar to the arguments sent to the -menuitems option, the arguments sent to Addl terns are included in several lists. There is no need to enclose the item lists inside another list level because the only thing you send to Addl terns is item

lists.

Here

is

an example:

$menub = $rnw->Menubutton -text => "File" ->pack; $menub->AddItems ["coinmand" => "Open", -coinmand => \&do_open] ["command" => "Close", -command => \&:do_close] )

(

(

,

-command => sub

["command" => "Exit",

This use of

Addl terns

is just

another

way

exit

{

}

,

]

)

of saying the following:

$menub = $mw->Memibutton(-text => "File", -menuitems => ["command" => "Open", -command => \&do_open] ["command" => "Close", -command => \&do_close] [

)

]

["command" => "Exit", ->pack;

Notice the extra set of All the information in

sent to

[

]

around the

between the

[

lists ]

is

{

exit

containing the

exactly the

}

]

menu

same

as

it

item information.

was when

it

was

Addl terns.

The command method adds use command, you must use in the

-command => sub

menu

.

a

item to the end of the menu. When you -label option to specify the text to be displayed example created: the same menu Addltems

command

the

This code creates

( )

$menub = $mw->Menubutton(-text => $menub->command( -label => "Open", $menub->command( -label => "Close", $menub->separator $menub->command( -label => "Exit",

"File" ->pack; )

-command => \&do_open) -command => \&do_close) -command => sub

{

exit

}

)

Creating a Cbeckbutton The checkbutton method adds a checkbutton item to the end of the menu. Like the command method, you are required to use the -label option to specify the text string to display in the

menu

with the checkbutton. All other checkbutton item

The Menubutton Widget

235

options are the same as those listed in "Specifying Items for the this chapter.

Menu"

earlier in

Here's an example:

$menub = $mw->Menubutton(-text => "Options"); $menub->checkbutton( -label => "Confirm Quit?" -variable => \$confirm_quit)

checkbutton is really a menu widget method, but it also works on a menubutton The same is true of radiobutton, separator, and cascade.

widget.

Creating a Radiobutton The radiobutton method adds must specify the

text to

a radiobutton item to the

be displayed

in the

menu by

end of the menu. You

using the -label option.

$menub->radiobutton(-label=> "Radio item")

Creating a Separator The separator method adds

a separator line to the

end of the menu.

It

does not

take any arguments: $menub->separator

(

)

Adding a Cascade Menu end of the menu. You must by using the -label option. Use $menub-> entryconf igure -menu => $submenu) to assign the menu to be cascaded.

The cascade method adds

a cascade item to the

specify the text to be displayed (

assume we already created $menu_more $menub->cascade (label => "More menu..."); -menu => $menu_move) $meniib->entryconf igure "More menu. ", #

.

(

.

Getting a Reference to the The menu method

Menu Item

returns a reference to the

menu used

within the menubutton

menu as the parmenu widget methfrom our menu by using

widget. This allows us to create cascade entries with the actual ent of the cascaded ods.

For example,

menu;

we

it

also allows us access to

could delete a

menu

all

item

of the

$menub->menu->delete(l), which would delete the second item in the menu. For more information on the menu widget methods, see "The Menu Widget" later in this chapter.

;

;

;

236

Chapter

1 1:

Menus

Complete Menubutton Examples Menus

more complicated widget than we've seen before because you them the same way. Sometimes you can use the simple -menuitems option, and other times you'll want to add to them dynamically. This section contains some full-length Perl scripts that create some useful are a

don't always add items to

menus.

Creating a Here

is

Menubar

the code that

was used

to create the

window and menubar

in Figure 11-4:

# /usr/bin/perl -w use Tk; my $inw = MainWindow->new; $iTiw->title "Menubutton" !

(

)

;

$inw->Button(-text => "Exit", -command => sub

{

exit;

}

)

->pack{-side => "bottom");

= $mw->Frame (-relief => 'ridge', -borderwidth => 2); $f->pack(-side => 'top', -anchor => 'n', -expand => 1, -fill => 'x');

my $f

foreach (qw/File Edit Options Help/) { push (©menus, $f->Menubutton(-text => $_)

)

}

$menus $menus $menus $menus

[3

]

[0] [1] [2]

->pack -side ->pack(-side ->pack(-side ->pack(-side (

=> right => 'left') => 'left') => 'left') '

'

)

MainLoop First a

frame was created across the top of the

window and packed

so

it

will resize

itself dynamically when the window gets larger or smaller. Then the menubuttons were created and packed into the frame. Each of the menus has no items. We'll

leave that as an exercise for the reader.

Dynamic Document List In certain cases, you'll

a

menu

dynamically.

Many

recently

opened and

applications

want to add and remove items from remember which documents you've most

keep them attached something creates a

similar,

to the File

menu

for easier access later. This

but I've simplified the problem

new document name, and



we'll just

we'll display that

example does

have a button

document name

in

that

an entry

237

Complete Menubutton Examples

widget so

#

we know which one we

are editing. Using our

methods from the menu widget,

select !

we

menubutton and

can create a solution

a

like this:

/usr/bin/perl -w

use Tk; $inw = MainWindow->new; $mw->title "Documents" (

)

Create a frame for our menubar across the top of the window $f - $mw->Frame{ -relief => 'ridge', -borderwidth => 2) -expand => 1, -fill -> 'x'); ->pack(-side => 'top', -anchor => 'n' #

,

Create the memibutton, with two items: New Doc and a separator $filem = $f->Men-ubutton(-text => "File", -tearoff => 0, ["command" -> "New Document", -menuitems => -command => \&new_document]

#

[

->pack{-side => 'left'); We will open docijment 1 to begin with, and we want to limit the number # of documents in our list to 0-9 {leaves 10 docs max in menu) $doc_num = 1; $doc_list_limit = 9; )

]

#

Create button that will do the same thing as the New Document menu item $mw->Button(-text => "New Document", -command => \&new_doc\jment) ->pack(-side => 'bottom', -anchor => e # The entry will display the current doc we are "editing". $entry = $mw->EntrY( -width => 80) ->pack( -expand => 1, -fill => 'both'); #

'

'

)

MainLoop;

Creates the next doc in line, incs the doc coionter Adds the new doc to the menu, and removes any docs from the # menu that are over the limit (oldest out first) sub new_doc\jment { my $name = "Document $doc_num" $doc_num++; # #

push (©current, $name) $filem->command( -label => "$name", -command => \&select_document, $name [

&select_doc;mient ($name) if

} }

;

($#current > $doc_list_limit) $filem->menu->delete(2) shift (©current)

{

]);

few

)

238

Chapter 11: Menus

sub select_document { iny ($selected) = @_; $entrY->delete(0, 'end'); $entry->insert 'end' "SELECTED DOCUMENT: $selected" (

,

Figure 11-15

shows what our window looks

like after

we've created three documents:

[selected DOCUMENT: Document 3

New Document Figure 11-15. Example of Document History

window

The Menu Widget when you

There are times

won't want to use a menubutton widget. Perhaps you

some menus that will cascade from your menubutton. You still need need to create the menus. You might also think of a way to use a menu that doesn't involve a button. For example, you could set up your application so the user right-clicks on a widget' and a related menu pops up, allowing the user to to create

change configuration options. It

is

also a

whether

it's

good idea a

to

be

familiar with the

menu widget by

itself

or the

methods

menu

for manipulating a

menu,

attached to a menubutton.

Creating the Basic Menu To

create a $inenu =

menu

widget, invoke

$parent->Menu options) (

The menu widget

is

menu

$menu->post

(

...

)



menu:

on which one of the geometry managers post directive:

is

displayed to the user via a

;

Different arguments sent to is

is

the desired parent of the

;

the only widget

not used directly. The

method

Menu from

post

will

determine

discussed later in this chapter.

Use "" with bind.

how

the

menu

is

displayed. This

The Menu Widget

Menu

239

Creation Options

As with any widget, there are options behaves.

Many

ton widget portion of the chapter, so aren't available with the

The following

is

a

list

how

that affect

I'll

menu widget

-activebackground =>

looks and

discussed in the menubut-

only cover those that perform actions that

menubutton widget or whose actions

of the options available for the

Sets the color of the

the

menu widget were

of the options for the

menu

are different.

widget:

color

background behind the

active

menu

item.

-activeborderwidth => amount Sets the

width of the edges of the active

-activeforeground =>

item's border.

color

menu

Sets the color of the text in the active

-background =>

menu

item.

color

Sets the color of the

background of the

entire

menu.

-borderwidth => amount Sets the

width of the menu's edge.

-cursor => cursomame Sets the cursor displayed

-disabledforeground =>

when

the

mouse

cursor

is

over the menu.

color

Sets the color of the text of

any disabled menu items.

-font => font Sets the font of the text displayed in the

menu.

-foregro\and => color Sets the color of the text in the

-menuitems => Defines a

list

menu.

list

of items to create in the menu.

-postcoitimand => callback Sets the callback that

-relief => 'flat'

-selectcolor =>

invoked before the

'groove'

|

Sets the relief of the

is

'raised'

|

is

posted to the screen.

'ridge'

|

'sunken'

edges of the menu.

color

Sets the color of the selection

-takef ocus =>

|

menu

|

1

|

box

in

checkbutton or radiobutton items.

undef

Controls the ability to use the keyboard to traverse the menu. Default

-tearoff =>

|

1

Determines whether or not the item. Default

is 0.

is 1.

menu

will contain the tear-off item as the first

240

Chapter 11: Menus

Menu

Style

The edges of the menu default to 'raised' with a -borderwidth of 2. This makes the menu look like a large button with multiple items of text listed in it. We can change the look of the menu edges by using the -relief option: -relief => 'flat'

The menus screen. The

'groove'

in Figure 11-16

actual

|

'raised'

|

'ridge'

'sunken'

|

were created and then torn

menu edge

inside the

is

off so they are left

window manager's

on the

decoration.

^ Ktenu wAidge

Menu

Itemi

Itemi

itemi

itonl

Itemi

ItemZ

ItemZ

itemZ

ItomZ

ItemZ

Item 3

Item 3

1

Items

Items

Items

Item 4

Item 4

1

item 4

Item 4

Item 4

Menu

1

Menu

w/flat

\Aetm

w/ltrised

Figure 11-16. Different relief options with

The width of the menu's edges the -borderwidth option:

w^roove

menu

w/sia)i(en

widget

(regardless of the

-relief) are changed by using

Changing the -borderwidth always makes the

different relief types stand out

-borderwidth => amount

more, as shown

1

Menu w/groove

Menu w/k^sed

MenuwAWge

Memiwlsunten

Itemi

1

Itemi

Itemi

Itmil

Itemi

ItemZ

1

ItemZ

ItemZ

ItemZ

ItemZ

Item 3

1

Item3

Item 3

Items

Items

Item 4

1

Itan4

Item 4

It«n4

Item 4

Menu

Figure 11-1

in Figure 11-17.

7.

w/flat

Menus

fi

with different relief options

The -activebordeirwidth option mouse cursor over it):

and -borderwidth

affects the active

menu

set to

4

item (the one with the

-activeborderwidth => amount

Menu Fonts and Cursors The

font of the text displayed in the entire

option: -font => font

menu

is

controlled with the

-font

The Menu Widget

241

shows

Figure 11-18

a

menu

with a different

"lucidasans-14". Fonts

font,

can be used for the value of -font were covered

in

Chapter

that

3.

Menu w/groove Item 1 Item 2

Item 3 Item 4 Figure 11-18.

To change

Menu

with a different font

the cursor displayed

when

the

mouse

cursor

is

over a

menu

widget,

use the -cursor option: -cursor => curso2ni.ame

The

default cursor for a

sor.

The

arrow

menu widget is different than the window's menu is 'arrow', whereas the window

default cursor for a

that points the other

is

an

way.

Calling a Subroutine Before Displaying the menu

Before displaying the

default cur-

cursor

(via the

post command

Menu

or a menubutton),

use the -postcoinmand option to specify a subroutine to

you can

call:

-postconimand => callback

The form

for the

callback

(described in Chapter

update the

state of

2).

each

is

the

same

One of the menu item

as

best uses of the -postcoinmand option if

needed. Here

menubutton widget but uses -postcoinmand before

it

is

the one used in a button widget

to

is

an example

perform an update of the

drawn:

Create the menubutton $menub = $inw->Menubutton(-text => "File", -tearoff => 0, -menuitems => [[ 'coinmand' => "Open", -command => \ &do_some thing 'command' => "Save", -command => \ &do_some thing 'command' => "Close", -command => \&do_something]

#

]

[

]

[

[

)

'command' => "Exit",

-command => sub

{

exit }]]

->pack

A flag we use to see if the document has been saved yet. $unsaved = 0;

#

We have to wait \intil after we've created the menubutton to access the menu widget part of it: $meniib->menu() ->configure(-postcommand => \&update_menu)

# #

is

to

that uses a

menu

.

242

Chapter

1 1:

Menus

This looks at some flags in our program and determines if the items should be updated or not sub update_menu { # #

($unsaved)

if

{

$menub->menu->entryconfigure(l, -state => "normal"); else { $menub->menu->entryconfigure (1, -state => "disabled");

}

} }

Specifying Menu Items The -menui terns option allows you to create the menu and the menu items at the same time. The format for doing so is the same as the format for the menubutton's -menuitems option. There

no Addltems method for a menu widget. The Addl terns method is only menubutton widget. You can use either the -menuitems option add method with a menu widget, add is described in the next section.

is

available with the

or the

Menu Indexes Like entry and text widgets,

menu

widgets have their

own

indexing scheme, as

follows.

n

The items in a menu are numbered from to is the first item at the top of the menu, and n is the last item in the menu. (The tear-off item in a menu counts as index if it is present. Use -tearof f => to turn it off.) /t;

"active"

The menu item

that

lighted). If there are '

none

is

currently active (the

no menu items

active,

mouse

is

over

it

and

it

is

high-

then "active" means the same as

'

"end"

The

last

menu

item in the menu.

in the

menu, then

window. This form of index

specification

If

there are

no items

'end' means the same as "none".

"last" Another way to say "end".

"none"

No

item.

The number

is

a

y coordinate

will resolve to the

same

as 0.

menu

in the

item closest to the y coordinate.

"@0" means the

The Menu Widget

243

"pattern"

The

pattern

ing with 0)

There

is

text to

matches

it

aren't really that

are probably

match the menu items is

against.

first

menu

item

(start-

used.

many menu widget methods. The most

entiryconfigure and delete because

than you'll use the others. Remember,

can invoke the

The

menu widget method

if

you

use them more often menubutton widget, you

you'll

are using a

directly

important methods

by using $inenubutton->menu->

method ().

Menu Widget

Configuring the

The cget method returns the current value of an option. It only affects the options for the entire menu; there is an entrycget method that will return information about specific menu items. Both the configure and cget methods are discussed in detail in Appendix A.

Configuring Menu Items The entrycget method queries

a specific

menu

item and returns the information

about that configuration option: $menu->entrYcget (index,

-option);

The index determines which menu item entrycget affects. Any of the options that can be sent with the add method (covered in the following section) are valid. The entryconf igure method returns or alters the configuration options of the menu item at index just as configure does for the entire menu widget: $menu->entryconfig\ire( index,

You can

specify

no options

[-option,

for that

...]);

to get the current configurations for

You can specify a single option to get the value index. You can also specify multiple option/value pairs

index.

at that

value,

all

of the options

of only that option to set the values of

those options for that index.

Adding Items -menuitems option, you can use the add method to add items menu. The first argument to add is the type of menu item to be added. It should be one of the following: "contmand", "radiobutton", "checkbutton", "separator", or "cascade". Here is a usage statement: In addition to the

to the

end of

a

$menu->add( type

[

,

options...

]

)

;

The options that affect each menu item are the same as those for the -menuitems option: -activebackgroimd, -activeforeground, -accelerator,

;

;

;

;

,

244

Chapter 11: Menus

-background, -bitmap, -coinmand, -font, -foreground, -image, -indicatoron, -label, -menu, -offvalue, -onvalue, -selectcolor, -selectimage, -state, -underline, -value, and -variable.

The

results of the following

two code snippets

are identical:

Snippet 1 Using add for menu items $menu = $mw->Menu; $menu->add( "command" -label => "Open", -command -> \&open_file) $menu->add( "command" -label => "Close", -command => \&close_file)

#

#

,

*

,

#Snippet 2 # Sending a list intially using -menuitems option $menu = $mw->Menu( -menuitems => ["command" => "Open", -command => \&open_f ile] [

["command" => "Close", -command => \&close_file] ]); call to add will add another item to the end of the menu. To add a somewhere other than the end of the menu, see the insert method

Each additional

menu

item to

(covered in the next section). Instead of

shown on able need

-text or -textvariable the

option.

menu If

to use the

Inserting

item.

options,

You should

we

notice that

use -label to indicate the text

we

-labelvarimenu item, you will

don't have a

you need to change the text shown in the entryconf igure method (discussed later in

this chapter).

Menu Items

The insert method works exactly the same way the add method works, except the new menu item will be inserted right before the menu item at index. You cannot insert a

menu

always be the

first

item before the tear-off

is

item because the tear-off must

item in the menu:

$menu->insert (index,

Here

menu

type

[,

aptior^

...

]

)

;

an example:

$menu->insert "end"

"radiobutton" -label=>"red"

(

Deleting

,

,

Menu Items

To remove menu

items from your menu, use the

$menu->delete index) (

# or.

)

;

.

$menu->delete indexl (

,

inde?c2)

delete method:

The

Menu

You can

Widget

delete

245^

one item by specifying only one index. You can delete more than a range of indexes. Here are some examples:

one by specifying

$menu->delete( 'last' 'end'); $menu->delete $menu->delete( "Open" )

(

)

deletes the last menu item deletes every menu item (except tearoff) deletes the item that matches "Open"

#

;

#

,

#

;

Invoking Menu Items The invoke method will try to invoke you clicked on it with the mouse):

the

menu

item

at

the specified index (as

if

$menu->invoke (index)

The

specific result of the invocation

The

index.

depends on what type of menu item

from any -coinmand callback associated with

result

that

is

at

index will be

returned by the invoke method. $menu->invoke "red" (

)

Determining Item Type The type method

returns a string that indicates the type of

menu

item located

at

index.

$type = $menu- >type( index)

;

The string returned will be one of the following: "command", "radiobutton", "checkbutton", "cascade", "separator", or "tearoff". $type = $menu->type(0)

;

#

look at index

Translating Index Values The index method

returns the numerical index of the

$menu->index( index)

menu

item

at index.

;

The code $menu->index( 'end' returns 9 if there are 10 menu items in the menu. The code $menu->index("Open" returns the index number of the menu )

)

item that matches "Open".

Displaying a If

you

Menu

menubutton widget to display your menu, you need You can use the post method or the Popup method.

aren't using a

display

it.

a

way

to

The post method displays the menu for you, but the menu only goes away after you select a menu item or specifically call unpost. The Popup displays the menu only while the mouse button is depressed.

;

;

;

246

Chapter 11: Menus

The post method requires x and y coordinates to tell it where to place the menu on the screen. Typically, you call it wherever the user clicked (unless you want it to display in the same place all the time). Here is an example that displays the menu when the user clicks the right mouse button in a listbox: Create a menu with two items for our exairple $menu = $mw->Menu(-tearof f => 0, -menuitems => [['command' => "A"], command' => "B" $lb = $mw->Listbox ->pack # create a binding on the listbox that will display our menu # when we click with the right mouse button $lb->bind("", \&display_menu( Ev('X'), Ev('Y')]); #

[

'

]

]

)

)

(

( )

[

sub display_menu ITT^

($lb,

$x,

)

,

{

$y)

= @_;

$menu->post $x, $y) (

;

}

I

created a simple

menu

some users mouse button to

we can get through the example quickly. I removed menu because I don't like tear-off menus all over the so keep this in mind). The bind is where I mapped the

so

the tear-off item from the

place (but

do,

right

display the menu.

used Ev( "X"

I

)

and Ev( "Y"

to

)

send the

more post with

coordinates of the location in which the user clicked (see Chapter 14 for

information about Ev("X") and Ev("Y")). The subroutine simply

calls

the correct arguments.

The menu will be displayed even when the user lets go of will unpost itself automatically when the user selects a menu Another way to display a

menu

is

played only while the user holds

mouse

the

button.

mouse

button.

It

item.

Popup. This causes the

to use

down

the

To

menu to be dismenu item,

select a

you must click down the mouse button, slide the cursor to the desired item, and then let go of the mouse button. The Popup method can be called with no arguments or with one or two options. The options that affect Popup are -popover and -popanchor. Calling Popup $menu->Popup

like this

( )

menu at the very center recommend that you at least use

displays the

of your entire screen. This

so

the

I

will take either the string

"cursor" or

a

-popover

isn't

very useful,

The -popover option The menu will be cen-

option.

widget reference.

tered under the cursor or centered over the widget; for example: $menu->Popup( -popover => "cursor"); $menu->Popup( -popover => $button) $menu->Popup( -popover => $listbox) ;

;

Notice that

we

#

# #

Center menu under cursor Center menu over $button Center menu over $listbox

are not using the syntax \$listbox. Because our scalars already

contain a reference to a widget,

we

don't

need

to reference

it

again.

The Menu Widget

247

The second option, -popanchor, affects how the menu gets positioned relative to the -popover argument (or the entire screen if -popover isn't specified). The -popanchor option takes a string argument where the string is one of the following: "nw", "ne", "sw", or "se". For instance, if you would like to display the menu's upper-left corner where the user clicks, use this code: $menu->Popup( -popover => "cursor", -popanchor => "nw");

This

how

is

I

the complete

menus

like to create right-click

example

in the "Right-Click

that are associated with widgets.

Menu

See

Example."

Displaying a Cascading Menu If

your

play

menu

menu

has a cascading

associated with

it,

use postcascade to

dis-

it:

$menu->postcascade( index)

The postcascade method cade

menu

index other

will

unpost any other submenu and then post any cas-

menu

associated with the

item located

at

index.

If

the

menu

not a cascade item type, then the only thing that happens

is

submenus

item

that

is

are unposted.

$menu->postcascade

Undisplaying a

(

suianenu"

"

)

;

Menu

you have displayed the menu on the screen using post, you can use unpost remove it from the screen: If

$menu->unpost

to

( )

unmap $menu from the window. If any cascaded menus be unmapped as well.

This will

at

any

of this

menu

are

also displayed, they will

Getting the Position of an Item The Yposition method topmost pixel of the

returns a decimal string that gives the

menu

item

at

y coordinate of the

index:

$location = $menu->Yposition index) (

Right-Click

Menu Example

There are times appears

A

you'll

when you

canvas

is

want

right-click

to use a right-click

on

menu, which

a perfect place to use a right-click

menu; there

ferent possible actions to take that associating different

of objects in the canvas

is

is

a

menu

that

a particular widget or location in the application.

advantageous.

are often so

menus with

many

dif-

different types

;

248

To

Chapter 11: Menus

create a right-click

desired,

menu widget, add the items to it as make the items perform useful tasks. To right-clicks on the desired object, use the bind

menu, simply

create a

and use the -coinmand option

menu when

display the

the user

to

command: $object->bind( ""

You can use

a right-click

,

menu

sub

{

$menu->Popup -popover => 'cursor'); (

}

)

with a listbox to allow users to delete or edit the

currently selected item.

Optionmenu Widget JiQm>mmii -H^i optionmenu

-

|

The optionmenu

cally sets the

a specific implementation of a

is

g^^ jj^^ difference

between the two

-indicatoron option

handles the display of the

menu

to

1,

that the

removes the

in a slightly different

You can use an optionmenu when you want want

several different items but don't

or with several radiobuttons.

is

To add

to

tear-off

menu

item,

and

way.

to give the user a choice

between

waste space with a listbox and scrollbar

items, use the

-menui terns or the other methods

menubutton wid-

optionmenu automati-

that

-options command

allowed you to add to a

instead of

menu

or

menubutton.

Creating

and Configuring an Optionmenu

The optionmenu

is

Optionmenu method:

created by using the

$optioninenu = $inw->Optionmenu

(

...

)

;

with a menubutton widget are also available for optionmenu widget. The following options are specific to the optionmenu:

All the options that are available

the

-textvariable, -options, -variable, and -coinmand.

-menuitems option or other methods to add items to an optionmenu, use the -options option. It takes an anonymous list that can contain either strings or other anonymous lists. The idea behind an optionmenu is to select one item from a list of items. The text displayed is the currently selected menu item. The -textvariable option determines where the displayed text is stored. There is also a -variable option, which you can use to store a value that is different than the one shown on the menu. Specify the displayed value and the stored value by using the -options option. If the displayed value is the same as Instead of using a

the stored value, use a simple

-options =>

[1,

2,

3,

4,

list:

5,

6],

-textvariable => $nvmiber

249

Optionmenu Widget

To

store a value other than the

-options => [["one",!],

one shown, use

["two", 2],

this

code:

["three", 3], ["six",6]],

["four", 4], ["five", 5], -textvariable => $di splayed, -variable => $number

words are displayed

In this example, the written

$displayed), and the stored value

(in

in the

menu

(and are stored in

$nuinber) are the integers. The nondis-

played value can be any scalar value.

The

-cortiinand option assigns a callback that will

be executed when a selection

has been made. The default arguments to the callback are the variables assigned with -textvariable and then -variable

(if it exists).

You can use

callbacks to

perform an action based on the item selected from the optionmenu. Here's a complete script that will allow you to see most of the optionmenu's useful features: #

!

/usr/bin/perl -w

use Tk; $inw =

MainWindow->new;

$ir[w->title "Optionmenu" (

)

;

$display_var = "ten"; $niw->Optionmenu( -command => sub { print "ARGS: @_\n"; print "in optioranenuNn" -textvariable => \$display_var, -variable => \$stored_var, -options => [["ten", 10],

;

},

"twenty", 20] ["thirty ",30]] [

)

->pack

( )

MainLoop; It's

a

good

idea to also create a label widget so the user

menu's purpose (shown

is

aware of the option-

in Figure 11-19).

Figure 11-19. Optionmenu with a label widget to the

left

The only methods available with the optionmenu are the cget and configure methods. The cget method returns information about an option in the optionmenu. The configure method can get or set option values for the optionmenu widget. Both cget and configure are covered in detail in Appendix A.

Chapter 11: Menus

250

Fun Things Create one click

on

get will

menu

to Try that has

a widget, the

two

menu

items: Disabled

will

pop

up.

If

and delete all

select

be disabled. Selecting 'Normal' reenables

Create an application with two menubuttons.

Take

and Normal.

you

different types of

menu

menu, with an

right-

that

wid-

that widget.

Have

the items

on the

first

add

items to the second menu.

the fun things from previous chapters

least a File

When you

'Disabled',

Exit item.

Be

and add menus

inventive!

to them.

Add

at

Frames

A

frame widget

is

other widgets to

a boring widget at

sit.

This doesn't

first

seem

glance. All

it

important, but

it

does is.

is

provide a place for

The geometry managers 2, Geometry Manage-

provided with Perl/Tk have some limitations (see Chapter

we

ment), and

can use frames to help them do

our example geometry manager throughout

most popular, but remember geometry managers as

A

this

their jobs better. We'll

chapter because

that the basic rules for using a

it

use

seems

pack to

as

be the

frame apply to the other

well.

is to contain other widgets, accommodating the size of the you don't have any widgets packed into the frame, you won't the widgets inside the frame are resized for any reason, the frame

frame widget's job

widgets within. see the frame.

If

If

will try to resize as well (either larger or smaller).*

Creating a

Frame

Use the parent widget of the frame $frame = $parent->Fraine

(

[

to invoke the

option => value,

Frame

( )

method:

])->pack();

...

MainWindow, a toplevel, or another frame widget.t After the frame is created, it can become a parent to other widgets. You must have created the frame but not necessarily packed it on the screen for it to be the parent

The $parent can be

a

*

You can change

t

Technically, any widget can be a parent of another widget, but

comes

this

behavior by using packPropagate

( )

or

gridPropagate I

like to

( )

make my

life

easier

when

it

widget inside the window. If I made a frame the child of a $button, I wouldn't be inside the button. I would then have to use the -in option with pack, confusing myself

to placing the

able to pack

it

even

Keep

further.

it

simple,

and

you'll

be much happier.

251

.

252

Chapter 12: Frames

Keep in mind that, even if you pack other widgets inside your you don't pack the frame as well, the other widgets won't show on the

of other widgets. frame,

if

screen. Just as with

method

all

the other widgets in Perl/Tk, the options specified in the

change

will

how

window. There

the frame looks inside the

options available with the frame widget, and they aren't complicated section covers

-background =>

at all.

This

and what they do.

the options

all

Frame few

are

color

Sets the color of the frame's

background area (there

is

no foreground

area).

-borderwidth => amount Sets the

width of the frame's edges. Default

is 0.

-class => classname Indicates the class associated with the frame in the option database. This

option can actually be used on any widget, not

-colormap => "new" Specifies

whether to use

TkS.O only.

|

frame.

$window

|

the application. Default

-container =>

just a

a

is

new colormap

or share one with another widget in

undef

1

If true,

this

frame

will

when

the

be used to contain another embedded

application.

-c\irsor =>

cursomame

Changes the cursor

to use

mouse

pointer

is

over the frame.

-height => amount Sets the starting height of the

-highlightbackgroimd =>

frame

in a valid screen distance.

color

Sets the color the highlight rectangle should

be when the frame does not have

keyboard focus.

-highlightcolor =>

color

Sets the color the highlight rectangle should

keyboard focus. Default color

is

be when the frame does have the

black.

-highlightthickness => amount Sets the thickness of the highlight rectangle. Default

-label => labelstring Adds a label to the Frame with the

-labelPack => Specifies

[

pack options

pack options

text "labelstring".

]

for the label.

is 0.

Frame Style

253

-labelVariable => \$variable Specifies a variable that contains the text for the label.

-relief => 'flat' 'groove' 'raised' 'ridge' 'sunken' 'solid' Changes the appearance of the edges of the widget. Default is flat |

|

|

|

|

'

'

-takefocus =>

-visual =>

When

|

1

|

undef

whether the frame should take the focus. Default

Specifies

"

is 0.

type #"

used on an

X Windows

system, changes the depth of colors available to

your application. Does nothing on Win32 systems.

-width => amount Sets the starting

Frame

width of the frame

in a valid

screen distance.

Style

you can use the -relief and -borderwidth options to change how the edges of a frame widget are drawn. The default -relief is flat and the default -borderwidth is 0. If you want the frame to have any edges at all, make sure you change -borderwidth to something higher than 0. Unless you put something in a frame, you'll never see it. So, for the examples in

As with

all

widgets,

'

'

,

Figure 12-1,

I

have inserted a label widget and an entry widget

of that frame. Note that

I

that state the relief

by using Label

actually created a label widget

and did

( )

not use the -label option (see the next section).

^ gd,,-,v:,,:»m^Pii^rtes

Frame

^Jiia

—_—

exaori^tes

-

J

iiai:

flat:

»

—__™.

...™—_™.

.

groove:

graove:

| j

raised:

raised: ridge:

sunken:

\

1

ridge:

i

|

|

^

sunken:

^

Figure 12-1. Different relief values forframes; borderwidth of 2

window.

which frame is "groove" to my

of 5

is a great way to find out where your frame is you have a complicated window, it's confusing to remember where. I'll often add -borderwidth => -relief => 5, Frame command to find that frame in the window.

Using -relief and -borderwidth in the

and borderwidth

If

254

Chapter 12: Frames

Adding a Label

a Frame

to

With Perl/Tk, you can add a label to your frame by using the -label option, which takes a text string as an argument: $inw->Fraine( -label =>

"My Frame:

")

->pack;

configure label in frame later $frame->configure( -label => "My Frame:

#

By

:

default, the label

placed

is

(see Figure 12-2). Again,

I

at the

")

top of the frame, centered across the width

put something in the frame so you can see the frame as

well as the item in the frame. In this case,

options in the frame.

-borderwidth =>

I

->pack;

I

placed a button with the default pack

also created the frame with

=>

-relief

'groove',

you can see the edge.

2 options so

-J B'aufne exsn^ite

^

jj

Frame Label !

Figure 12-2.

Frame with

You can change option.

It

in

frame

label in default position

by using the -labelPack where the array contains any

the location of the label inside the frame

anonymous

takes an

pack options

Button

array as an argument,

for the label:

-labelPack =>

-side => 'left', -anchor => 'w']

[

Be careful to notice that this option has an uppercase letter in it. If you try to use -labelPack without the capital "P," you'll get a compilation error. Also notice that there isn't a -labelGrid option available. You must use pack() to put widgets inside your frame if you are going to use the -label option. If you don't, bad things happen (your application might not run at all). Instead of using a static text string with your frame's label, you can assign a variable by using the

-labelVariable option

(again, notice the capital V):

-labelVariable => \$label_text

When you change frame

The

will

the contents of the variable $label_text, the label in the

change as

instant

well.

you use the -label or -labelVariable option,

You can use these $frame->configure( ...

placed inside the frame. call

or later with

placed above

all

a label

options either in the )

other widgets inside the frame.

.

If

you use them

is

created and

initial

later,

Frame ()

the label

is

255

Colormap Complications

Frames Aren Y Interactive The frame widget itself is not interactive; by default, it can't accept input from the user. The widgets inside it can, but the frame cannot. As always, the focus ability is controlled by the -take focus option: -takefocus =>

With a frame widget, the user

it

set to 0. If for

is

on your frame, you

will

need

to

some reason you need to get input from => 1. it to -takefocus

change

Colormap Com^plications when you you'll

are running several applications at

sometimes notice

that the colors

once and you

become

an application to the browser, the colors

corrupted.

start a

web

When you

browser,

switch from

your other applications suddenly

in

you switch back from your browser to an application, the browser colors change. This is happening because the web browser is a color hog. It has requested more colors than the operating system can allocate at once. The OS must alter the colormap between applications to allow the active application to change.

If

use the colors

way

to

it

wants to use. The colormap simply gives the operating system a

keep track of

who

is

using which colors.

Perl/Tk applications can have

make each button

many

—you

colors too

can get color-happy and

a different color of the rainbow. This can cause problems

there are other applications running that

want

applications are color hogs, Perl/Tk will switch to black-and-white

don't like

behavior,

this

-colormap

you can use the -colormap option

word "new"

takes either the

given "new",

it

will create

its

own

that

is

the

-visual

or a reference to another

colormap.

When

for

If

you

override

window.

it.

If

you use -colormap with is

one

catch,

option.

The -visual option takes number;

mode.

to

another window, the two windows will share the colormap. But there

and

if

a lot of different colors too. If other

as

an argument a

string that contains a

keyword and

a

example:

-visual => "staticgrey 2"

The keyword can be any one of the following: staticgrey, greyscale, staticcolor, pseudocolor, truecolor, or directcolor. The number indicates the depth of color used (2 = black/white).

When you

use -colornnap to share the colormap between two windows, the -visual option for both must be the same. This means that -visual must be imdef for both (the default) or it must have the same value. Neither -colormap nor -visual can be altered by using the configure method.

256

Chapter 12: Frames

You

will see

both -colorroap and -visual options

gets, also.

We

est, you'll

probably never use either option

covered

it

here

first

because

this is

in

Chapter

where we see

13,

Toplevel Wid-

it first.

To be hon-

in either widget.

The Magical Class Option You can

force your frame to be in another class (besides frame)

option. Simply give

it

a string that

is

by using the -class

a unique class identifier;

-class => "I^frame"

For more information on using classes (and what good they can do you), see

Chapter

13-

Frame Methods The only methods These are described

available with the frame widget are in detail in

Appendix

cget and configure.

A, Configuring Widgets with configure

and cget.

Fun Things

to Try

When you

use the Scrolled method, you are using frames without even knowThe newly scrolled widget is placed inside a frame with its scrollbars so that behaves as one contained widget. Here are some other ways you can use

ing it

it.

frames: •

Create several lines of labels with entry widgets. Each

own •

frame so

it

will

look

'line'

needs

to

be

in

its

right.

Place an image along one side of your application window. Put the widgets in a

frame (on the

left

or

on the

right)

and place the image on the other side of

them. •

Place a scrolled listbox in your application window, a frame containing three

buttons (OK, Cancel, Apply) along the bottom of the window, and a frame

along the right containing two buttons (Delete, Add) that manipulate the

list-

box. By using frames, you can keep the buttons that belong together in one area

instead

purpose.

of grouping them with other buttons that serve a different

Toplevel Widgets

Any Perl/Tk application includes at least one toplevel widget. When you call the new method from the MainWindow class, you are creating a toplevel widget withYou can create other toplevel widgets to be used in your out even knowing application in addition to the MainWindow toplevel widget. The MainWindow is Other special because it automatically displays when you call MainLoop toplevel widgets in your program must be explicitly displayed somewhere in the it.

{ )

.

code.

Here are some examples of

how you

can use toplevel widgets:



Display informational text with a Close button.*



Provide data gathering that

triggered

is

by something the user does

(for

exam-

ple, clicking a button).

All toplevel

widgets have the same behavior: Each has decoration that

tent with the

system on which your application

is

run.

is

consis-

Each toplevel can contain

other widgets and/or multiple groups of widgets (for example, they can be

grouped

The

in a

frame widget).

rest of the

chapter will cover

how

to use toplevel widgets

and what options

allow you to change their behavior.

Creating a Toplevel Widget To create a toplevel, call Toplevel from the desired MainWindow widget (you already know that to create

Look

at

Tk::Dialog.

It is

designed to do

this

and uses

parent widget, usually the a

main window, you must

a toplevel widget.

257

;

;

;

;

258

Chapter 13: Toplevel Widgets

use MainWindow->new{)). The returned item

place items within

is

a reference to the toplevel wid-

allows you to configure the widget,

get; the reference

it.

Here

(

)

it,

and

;

$inw->Button(-text => "Toplevel",

MainLoop sub do_toplevel { if (! Exists ($tl))

methods on

a simple example:

is

use Tk; $raw = MainWindow->new; $inw->title "MainWindow"

call

-command => \&do_toplevel) ->pack()

;

{

$tl = $inw->Toplevel ; $tl->title( "Toplevel") $tl->Button(-text => "Close", { )

}

-command => sub else { $tl->deiconify() $tl->raise()

{

$tl->withdraw

)

}

->pack;

}

}

When you

run

program, clicking on the Toplevel button in the main

this

creates the toplevel widget

toplevel from view.

show want

it

You need

it

needs

to)

and displays

show something

the Close button

is

it.

window

Clicking Close hides the

to test for the existence of the toplevel before

because you don't want to re-create

to try to

When

(if

it

if it

you

already exists and you don't

that doesn't exist.

clicked, the toplevel

is

withdrawn.

It still

exists;

it

is just

not visible to the user. This saves time the next time around by redisplaying the

same window. You can also use withdraw if you don't want to show the toplevel while you are filling it with widgets. Simply use the withdraw method, place the interior widgets, and then redisplay the widget by using deiconify and raise. These options can be specified

in the call to

Toplevel

or by using the

configure

method.

-background => Sets the

color

background color of the toplevel widget. Note

may be hidden by

widgets placed in the toplevel

if

that the

the toplevel

is

background completely

covered by widgets.

-borderTvidth => amount Sets the

width of the border around the toplevel. Default

is 0.

-class => classname Sets the classname

used with the option database

for this toplevel widget.

259

Creating a Toplevel Widget

-colormap => "new" Specifies whether

$window

|

to use a

the application. Default

-container => TkS.O only.

-use

|

is

new colormap

or share one with another widget in

undef

1

If true, this

window

will contain

an embedded application (see the

option).

-cursor => cursomame Sets the type of cursor

used over the toplevel widget.

-height => amount Sets the height of the toplevel.

-highlightbackground =>

color

Sets the color the highlight rectangle

should be

when

the toplevel does not

have focus.

-highlightcolor =>

color

Sets the color the highlight rectangle should

be when the toplevel does have

focus.

-highlightthickness => amount Sets the thickness of the highlight rectangle. Default

is 0.

-menu => $inenu TkS.O only. Indicates that the toplevel uses the

menu

in

$menu

across the top

of the window.

-relief => 'flat' 'groove' 'raised' 'ridge' 'sunken' 'solid' Changes the appearance of the edges of the toplevel. Default is flat |

|

|

|

|

'

'

-screen => screenname Sets the screen on which

to place the toplevel.

Cannot be changed by config-

ure method.

-takefocus => Determines

if

|

1

|

undef

toplevel can have keyboard focus. Default

is 0,

meaning

it

can-

not have keyboard focus.

-use => $windowid TkS.O only. $windowid must contain a hex string of the window the toplevel. The -container option must have the value 1

to

embed

in

to use this

option.

-visual =>

When

"

type #"

used on an

X Window

System, changes the depth of colors available to

your application. Does nothing on Win32 systems.

-width => amount Sets the desired

width of the toplevel.

260

Chapter 13: Toplevel Widgets

Toplevel Methods The methods

available with the toplevel widget are listed

lowing sections

Window as seen many

(it is

important to note that

all

and explained

in the fol-

of these methods apply to a Main-

Main Window is just a specialized toplevel widget). You haven't them before because toplevel is a different sort of widget than the others covered so far in this book. Also keep in mind that a lot of these methods were designed originally for use with a Unix windowing environment, and quite a few of them will state "No effect in Win32 system." Many of these functions serve no useful purpose to the typical ordinary Perl/Tk application, but I'll document them here for thoroughness. well; a

of

methods here

Several of the like

with If

window manager properties, which

alter

often look

WM_PROPERTY_THING. These properties are also traditionally associated the X Window system on Unix, but some still apply in Win32 systems as well.

a specific

method doesn't say anything about which system it applies to, it If it only applies to one or the other (or only half-works in one

apply to both.

will

sys-

tem), this will be mentioned as well.

Configuring a Toplevel Both cget and configure methods are used to toplevel widget. See

Appendix A

for

more

set

and get option values

detailed information

on how

for a

to

use

these methods.

Sizing a Toplevel You can use

the

geometry method

geometry string determines the

The geometry glance,

it

geometry -^=7

is

string

is

a

geometry

window on

string.

Here

is

A

the screen.

concept that originated on Unix systems, and

a

a bit cryptic.

to define or retrieve a

and placement of

size

at first

a regular expression that describes a complete

string:

(\d+x\d+) ?([+-] \d+ [+-] \d+) ?$

The equal (\d+x\d+)

sign can be omitted completely (and usually is

the width

and height

(in that order)

is).

The

first

portion

separated by an x. Both width

by default and in grid units if the window is gridded with the grid method (described later). The last portion of the geometry string represents the x and y coordinates of the location in which the toplevel should be and height are specified

in pixels

placed on the screen. Both x and y are always in pixels. Here are a few examples of

what some geometry 300x300 300x450 300x450+0+0 300x450-0-0

# # # #

strings

look

like:

width and height both = 300 width = 300, height = 450 width - 300, height = 450 placed in upper left comer width = 300, height = 450 placed in lower right comer

261

Toplevel Methods

300x450+10+10

width = 300, height = 450 placed 10 pixels out from upper left comer window is 'natural' size, placed in upper left comer

#

#

+0+0

#

When geometry

no arguments, the current geometry string is returned. You can also specify a new geometry by using geometry with the new geometry string as the argument. To set the size and position of the window immediately, you would do this: is

called with

MainWindow->new(

$inw =

)

;

$ir[w->geometry( "300x450+0+0")

;

you specify only the width and height, the placement of the window is determined by the window manager. If you specify only the positioning, then the size of the window will be determined by the widgets placed within the toplevel, but the window will be placed at those x and y coordinates. If

You can

force the

empty geometry

window back

to

its

natural size

by

calling

geometry

(

)

with an

string:

$toplevel->geometry

(

" "

)

Maximum Size You can use maxsize

to restrict the largest size of the

window.

It

takes

two

inte-

gers as arguments, as follows:

$toplevel->maxsize(300, 300) If

you

call

maxsize without any arguments,

with two items in

empty

it

an empty

representing the current values. Calling

string or a

list

maxsize with two

strings cancels the limitation.

Minimum

Size

You can

also restrict the smallest size of the

dow

always be

will

at least

and height

eliminate the

minimum

using minsize. The win-

;

minsize without arguments

the width

window by

the size specified:

$toplevel->minsize(100,100) Calling

you'll get

an empty string or a list containing minsize with two empty strings will

will return

respectively. Calling size restriction.

Limiting Resizing You can

control whether a

window can be

resized in width and/or height

using resizable: $toplevel->resizable 1 ($canwidth, $canheight) = $toplevel->resizable() (

,

)

;

by

,

262

Chapter 13: Toplevel Widgets

means it is resizable, and means it is nonresizable in the specified you don't specify any arguments, resizable returns a list with two items. The first item is a 1 or and indicates whether the width is resizable. The second item is a 1 or and indicates whether if the height is resizable. By default, Specifying

1

direction. If

a

window

resizable in both directions.

is

Using a Size Aspect You can use

the

aspect method

window

to force the

to stay a certain

width and

height:

$toplevel->aspect

(

[

minN, minD, maxN, maxD

])

;

The aspect method does some very subtle things, and you'll probably never use it. If you do, play around with different values (starting with the example below) to get the effect you want.

When you

use the aspect method with no arguments,

no

string (if there are

constraints to the aspect of the

returns either an

it

window)

empty

or an array contain-

ing four elements: ($miriN,

$miriD,

$iTiaxN,

Using these values, you can see ($minN/$mirLD)

You can

also

= $toplevel->aspect;

$maxD)

how aspect

< width/height
aspect

(1

2,3,1); the

effect

is

on the win-

subtle.

Setting the Title You can change

the text across the top of the

window by

using the title

method: $toplevel->title("This will be the title");

Pass a string in with title and the

dow, assuming the window

is

new

title

will

currently visible.

If

appear immediately

in the

win-

you don't pass an argument with

title string is returned. For the X Window System, the default window is the name used to run the program, and the first character of name is uppercase. For Microsoft Windows, the title always starts out as

title, the current title

the

of a

Toplevel.

Showing the Toplevel The deiconify method causes ifies

it

immediately

if

the

the toplevel to

window

be displayed noniconified or deicon-

has already been displayed once.

If

the

window

263

Toplevel Methods

has been withdrawn, a $toplevel->raise() must also be done to correctly display the window.

The raise method brings the toplevel to the front of all dows in the application if you call it with no arguments: $toplevel->raise

You can

(

)

also put the toplevel in front of another toplevel:

$toplevel->raise $other_toplevel (

It is

the other toplevel win-

sometimes necessary

show up on

to

)

use both deiconify and raise to get the

window

to

the screen.

Withdrawing the Toplevel When you

window, it is a good idea to make it invisible while you with widgets. You can do so by using the withdraw method: create a

$toplevel->withdraw(

it

)

window is already visible, withdraw will make about the window until it has been deiconified. If

fill

the

the

window manager

forget

Iconifying the Toplevel The iconify method

forces the toplevel into iconified form:

$toplevel->iconify() Iconifying will not

is

not the same as withdrawing the window; withdrawing the

show an

icon on the desktop.

Specifying the Icon In the Unix

window

X Window

Bitmap

System,

when you iconify your application, it is repreYou use the iconbitiinap method to specify

sented on the screen with a bitmap. this

bitmap: $toplevel->iconbitmap() $toplevel->iconbititiap "bitmap" (

)

;

same form the -bitmap option supported by the button widget (see Chapter 3, The Basic Button). Calling iconbitmap with no arguments returns the current bitmap or an empty string. Calling iconbitmap with an empty string removes the current bitmap. It

takes a bitmap in the

On Win32

systems, the application

Tk icon and the name of Win32 system does nothing. able

is

kept in the

Start

taskbar with an unchange-

the application. Using the iconbitiinap

method on

a

;

;

;

;

;

264

Chapter 13: Toplevel Widgets

Specifying the Icon

A mask

this will

specified from a

file

X Window

only work with

or a default bitmap

name

Systems). (see

It

also takes a bitmap

-bitmap documentation

in

Where the bitmap mask has zeroes, no part of the normal icon bitmap be displayed. Where the mask has ones, normal icon bitmaps will be displayed.

Chapter will

bitmap can be specified by using the iconmask method

for the icon

(remember,

Mask

Calling string

3).

iconmask with no arguments returns the current bitmap mask or an empty no bitmap is being used. Calling iconmask with an empty string unsets

if

the mask: Scurrentinask = $toplevel->iconiTiask()

$toplevel->iconmask( "bititiapname" $toplevel->iconmask{ " ")

Setting the

displayed

empty

;

get the mask set the mask # unset the mask # #

;

Name of the Icon

The iconname method is

)

when

sets or returns the current text associated

the application

is

iconified.

You can

with the icon that

pass in a

new

string or

an

string:

$toplevel->iconname "newname" $current_name = $toplevel->iconname() (

)

you don't specify an argument at all, iconname returns the current iconname or an empty string. You can query and set the iconname on a Win32 system, but it doesn't do anything. This is a method that is used on the X Window System only. If

Setting the Icon Position The iconposition method suggests to the X Window System manager where icon should be placed on the desktop when the application is iconified: {$x, $y) - $toplevel->iconposition( $toplevel->iconposition($x, $y) If

X and y

X and

y. If

aren't specified, a

you

find

returned containing only two items, the current

iconposition with two empty the window manager is cancelled.

strings

(one for each x and

y),

Window Instead of an Icon

window) instead bitmap for an icon. Specify the widget by using the iconwindow method. To out what the current widget is, call iconwindow with no arguments (an empty

Some systems of a

)

call

the suggestion to

Using a

list is

the

(not

Win32) support the idea of using

a widget (or

265

Toplevel Methods

string

is

returned

string instead of

if

there

$widget

no associated $widget). You can specify an empty by using a widget for the icon:

is

to cancel

$currentwindow = $toplevel->iconwindow( $toplevel->iconwindow($window) $toplevel->iconwindow( " "

)

;

get set # imset #

#

)

Determining the State The state method

returns

one of three

strings:

"normal", "iconic", or "with-

drawn". $state = $toplevel->state(

The

)

string indicates the state of the

window when state

name

assigned to

returns an

called.

Name

Assigning an Application The client method

is

empty

string

if

your application doesn't have a

it.

$toplevel->client $toplevel->client "name" $naine =

);

{

(

)

To

assign a name, send a string to the

toplevel widget.

You can use

this in

client method

an .Xdefaults

file in

after

the

you

create your

X Window

System to

assign colors to your application.

Window Properties window properties: WM_DELETE_ WINDOW, WM_SAVE_YOURSELF, and WM_TAKE_FOCUS. The callback (if any) associated with each property will be invoked when the window manager recogThe protocol method

controls the following

nizes the event associated with the property:

$toplevel->protocol

(

[

property_name]

[ ,

callback

]

)

;

The WM_DELETE_WINDOW property callback is invoked when the window has been deleted by the window manager. By default, there is a callback assigned by Perl/Tk that destroys the window. If you assign a new callback, your callback will be invoked instead of the default callback. If you need to save data associated with that window, do so in the callback and then invoke $toplevel->destroy() to mimic the correct behavior afterward.

The other two

much

less

properties,

commonly

tems but not

in

WM_SAVE_YOURSELF and WM_TAKE_FOCUS, WM_TAKE_FOCUS is used in Unix

used. Eor instance,

Win32. The presence of these properties

window system you

are running.

If

your application

will

is

are sys-

dependent on the

be running on multiple

systems, don't expect these properties to always be available.

To

find out

if

they

;

266

Chapter 13: Toplevel Widgets

one

are available, assign each

application to see If

the

if

a callback that

print

is

does

a

print and

mn

the

you leave out the callback when you use protocol, the current callback

assigned to that property will be returned (or an empty string rent callback assigned).

You can remove

instead of the callback.

If

of

then

ever invoked.

all

if

there

isn't a

cur-

by sending an empty string specified, the method returns a list

the callback

neither argument

is

properties that have callbacks assigned to them.

Colormap Property The colormapwindows method This property

erty.

is

used to

the

affects

talk to the

WM_COLORMAP_WINDOWS

prop-

window manager about windows

that

have private colormaps. Using colormapwindows with no arguments returns a of windows.

The

colormap than

list

contains

windows

pass a

have

list

a different

their parents:

ilist = $toplevel->colormapiwindows

You can

(in order of priority) that

list

of

windows

( )

;

colormapwindows

to

as well:

$toplevel->colormapwindows (©list) If

you don't use

this

function at

all,

Perl/Tk will take care of everything for you,

although the order of the windows might be different.

The

Command Property

The command method (not

to

be confused with the -command option used with

most of the widgets) controls the

'WM_COMMAND

arguments, command returns a

reference:

list

$listref = $toplevel->conimand()

The

list

holds the words of the

property.

When

used with no

;

command used to start the application. Use this bit command was (which is sometimes

of code to determine what your application nothing):

$listptr = $mw->coinmand foreach (©$listptr) { print "$'_\n";

( )

;

}

You can

unset the

'WM_COMMAND

$toplevel->cornmand(

" "

)

;

property by sending an empty

string:

267

Toplevel Methods

The Focus Model The

method

f ocusmodel

the keyboard focus

$toplevel->f ocusmodel

The

default

is

changes present

controls

when

whether or not the toplevel widget

another application or [

(

"active"

in

"passive"

|

"passive", meaning

window should have

it

]

give

will

up

will give it:

)

up

The

the keyboard focus.

your application depend completely on the type of window

manager you are running your application under. under Win32 or the X Window System.

My

testing revealed

no changes

Getting the Parent of the Toplevel The frame method

returns a hexadecimal string that

is

the "ID" of the parent of

the toplevel widget: $id = $toplevel->f rame

You can

use

$widget->id

( )

( )

to get the

same ID from any widget

in

your application.

The Application Grid way back

There are a few complications with the grid method. Remember

in

Chapter 2 there was a grid there also which controlled geometry management. To resolve this

little

$iTiw->wm( 'grid'

We

must use the

we

problem, ...

,

wm

)

have to

call this

grid method

in a

funny way:

;

(stands for

window manager) method

to invoke

grid

Now that we have that cleared up, we can get into what wm( 'grid' When you tell the window to grid, you are restricting the size can

,

to the grid as defined in grid.

We

have

to

.

.

does.

)

.

be.

it

must always snap

indirectly.

The

size

the

list-

remember

box widget and the -setgrid option back in Chapter 7, The Listbox Widget. Once you use -setgrid => 1 on a listbox, you can use @list = $toplevel-> wm('grid') to determine the values used in the grid. The values I got on my system were 10, 10, 7, and 17. This means the base width and height were each 10 pixels and each grid unit incremented by 7 pixels in width and 17 pixels in height. You can change the grid size and increments by calling wm( 'grid' with new values if you desire, but if you don't, Tk manages everything quite nicely for ;

,

,

.

.

)

any of the gridded widgets.

You should for

also

know that you can new values.

each instead of

unset the grid values by using empty strings

;

;

.

268

Chapter 13: Toplevel Widgets

Being the Leader it's good to know what you're not The group method makes a widget the group leader of related windows. For each toplevel that you want to be in $widget's group, call $toplevel->group($widget) If $widget isn't specified, it will return the current group leader of $ toplevel, or it will return an empty string if $ toplevel

This

another method you'll never use, but

is

using

it

for.

.

part of a group.

isn't

You can send an empty That

is,

to

remove

string to cancel toplevel's association with that group.

a toplevel from the group, call

$toplevel->group

(

" "

)

Removing Decorations To make ders,

a

window

with none of the normal

window

decorations

and so on) you can use the overrideredirect method with a

$toplevel->overrideredirect (1)

bor-

true value:

Remove all decorations

#

;

(titlebar,

you won't be able to move the window on the screen once it is you forgot to put an exit button on it, you won't be able to quit the application gracefully (doing a CTRL-C in the window that started the script will Be

careful though;

drawn.

If

kill it).

This tion

a

is

way

loading.

is



make a splash screen Remember that you must

to

call

MainLoop

overrideredirect with no argument

Calling

overrideredirect again with

for

it

as

your applica-

show up

to

at all.

returns the current value (1 or 0):

$current_value = $toplevel->overrideredirect Calling

shows up

a screen that

()

value will not turn decorations back on

a

once the window has been displayed.

Who Placed the Window? When tells

the toplevel widget

the program

where

is

window manager window manager where it window manually when it

placed on the window, either the

to be or the program

tells

the

wants to be. In some cases, the user positions the

comes up. $who = $toplevel->positionfrom() $toplevel->positionfrom "program" (

When

called without argument, the

which one happened.

If

it

)

;

#

Try and force it

positionf rom method

returns information

returns the string "program", an

empty

string,

on

or a

means either the window manager or the program requested the position. If positionf rom returns the string "user", the user manually placed the window when it was created. $widget,

it

Fun Things

You can

269

to Try

try to force

gram" or "user"

which

string,

happen by calling positionf rem with the "proonly work if your window manager agrees with

will

but

it

will

you.

Who Sized It? The sizef rem method does the same thing positionf rem does except information regarding the size of the window. $who = $toplevel->sizefrom() $toplevel->sizefrom( "user" )

returns

"program" or "user"? Try and force it

#

;

#

;

it

Not a Real Window A

transient

window

is

one

that isn't quite a real

window

(such as a pull-down

menu). You can indicate to the window manager that the toplevel

menu) is related to transient method:

the pulldown

by using the

its

master (the

$toplevel->transient () $toplevel->transient ($master) $mYitiaster =

If

window

in

which

(for

it

is

example,

displayed)

;

you don't use any arguments with transient, an empty string.

it

returns either the current mas-

ter or

Review It

is

there

a is

mation

good idea too is

much

also

to use another toplevel

information to

sometimes

a

fit

good

in

widget instead of the MainWindow

one window. Using toplevels

idea.

When

design decision that you'll have to make.

You

to use

don't

to

group

infor-

an additional toplevel

want

to

if

is

a

have too many win-

dows for the user to navigate, but a well-designed application might be able to make use of one or two. For instance, the Tk module comes with a Tk::Dialog module that lets you easily display messages to the user. Check out the documentation included with the Dialog.pm file for more information on how to use it.

Fun Things

to Try

Take the Dynamic Document ate a

new

List

example from the

toplevel every time the user hits the

actually create or load a

file.)

last

chapter and

New Document

make

it

cre-

button. (Advanced:

;

Binding Events

is an event-driven programming language. You design your program respond to events generated by the program. Event sequences can be pushing a button, moving the mouse, or typing some characters with a keyboard. The relationship between the event sequence and the widget is called

Perl/Tk to

a binding.

Each widget provided with Perl/Tk has button widget changes color

when

the

invokes a callback that you specified ings,

ones

that are created

when you

own

mouse

when

it

default bindings. For example, the

pointer is

is

clicked.

create the widget

You can have your program respond

command

its

over the button and

it

These are default bind-

itself.

to additional events

by using the bind

to assign callbacks to different event sequences; the basic format

is:

$widget - >bind sequence (

In addition,

,

cal Iback)

you can override the

own

or just

from the widget to which you would

like to

default bindings

by creating your

removing them.

The bind Method To use

the

bind method, invoke

add the binding. For instance,

if

it

you want

to

add

ton, use $button->bind. In certain instances, you

270

$butmain window

a binding to a button in

would use

the

271

The bind Method

of your application: $inw->bind

(

.

.

,

)



There are several different

arguments you can send to bind. The following

$widget->bind() Calling

bind

list

them

explains

sets of valid

all:

;

with no arguments returns a

,

)

of bind sequences (e.g.

list

have been created

that

for that widget.

It

not

will

any of the default bindings. Here's an example:

return

$button = $mw->Button( ... $button->bind( ""

)

,

->pack; sub { ...

}

)

©bindings = $button->bind( print "Bindings for button: ©bindings \n " # would print: # Bindings for button: )

This function will return an empty string

if

no

there are

additional bindings for

that widget.

$widget->bind(5e^Mewce) ; You can determine what callback

associated with a bind sequence. Pass in

is

"") as the first argument and the currently assigned callback will be returned. Expanding the preceding example, we can use the information in ©bindings to see what callbacks are asso-

the bind sequence (for example,

ciated with them: f oreach

©bindings { print "$_ is assigned callback (

)

$button->bind($_)

",

,

"\n";

}

#

is assigned callback Tk: :Callback=CODE(0x91fdcc)

you send a bind sequence that doesn't exist for that widget, you'll simply empty string as the result. Also, if you use a sequence that is considered a default binding (for example, "" on a button widget), you'll get an empty string as well (unless you've added another binding to it If

get an

with bind). $>-wi.dgQt->bi.ndi {sequence ,

To have sequence

callback)

a callback invoked in the

bind

cussed in Chapter

3-

call. It

Here are

;

when

a

sequence happens, specify

it

after the

can be any of the valid forms for callbacks a

$button->bind( "" sub { print "Right clickedXn" } $entry->bind( "" sub { print "Hit return in entry widget\n" $button->bind " " \6cbl_addtl_action $canvas->Tk: :bind{"", \&draw_rec tangle, Ev("X"), Ev("Y") ,

)

,

(

( )

,

)

callback.

}

)

;

;

[

To remove

dis-

few examples:

a binding for a specific sequence, send an

empty

]);

string for the

;

,

272

,

,

;

Chapter 14: Binding Events

$widget->bind(/Scrolled( "Text" ->pack(-e>^and => $t2 = $inw->Scrolled( "Text") ->pack( -expand => )

$menu = $mw->Menu(-menuitems =>

-fill => 'both'); -fill => 'both'

1, 1,

)

["command" => "Search", -command => \&search_f ile] ["command" => "Search Again" -command => \&search_again]

[

],

-tearoff => 0) $mw->bind (Tk Text " " sub { $menu->Popup(-popover => 'cursor', -popanchor => "nw") } ;

:

Any

)

widgets you create inside the application would then have the search

text

menu pop up tines to

,

:

over

it.

You would have

to

do

a

little

work

in the search rou-

determine which text widget triggered the function, but you wouldn't

have to recode the same bind sequence for each

widget you create.

text

we specified the sequence ("") to be we would get a list of the current callbacks associated

In the preceding example,

bound.

If

we

didn't,

with that event sequence.

The

special tag 'all' can

application. But

you would

be

be used

careful; you'll get

first

much more

widget and

activity in

window

in the

your callback than

think!

Arguments Sent to The

to refer to every

argument

calling widget. This

the Callback

to a callback assigned with is

true

even when

bind

is

always a reference to the

you bind to a widget

class.

You can use

the

reference passed in to retrieve information about the widget from which the

sequence was invoked. Here's an example of using a single entry widget: $entry = $mw->Entry () ->pack; \&hit_retum) $entrY->bind( "" sub hit_ret\am { ,

my

($e)

= @_;

print "Entry contained: }

;

",

$e->get,

"\n";

273

Defining Event Sequences

When you

bind

use

job of determining

to

invoke a callback on an entire widget

class,

which widget was the subject of the event much

$inw->Scrolled( "Text" ->pack( -expand => $iTiw->Scrolled "Text ") ->pack( -expand => )

(

$menu = $ir(w->Menu(-menui terns =>

[

1, 1,

it

makes the

easier:

-fill => 'both'); -fill => 'both');

["command" => "Save", -command => \&save_file] ["command" => "Open", -command => \&open_file] ],

-tearoff => 0) $mw->bind(Tk: :Text, "" sub { $menu->Popup(-popover => 'cursor') sub save_file {

my ($text)

});

= ©_;

die "Couldn't open outfile for writing"; open(FH, ">outfile") "end"); print FH $text->get "1.0" close (FH) |

|

(

,

}

The

call to

bind

uses Tk: :Text as the

be applied to every

which

text

widget

cation might also to actually

is

text

clicked,

its

argument. This will cause the bind to this

example, no matter

contents will be written to "outfile".

prompt the user

do something

first

widget in the application. In

The

appli-

for a different filename at that point, allowing

it

useful.

Defining Event Sequences So

far,

and

you've seen several different event sequences

—but

haven't

I

yet

explained

Although the examples you've seen

— , ,

the

format

for

building

them.

simple,

event

may seem obvious and

sequences can get much more complicated.

The event sequence is built from an optional modifier, an event, and an optional detail. They are separated by dashes and then placed between angle brackets:

As

we

discuss

all

the possible bindings,

keep

in

mind

that

it

is

possible for

more

than one event sequence to match. The more detailed matches will invoke their callbacks

first. If

binding

is

invoked

first,

a binding has

created

on

all

been created on

a specific button,

and then another

of the buttons, the specific-button bind callback will be

and then the more general

all-button bind callback will

be invoked.

Modifiers A

same time the main event happens, holding down the Control key and clicking the mouse. The modifying

modifier

such as

is

an event

that

happens

at

the

274

Chapter 14: Binding Events

event must happen

first

in order for the entire event

pressing the Control key and then pressing the

The possible modifiers and

their

mouse

sequence to match

(e.g.,

button).

meanings are as follows:

Control

The Control key must be pressed down ).

as the

main event

happening

is

(e.g.,

Shift

The Shift key must be pressed down ).

as

the

main event happens

(e.g.,

Lock

The Caps Lock key must be pressed

to turn

on caps lock

(e.g.,

).

Alt

Causes the main event to match only while the main event happens Microsoft

Windows

users

(e.g.,

if

either of the Alt keys

should be aware that sometimes

doesn't allow the event notifier to notify applications that the

been pressed. The

left

Alt

key

is

try the right

using an

pressed

down

MS Windows left Alt

key has

normally the Alt key people use

switching between applications by using ALT-Tab.

work,

is

).

If

the

left

Alt

when

key doesn't

one before giving up. This warning also applies if you are server (e.g., Exceed) on MS Windows to access a Unix

X Window

system.

Button* where *

is 1, 2, 3, 4,

These modifiers indicate fied

or 5. You could also use that,

B# as a

shortcut.

before the rest of the event happens, the speci-

mouse-button number must be depressed. For instance,

when

if

you want

to

mouse button 1 and then mouse button (or ). The event

you can use the 3, same event would not be triggered if you clicked mouse button 3 and then mouse button 1. The events are order dependent. trigger

It

is

an event

the user clicks

not valid to use only

because, without

"Button" and the number, you are indicating

the dash

between

a modifier to another event

type.

Double

Double is a special type of modifier that indicates the main event should happen twice. Double puts a constraint on the minimum amount of time between the repetitions of the main event. Double is most often used to indicate a double-click of a

mouse

button.

is important to note that is not equivalent to . Although they sort of mean the same thing, there is no

It

275

Defining Event Sequences

time constraint with the

event.

The second means

"You clicked button 1, and then at some later point, you clicked button 1 again." The event means "You clicked button 1, and within a certain time period, you clicked button

again."

1

Triple

Similar to Double, Triple

is

another special modifier type.

main event occur three times

It

requires that the

in rapid succession.

to consider with Double and Triple modifiers is that you click five times quickly on a button, the first click would match at event, the second click would match a event, the third click would match event, and the fourth click would also match a event, and so on. This is true only if the event is defined. If only is defined, the third click would reactivate that binding instead of the binding. The timeline in Figure 14-1 shows

Another interesting thing they are cumulative.

when

If

the events are generated.

Clickl

Click2

Click4

Clicks

Single Click

1st Doubleclick

2ncl

Double Click

3rd Double Click

event generated

event generated

event generated

event generated

Figure 14-1. Cumulative double-clicking example

Meta (orM) Requires that the Meta key be pressed during the main event. The Meta key usually used

on X Window Systems

is

only.

Mod^orM* This

is

also only used

5);

use Ev( 'K'

)

on

X Window

to determine

Systems. There are several modifiers (1—

where they

on your keyboard.

are

Event Types (with Optional Details) The event portion of

the event string

is

the event

we

modifier or not (as specified in the preceding section).

event

is

triggered or generated,

it

means

callback associated with the event,

The following

is

a

list

it

are looking

When

that the event has

will

look as

if

for. It

can have a

the information says an

happened.

If

there

is

no

nothing has actually happened.

of event types and the optional details where applicable.

.

276

Chapter 14: Binding Events

ButtonPress (or Button)

A

ButtonPress happens

when

mouse button

a

pressed down. The Button

is

it's just a shorter way to write it. If you use any mouse button, but you can specify a spe-

event also refers to a ButtonPress; the event , cific

it

button by adding a

refers to

, , and so on.

detail:

ButtonRelease

A

ButtonRelease event happens

when

the

mouse button

is

released.

You can

happen based on the button being pressed down (Button or ButtonPress) and let up (ButtonRelease). You can specify a detail to indicate a different button: , , and so on. If a specific button isn't specified, any button will match the event. have

different things

Circulate

The

Circulate event

window and

is

when your

generated

the stacking order

is

application has

more than one

switched around.

Colormap

The Colormap event happens when

the colormap for the widget (usually a

toplevel) has changed.

Configure

The Configure event happens when to this one,

dow

is

be

careful;

resized,

it

a widget

can be called quite

is

configured.

often.

Configure event being generated for those widgets. ated,

it

you map

a callback

Every time the application win-

window

each widget within the

If

is

configured, resulting in a

When

the widget

is first

cre-

also generates a Configure event.

Destroy

When

the widget

fully destroy a

is

destroyed, the Destroy event

is

widget by using $widget->destroy

generated.

You can

force-

( )

Enter

The Enter event happens when the mouse cursor the widget. It is important to remember that this

enters the area occupied is

by

not the "user-presses-the-

RETURN/Enter-keyboard-key" event. Expose

The Expose event happens when

the

window has been exposed.

Focusin

When (or

the widget receives the keyboard focus because the user has tabbed to

$widget->f ecus

( )

happens

in the

it

program), the FocusIn event happens.

FocusOut

The FocusOut event

is

the opposite of FocusIn.

leaves the widget, FocusOut

is

triggered.

When

the keyboard focus

277

Defining Event Sequences

Gravity

The Gravity event happens when the widget moves because ent changed size.

the widget's par-

KeyPress (or Key)

When

a

key on the keyboard

is

pressed, the KeyPress (or Key) event

gener-

is

ated. It is possible to narrow this down to the specific key such as the "a" key by using a detail with the event: . If you want to determine which as an argument key was pressed to trigger the event, you can use Ev K (

'

'

)

with your callback: $ir[w- >bind

(

"

"

,

[

\

&check_key

,

Ev

(

'

K

'

)

]

)

;

This has the effect of sending the key symbol for the key pressed as an argu-

ment this

to

check_key. To find out which key symbols are

for

which keys, use

piece of code: use Tk; $mw = MainWindow->new; $mw->bind("", siib MainLoop

print "Key: $_[l]\n";

{

[

As you press keys on the keyboard,

},

you'll see their

Ev('K')]

)

key symbols printed out

on the screen. Notice that the shift characters above the numbers (such as $, %, /\, and so on) come out as named ("dollar," "percent," "caret," and so on). KeyRelease

The KeyRelease event the key

is

released.

is

the

companion event

Sometimes

it

is

to KeyPress.

It is

invoked

when

preferable to wait until the key has been

released before doing anything.

Leave

The Leave event happens when the mouse cursor leaves the area occupied by the widget. Use Enter and Leave events to create two bindings for the same widget and you can do neat things such as change the mouse cursor while the mouse is in the widget (look into using -cursor first if it's available for that widget).

Map The Map event happens when window has been mapped or opened

(deiconified).

Motion

When

the

erates a lightly

bind to

mouse moves around on

Motion event. This

because your callback just a single

will

be triggered

all

the time. Granted,

widget, you'll only get Motion events

ing over that widget, but that gest having a very

the screen above your application,

it

gen-

another event that you don't want to bind to

is

is still

good reason

when you

Motion event.

you

are pass-

a lot of invocations of the callback.

for binding to the

if

I

sug-

.

278

Chapter 14: Binding Events

Reparent

The Reparent event happens when parent of

the

bound widget has changed.

Unmap The Unmap event happens when

bound window has been

the

iconified.

Visibility

When

widget

a

several

ways

When



screen,

the application it

When

visible,

first

starts

it

onto the screen, a

the widget

is

There are

triggers the Visibility event.

it

in

your application:

up, and the widget

Note

triggers a Visibility event.

don't pack •

becomes

first

widget becomes visible

a

Visibility

that

if

you

is

placed on the

create a widget

and

event will not be generated.

unpacked by using pack

(

'

forget

'

and then

)

repacked.

When



window is resized and the widget suddenly comes into view window has been made smaller and then resized larger).

the

(usually after the

When



the widget

and

get)

scrolls

is

inside another widget (such as a text or canvas wid-

back on the screen.

Event Information You can find out information about an. event by using the Ev method. There are many values you can use in a call to Ev, and they are thoroughly documented on the Perl/Tk documentation web site at http://w4.lns.comell.edu/~pvhp/ptk/ doc/bind. htm, which ptk/pod/bind.pod.

I'll

is

maintained by Peter Prymmer, and http://www.perl.com/

cover the values that you would want to use 99.9 percent of

the time.

Remember

events.

you use an Ev value

If

that certain values

used with Ev are only valid

that doesn't apply, you'll get

for certain

an undefined value.

Coordinates To determine the coordinates at which the event happened, use Ev('x') and They return coordinates relative to the window in which the event hapEv( 'y' pened. If you want coordinates relative to the root of your window system (desk)



top in Windows, Xroot in X), use uppercase

Ev('X') and Ev('Y')are valid only Key Release, or Motion events.

Button To

X

and Y: Ev( 'X'

for ButtonPress,

)

and Ev( Y' '

)

ButtonRelease, KeyPress,

Number

find out

which button number on the mouse was pressed, use Ev('b')- It If you use Ev('b') with

valid only for ButtonPress or ButtonRelease events.

event,

you would obviously get

1

back.

is

a

279

Bailing Out of a Callback Created with bind

Height and Width to return the height and a 'w' to return the width associated with the The width and height returned indicate how large the widget is. For instance, if you want to find out the new size of a button after the window has been manually resized by the user, you can do this:

Use an 'h'

event.

$button->bind("",

sub { print "H: $_[!], W: $_[2]\n"; Ev('h'), Ev('w')

[

]

},

)

The callback will only be invoked when the widget has been configured. This happens when the widget is first created and any time the widget is resized. Ev( 'h'

)

and Ev( 'w'

are valid only for Configure, Expose,

)

and GraphicsExpose

events.

Keyboard Information There are several ways

to find out

which keys the user has pressed on the key-

board. Use 'K' to print out the value associated with that key called a keysym. If you use lowercase 'k', you'll get the ASCII value associated with the key. Try this bit of code to see the difference: $b->bind{"", )

and Ev( 'K'

You can

also get the

Ev( 'k'

[

sub

{

print "ARCS:

(a_\n"

;

are valid only for KeyPress

)

keysym

},

]

)

and KeyRelease events.

number

as a decimal

Ev('k'), Ev('K')

rather than a string

by using

Ev('N').

Event Type You can

find out

Ev('T').

When

It's

what type of event the callback

is

responding to by using

responding to a KeyPress event, the string

pretty obvious, but

sometimes

it's

useful

if

you

will

are using the

be "KeyPress".

same callback

to

respond to several different events.

Bailing Out of a Callback Created with

bind To

stop the processing within your callback, you can use a

return control. This will not stop any further cessed.

To

halt the processing of

combination, you can use Tk:

:

any and

break

all

bound

return statement

to

callbacks from being pro-

callbacks

bound

to a widget/event

instead of the milder return.

;

.

;

;

:

280

Chapter 14: Binding Events

The bindtags Method To

find out the tags associated with a widget, use the

bindtags method;

for

example: print join(' ', $button->bindtags # prints this: Tk: Button .button print join(' ', $inw->bindtags () # prints this MainWindow all

( )

:

)

:

This

tells

.

)

all

;

.

us the order in which the widget will respond to binding callbacks. The

always to the class that the widget belongs

first

response

first

example and MainWindow

is

to;

Tk::Button in the

in the second.

The information returned from bindtags isn't nearly as interesting as what you can do with arguments sent to it. To remove all specific bindings from a widget except those that apply to all '

'

$button->bindtags

Now

[ (

'

all

'

]

)

the button will not respond to being pressed,

page

bindtags, you can reverse the order

for

events like

in

or the

in the Perl/Tk

web

which the widget responds

to

this:

$b->bindtags

We

mouse movements,

As demonstrated

default bindings associated with the widget.

already

[ '

(

know

all

'

that

,

$b->toplevel ref $b) $b] ,

(

,

)

'all' means any bindings associated with the special

all bindtag. Using $b->toplevel returns the window $b lives in: MainWindow=HASH(0x9798d8). Using ref($b) gives the package $b belongs to: Tk: :ButTk: Button. Finally, $b means the specific instance of $b: ton=HASH 0x99c0cc '

'

:

)

(

HASH(0x99c0cc) in

parentheses

that

it

is

is

is

a

what we see when

just the physical

we

memory

print the value out.

The hex number HASH means

location of that widget.

stored in a hash structure.

Ways

Use bind

to

do things easily. You can menu when you right-click on Use bind with text tags to create a pseudo-html document. Add a double-click binding to the listbox so that something happens when a user double-clicks on an Using bind

add

is

a powerful

way

to

make your

a binding to a listbox widget so

it

application

will display a

it.

item in the listbox. There are more ways you can use

cover here. Just

make

sure you don't

do anything

example, triple-clicking while holding

down

bind than

I

could ever

that the user can't figure out (for

the Control key

is

a bit obscure).

Composite Widgets

So

we have

far,

only discussed each basic widget separately. The Perl/Tk distribu-

tion also includes several composite widgets.

of widgets that

do something

specific

Composite widgets are combinations

when

some

they are combined. Here are

examples of composite widgets:

Optionmenu Based on menubutton widget; on the menu.

it

allows the user to select from a

list

of items

LabEntfy

Based on frame widget;

it

is

Based on toplevel widget;

it

an entry widget with a configurable

label.

Dialog

I

displays a bitmap

and

a

message

to the user.

chose these examples because they demonstrate a good point about composite

They can be based on a widget (in that contains widgets, or on a toplevel widget complete window.

widgets.

When

I

first

started learning about

ing something.

If

I

looked

at

this case,

menubutton), on a frame

that contains other widgets

composite widgets,

the code out of the

I

always

comer of my

felt like

eye,

it

I

and

was

made

is

a

miss-

sense.

if I looked at it head on, I was suddenly utterly confused and wasn't sure what was doing. The important thing to remember is that there is quite a bit that goes on behind the scenes that we take advantage of when we are creating a compos-

Yet it

ite

My

widget.

goal with this chapter

isn't for

you

to write the

most complex type of compos-

how

composite widgets work is more than enough. You can build up slowly from there. The best thing to do is read through this chapter and then look at the examples already included with the ite

widget you can think

of.

Simply understanding

281

;

;

;

;

;

;

282

Chapter 15: Composite Widgets

The composite widgets included with the Tk module are many different people, and will do something when you run them (plus they are usually documented with pod documentation). Rather than show a do-nothing example in this chapter, I will refer you to real distribution of Perl/Tk.

complete, have been reviewed by

code.

Looking at an Example Sideways I

admit

it.

I

examples. They give

like

me

I'm getting into the nitty-gritty. Since there posite widgets, we'll start simple

come back

a starting point to

to

quite a bit of nitty-gritty with

is

and work up from

when com-

there.

you look at the code for these composite widgets, the LabEntry has amount of code. Here is the LabEntry.pm widget code: If

the smallest

Copyright (c) 1995-1997 Nick Ing-Simmons All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Class LabeledEntry

#

.

# #

#

package Tk: LabEntry; require Tk: Frame; ©ISA = qw{Tk: Frame) :

:

:

Constiruct Tk: Widget 'LabEntry'; :

sub Populate {

require Tk: Entry; # LabeledEntry constructor. :

#

my($cw, $args) = @_; $cw->SUPER: Populate $args entry, # Advertised subwidgets: my $e = $cw->Entry() $e->pack( -expand => 1, -fill => 'both'); $cw->Advertise( 'entry' => $e) $cw->ConfigSpecs (DEFAULT => [$e] $cw->Delegates (DEFAULT => $e) $cw->AddScrollbars($e) if (exists $args->{-scrollbars} :

(

)

)

)

}

1;

That's the complete set of code,

comments and

composite widget because of the

Programming each package

method

if it

line (ilSA

=

Perl (O'Reilly, 1997) to find out a

special array called (ilSA

can't find the

method

in that

all.

You can

tell it's

qw(Tk: Frame). :

what the @ISA array

tells

Perl

where

package." There's a

a frame-based

We

can look

is for:

in

"Within

else to look for a lot

more

there about

283

Location of Files

how

to explain a simple concept:

your code.*

line in

wouldn't want to overuse their words

just

To have your composite widget work, you need

this

implements inheritance, but

this

All the other

I

explanation

is

—how does the entry widget come

Next step because

if

we

use a LabEntry,

one subroutine

in the

whole

we file;

nitty-gritty.

into play?

We know

gets created

it

see one on the screen. You'll notice there's only that subroutine

is

Populate. You never

called

call it directly, but it does get called. The arguments to Populate are two scalars. The first is a reference to the frame itself, and the second is a reference to a hash that contains all the argument pairs you would have used to create the widget. Here's an example of creating a LabEntry widget:

$label_entry = $mw->LabEntrY(-textvariable => \$text, -label => "Enter Name:", -labelPack => -side => 'left'

)

[

As you glance through the code, you know an entry widget see this

my $e

line:

= $cw->Entry

( )

.

Then

and Delegates. For

Advertising, ConfigSpecs,

a

is

let's just

->pack(

)

created because

bunch of weird

now

]

stuff

you

happens with

say that these functions

allow the entry widget to behave as you would expect an entry widget to behave.

The LabEntry 's

when we the

label

create

we

If

it.

created automatically because

is

-label option with

a simple

look back to Chapter a frame, a label will

composite widget

is

that

it

12,

we

Frames,

be created

use the -label option

we

use

So what makes

this

we know

for us.

that

if

takes advantage of the label already included

with a frame widget.

Location of Files When you name

create your

own

composite widgets, you create a

file

that has the

same

(including capitalization) of your widget and has a .pm suffix. For instance,

you wanted place the code if

new composite

to create a for

it

widget called ListButton, you would

in a file called ListButton.pm.

new

use ListButton

In the

code

at the

top of your code, assuming you keep your composite widget

that uses

your

ListButton.pm) in the

same before any use or require use lib

(

"dirl "

,

"dir2 "

widget, include

after the files

use Tk (such as

directory as the rest of your application code.

If

not,

statements, add: )

pointing to whatever directory you're using for ListButton.pm.

* You really don't need to inherit from a frame, but most people do, and because you have an automatic container for your composite widget.

t

The

we

nitty-gritty

don't

need

would involve

tracing through

that level of detail here.

all

the Perl/Tk

code

it

to see

makes what

things a

little

simpler

gets called where, but

;

;

284

Chapter 15: Composite Widgets

Creating a Composite Widget Based on

Frame There are

between creating

differences

slight

frame and creating one based on a toplevel.

a I

composite widget based on a

example

will include a short

for

each to give you an idea of what you can do.

Assuming you're making

a composite widget called

you absolutely must have

in

package MyWidget; require Tk: Frame; ©ISA = qw(Tk: Frame

your

new composite

MyWidget, the

widget

first

five lines

file are:

:

:

)

Construct Tk: Widget :

'

I^f/Widget

'

sub Populate {

You must MyWidget

declare your

new

widget as

line. (If you were going would use DirName: :]y^/Widget.)

The next two

lines are simple:

to

its

own

package, hence the package

have a subdirectory

for

your widgets, you

Tk: Frame to make sure you have

require

:

loaded the information necessary to use a frame widget, and then add Tk::Frame to the

©ISA

variable.

(you could also write

name

calling

line calls the

Construct method from

Tk: :Widget->Const3ruct( "MyWidget"

this as

of your widget. In this

directory in

By

The next

call to

which your widget

Construct you do not add

Tk:: Widget ))

with the

name

the

of the

resides.

Construct, you create a constructor method

widget. This allows you to create a

for

new MyWidget by

your

new MyWidget MyWidget

calling the

method: $newwidget = $itiw->MyWidget (...);

You

are creating a composite widget based

late

to create

on

a frame, so

you need

to use

Popu-

your subwidgets and do any other necessary configuration.

Inside Populate It

a

is

create

good in

idea to

add

a

require statement

for

any other widgets you want to

your composite widget. In the LabEntry code,

Tk: Entry because LabEntry creates an entry widget. :

we saw

a

require

Creating a Composite Widget Based on

Populate

is

Frame

two arguments:

called with

285

a reference to the

composite widget and

arguments to variables so you can use them

a reference to a hash. Assign these later:

my

($cw,

$args)

= @_;

The next thing you should do entire

Do

composite widget.

and then seeing

if

the value

is

this

was

deal with any specific options that apply to your

by getting them out of the $args hash reference defined:

$option_value = delete $args->{ "-flag" if (defined $option_value) {

}

}

say you want to use the option -filename, which will get the value associ-

Let's

ated with the

-filename option

into $ filename:

$filename = delete $args->{ "-filename" if (defined $filename) { # Open file.

}

.

}

After dealing with

the arguments that

all

idea to call SUPER:

:

Populate

$cw->SUPER: Populate $args :

(

you want

you want

if

methods

for

gets,

call

is

a

good

)

in

your composite widget. For

to create a listbox with several buttons, call the appropriate

each one.

you should

it

like this:

Next you should create the widgets you want instance,

to pull out directly,

If

you want the user

Advertise

for

be able to manipulate those wid-

to

each one.

Calling Advertise

The Advertise method allows you to use the siibwidget method to get directly at that widget later on in the program. For example, after you create the LabEntry, you can get a reference to the entry widget: $label_entrY = $mw->LabEntry (-textvariable => \$text, -label => "Enter Name:", -labelPack => -side => 'left' ])->pack(); $entry = $label_entry->Subwidget "entry" $entered = $entry->get [

(

)

( )

When you tise

for

have two

create a composite widget

each widget. For example, calls to

if

Advertise:

$cw->Advertise( 'entry' => $e) $cw->Advertise( 'button' => $button)

remember to add another call to Adveryou create an entry and a button, you'll

;

;

286

Chapter 15: Composite Widgets

Calling Delegates

When you to define

you

create a composite widget,

When you

widgets into one.

what methods

and sending

it

are essentially combining

two or three

invoke methods on the composite widget, you have

are actually called.

a reference to the

Do

so by using the Delegates method

widget you want to use:

$cw->Delegates (DEFAULT => $e) All other

subwidget methods of the composite

the siibwidget

You can

will

have to be accessed by using

method and then invoking methods from

Delegates

also use

$cw->Delegates

('

insert

to call a

method on

there.

a subwidget as follows:

=> $scrolled_listbox,

'

$scrolled_listbox, DEFAULT => $e) 'delete'

==>

;

In this example,

if

be passed along

$conposite->insert (...), the method call will $scrolled_list±)Ox->insert method. You cannot pass

the user calls

to the

along any methods that your composite already defines.

own insert

If

your composite uses

its

method, you would have to manually pass control to the subwidget

yourself.

Calling ConflgSpecs

When you it.

create a composite widget,

You can use Conf igSpecs

to

do

so.

you want to

handle

option, or specify a default widget that will handle

simple composite widget such as LabEntry will

default widget to handle

all

of the configuration.

$cw->Conf igSpecs (DEFAULT => [$e]

Specify

DEFAULT

as the

first

call

an option

alias

of the

configure

to another calls.

Conf igSpecs just to set Conf igSpecs like this:

a

called

)

parameter, and then specify an

taining the widget to use as the

configure and use

It

it,

all

configure on ways to call Con-

call

There are three different

figSpecs: create an option and a way

A

be able to

to

anonymous

list

second parameter. This way, anytime you

concall

the composite widget reference, you'll be configuring the

entry widget.

Creating an alias

You can short

name

use Conf igSpecs to create an

alias for

and long version of the same option. to

mean

exactly the

same

thing, call

If

an option, possibly to make a

you want

Conf igSpecs

$cw->ConfigSpecs( '-file' => '-filename');

Specify the alias

first

and the equivalent option second.

to use

-file and -file-

like this:

Creating a Composite Widget Based on

Frame

287

Defining options

To

some

define an option and associate

$cw->ConfigSpecs(-newoption =>

action with

it,

call

Conf igSpecs

, "newOption", "NewOption"

[

,

]

like this:

)

The option you are creating the action for is listed first, and the second argument is an anonymous list consisting of four items. The first item is the action you want to take and should be "DESCENDANTS", "ADVERTISED", "SELF", "CHILDREN", "PASSIVE", "METHOD", "CALLBACK", or a $reference to a subwidget. The second and third items in the list have to do with the option database and can be left blank if you prefer. The fourth item is the default value of that option, usually undef or " " or whatever you want the default value of that option to be if the user doesn't specify

The

it.

action part of the

list

defines

what happens. Each possible value

is

defined as

follows:

DESCENDANTS The configure

for that option will

ADVERTISED The configure

will

be applied to

SELF The configure

will

be applied to the base widget

be applied recursively to

all

all

descendants.

advertised subwidgets.

(in this case, a frame,

but the

base widget can also be another composite widget).

CHILDREN The configure

will

be applied

to

all

children.

PASSIVE The value will be stored in $args. This is the way you would use Conf igSpecs on any options that can be used at create time or by custom methods of your composite widget.

METHOD The method with the same name as the option will be called. For instance, if « . => you call $cw->ConfigSpecs(-newoption ["METHOD", » undef] and then the user uses the -newoption option, the method newoption (which you still have to define in the file somewhere) will be -•

^

^

)

invoked. When you cannot define an option with one of the other you can use METHOD.

settings,

CALLBACK Invokes a method inside your composite widget sent

when

=>

["CALLBACK",

the widget

is

that option

if

,

configured or

$cw->ConfigSpecs (-itiyopt "MyMethod" undef]) would call the

created. For instance,

"inyMethod"

is

,

)

;;

( ;

;

.

,

,

288

,

,

Chapter 15: Composite Widgets

subroutine rayMethod

when

the option -itr/opt

Conf igSpecs below

try.pm's

is

used (also see BrowseEn-

an example).

for

$reference Forces a

call

to

Usually

option.

$reference->configure( -option => value) for $reference is a subwidget of the composite widget

that (for

example, an entry widget). ConflgSpecs example

Here

is

Conf igSpecs

the

$w->Conf igSpecs -listwidth -listcmd -browsecmd -choices -state -arrowimage -variable DEFAULT

As you can this

see,

call

=>

=> => => => => => =>

from the TkS.O version of BrowseEntry.pm:

[qw/PASSIVE listWidth ListWidth/ undef [qw/CALLBACK listCmd ListCmd/ undef [qw/CALLBACK browseCmd BrowseCmd/ undef] [qw/METHOD choices Choices/, undef] [qw/METHOD state State normal/] [{-image => $b} ,qw/arrowImage Ar rowlmage/, undef ]

,

]

,

,

,

]

,

"-textvariable" [$e]

)

you can send multiple pairs of information to ConfigSpecs. In is one PASSIVE option, two CALLBACK options, and two

example, there

METHOD

options.

Any

methods pointed

to in

configure with

other calls to

directed to the subwidget $e.

Take

a look at the

ConfigSpecs

different options will

be

complete code to see what the

do.

Frame-Based Widget Review Just to

sum

up, here's

some pseudocode

frame-based composite widget: $package NewWidget; ©ISA = qw(Tk: :Frame) Tk: :Widget->Construct 'NewWidget' (

sub Populate

)

(

{

my

{$cw,

$args)

= @_;

Handle any creation only options = delete $args-> { -option} if (defined $value) { #

my $value

}

Create any subwidgets you want to $widget = $cw->Widget (...); #

.

.

to

show you how

to create

your

own

Toplevel-Based Composite Widgets

$cw->Delegates $cw->Conf igSpecs

289

( )

(...);

}

sub myoption

{

}

1;

Toplevel-Based Composite Widgets one small difference between a composite widget based on a frame If you want to be able to use ->new() to create your window, define InitObject instead of Populate. Most of the composite widgets included with the Tk distribution do not do this, however. Look at ColorEditor.pm and DialogBox.pm for examples of how to create a toplevel-based composite widget. All the rules for using ConfigDefaults are the same. There

is

instead of a toplevel.

;

Methods for Any Widget So

far,

most of the chapters

in this

book have concentrated on

This chapter covers the methods that apply to

all

need most of these methods, but there are a few

Many call

times, you'll use a

MainWindow

these methods, but you can also

specific widgets.

widgets. You'll probably never

that you'll

use frequently.

reference (usually $inw in our examples) to

call

them from other widgets, such

as

$but-

ton, $checkbutton, and so on. Most of the methods are informational only,

meaning you pass no arguments We'll use the generic

to them;

$widget here

you only get

a value back.

instead of a specific widget type. This will

help you to remember that these are multipurpose methods.

Building a Family Tree The following methods deal with the ancestors or children of widgets and how they were created: children, name, parent, toplevel, manager, and class.

Widget's Children To determine the children of children method:

a

widget (usually

a toplevel or a frame),

use the

@kids = $widget->children() # i.e. Tk: :Button=HASH(0x85e3a0) Tk: :Button=HASH(0x85e4a8)

The

list

returned contains scalars that are the children of $widget.

You can then

use those references to perform actions such as setting a background color or font.

290

291

Building a Family Tree

Name of a Widget To determine what

the parent calls the widget use the

$name = $widget->name

You can combine

the

(

)

;

name and children method

©kids = $widget->children() f oreach @kids { print "Name: ", $_->name(), (

name method:

like this:

)

"\n";

}

Here

is

example output from

that code:

button buttonl

Parent of a Widget To

get a reference to the parent of a widget, use the

$parent = $widget->parent

parent method:

( )

The Widget's Toplevel To

get the toplevel widget that contains a widget, use toplevel:

$path

$widget->toplevel

=

(

)

The $path returned is a number (that is, 8606484) that you can compare to another number that was returned from another call to toplevel to see if they are equal.

Widget's You can

Manager

find out

Smanager It

which geometry manager $widget used by

= $widget->inanager

()

calling

manager:

;

returns a string that describes the geometry manager; for instance,

toplevel widget,

it

to

work

it

is

a

"grid", "pack", "place", or "wm". The manager

will return

method doesn't seem

if

correctly

on Windows

95, but

it

works on Unix and

Windows NT.

The Widget's

class

The class method returns a example, $listbox->class

{ )

"Menu".

string that indicates

returns "ListJDOx",

which class it belongs to. For and $menu->class returns ( )

;

;

.

292

Chapter 16: Methods for Any Widget

Widget's You can

ID

get an ID string for a widget

$id = $widget->id() print "$id\n"; # Prints 0x9c944c

The value returned

is

a

by using the id method:

;

hex value. This method does not work under Windows

95.

Widget's Path You can you

pathname of the window by id method:

get the

calling

pathname and using

the ID

retrieved with the

$path = $widget->pathnaine($id)

There

is

;

PathName method:

also the

$path = $iTiw->PathNaine

( )

;

method prints out the path of $mw would have a PathName of " "

the widget that

This

calling

is

it.

For example,

my

.

Color-Related Methods There are four methods

that deal with color:

colormapfull, rgb, cells, and

depth.

Is the

Colormap

To determine

Full?

the colormap for the widget

if

$isfull = $widget->colormapfull

The colonnapfull method

Cell

(

is full,

use colonnapfull:

)

returns a

1 if

the colormap

is full

and

if it is

not

full.

Count

The number of

cells in the

colormap can be obtained by using the cells method:

$count = $widget->cells

The value returned

is

a

(

)

number

indicating the

number

of colors; for example, 64.

Color Depth You can

get the

number

of bits per pixel by using the

$depth = $widget->depth() # $depth might contain "16"

depth method:

293

option Databases

Translate to

RGB Value

You can translate a color name to the red, green, and blue values by using the rgb method. Send rgb a color name (valid color names v^ere covered in Chapter 3) and

it

returns a

list

containing three items that represent the red, green,

and blue numbers. ($red,

Now

$green,

$blue)

= $widget->rgb( "color"

)

$red, $green, and $blue each contain an integer from

to 255.

Setting Colors You can have your the

based on one color automatically by using

entire application

setPalette method: $widget->setPalette( color)

The background all

color of

is

set to the specified color,

other widgets are calculated based

lighter color than the

color

on

$widget

a

background,

you picked. This method

it

on

will

that color.

show up

So

if

and the colors

a button's

edge

for is

a

a lighter shade of whatever

affects the entire application

even

if

you only

call

it

widget instead of a toplevel.

You can

set colors for explicit options

to associate with

it.

by specifying the name and then the color

For instance, the following code will set

and

in the application to red

all

backgrounds

$b->setPalette( "background" => "blue",

all

foreground items

to blue:

"foreground" => "red");

Predefined Color Scheme The bisque method $widget->bisque

sets the entire application to is

( )

the

same

use a bisque scheme. Calling

$widget->setPalette "bisque"

as calling

(

)

Option Databases Under the

X Window

System, a

file

named

contains configuration information for

X

.Xdefaults in the user's

call

it

directory

applications, including the colors

and

You can create the same type of file for Win32 whatever you want. You might use a file like this to let your

fonts an application should use.

systems and

home

users change the application's color settings.

Typically the lines in this

file

look something

screen*background yellow screen. button. foreground: green screen* font: {Arial} 24 {normal} :

like this:

;

;

Chapter 16: Methods for Any Widget

294

The

;

:

first

name

item in each line should be the

My

options are for your application only. screen, so that

is

what

I

used as the

keyword

first

of your application unless the

test application

in

each

was line.

named

in a file

The second key-

(if specified) is a widget type or name (you can specify a name for any widby adding the -name option to the creation command of that widget). The third keyword is the "class" for which you want to set a default. You can set a default value for any of the options associated with a widget. See Appendix A to find out which class is associated with each widget type.

word get

To read ple,

in this file, call optionReadf ile with the location of the "color_options" or "C: / .Xdefaults" or " .Xdefaults"):

$widget->optioriReadfile "filename" (

Make

)

newline on

last line

of this

file

or you'll get an error

C:\PERL\lib\site/Tk/Submethods.pm line

line 2 at

make much sense except

16." This error doesn't

exam-

;

sure to include a newline on the

that says, "missing

file (for

that the first line

number

it

gives

you matches the number of lines in the option file you are trying to read in. If you to call the method, you'll get a more use $widget->option( "readfile" ,

.

.

.

)

sensible error message.

As the second argument to optionReadf ile you can specify an optional priority, which should be one of "widgetDefault", "startupFile", "userDefault", or "interactive". The default priority is "interactive", which is the highest priority.

$widget->optionReadf ile

You can add an

(

"

filename"

,

"widgetDefault"

)

option type in the program dynamically by using the

optionAdd

method (whether or not you have used optioriReadf ile) $widget->optionAdd(pattezT! => value);

For example,

we

can change the font for the entire program

$widget->optionAdd

(

"

screen* font "

,

" {

Arial } 24 {normal }

"

like this:

)

The optionClear method should clear out any current option the file (or retrieve them from the resource manager): $widget->optionClear

settings

and reread

( )

To determine

the current setting for the value associated with a specified

and

optionGet:

class, call

$widget->optionGet (name, class);

name

295

Converting Screen Distances

The Application's Name The name of the application that is used in the option file discussed earlier is by default the name of the file from which the script is run. You can use the appname method to change the name of the file: $mw->appnaine "newname" (

You can

)

;

find out the current

name

of the application by calling

appname with no

arguments: $name = $inw->appname

( )

;

Widget Existence To determine

if

a widget has

(Exists ($widget)

if

been

created, use

Exists ($widget)

{

)

}

Note the uppercase "E" on built-in Perl

Is the To

this

method. The Exists method

exists method. Make

sure

you

is

different

from the

don't confuse the two.

Widget Mapped?

find out

if

the widget has

been mapped

to the screen, use the

ismapped

method: if

$widget->isinapped Do something else { # map the widget (

( )

)

#

}

}

The ismapped method and if it is not.

returns

1

the widget

if

is

currently

mapped

to the screen

Converting Screen Distances If you prefer to use inches as a screen distance but you want to print out pixels, you can use the pixels method to convert any valid screen distance string into a

pixel value; for example:

$pixels = $widget->pixels "2i" $pixels - $widget->pixels "2m" (

)

;

#

)

;

#

(

What is What is

2 2

inches in pixels? millimeters in pixels?

;

;

;

;

;

296

Chapter 16: Methods for Any Widget

The pixels method rounds to pixel result by using fpixels:

the nearest

$pixels = $widget->fpixels("2i") $pixels = $widget->fpixels("2m")

;

#

;

#

whole

What is What is

pixel.

2 2

You can

get a fractional

inches in pixels? millimeters in pixels?

Size of Widget You can

use the following methods to find out the size of a widget in several

dif-

ferent ways.

Geometry

Widget's

The geometrY method

geometry

returns the

widget

string for the

in the

form of

widthxheight+x^y. $geom = $widget->geometry()

The geometry

string

was discussed

in detail in

Chapter

13-

Geometry values

are

specified in pixels.

Requested Height The height of the widget

is

returned by the

$height = $widget->reqheight

The widget

itself

reqheight method:

( )

determines the appropriate height.

Requested Width The width of $width

=

the widget can be determined

$widget->reqwidth(

by using the reqwidth method:

)

Actual Width To

get the width of the widget as

$cur_width

When

=

the widget

$widget->width( is first

created,

ished drawing everything. After

it

currently

is

drawn, use the width method:

)

width

that,

it

will return a 1 until the application has fin-

will return the actual

Actual Height To

get the current height, use the

$h = $widget->height

(

)

height method:

width of the widget.

297

Widget Position

width method, height returns a 1 when the widget is first created. You can use the update or the af terldle method to force everything else to happen and then call height or width to get the finished values.

Just like the

Widget Position The methods

in this section all deal

with the position of a widget.

Position Relative to the Root Window To determine which widget

is at

the point x,y;, use the

containing method:

$which = $widget->containing($x, $y)

The $x and $y coordinates must be

Windows found

system, the desktop).

those coordinates.

at

nates, the

one

If

relative to the root

An empty

string

window

returned

is

if

(or

on

there

a Microsoft

no widget

is

there are several widgets located at those coordi-

closest to the front

is

returned.

Coordinates Relative to Parent You can

get the coordinates of the upper-left

y methods. The

comer

of a widget by using the

x and

coordinates they return are relative to the parent of the widget:

$x = $widget->x() $y = $widget->y()

Coordinates Relative to Root Window To on

get the coordinates relative to the root

window, you can use rootx and rooty

the widget: $x = $widget->rootx $y = $widget->rooty()

( )

The coordinates

refer to the upper-left corner of the widget.

Virtual Desktop Coordinates If

you have

a virtual desktop, there are special

relative to the virtual desktop. Virtual

dow

System (such as the

Microsoft

Windows

methods

desktops are very

fvwm and tvtwm window

as well.

that will give coordinates

common on

the

X

Win-

managers), but they exist on

;

;

; ;;

;

; ;

298

Chapter

To determine the height and width and vrootwidth methods: $height = $widget->vrootheight $width = $widget->vrootwidth()

To

1 6:

Methods for Any Widget

of the virtual desktop, use the

vrootheight

( )

get the coordinates of the widget's upper-left corner relative to the virtual desk-

top, use

vrootx and vrooty:

$x = $widget->vrootx $y - $widget->vrooty()

( )

All four of these

methods return an empty

Cursor Coordinates Relative

string

to

if

a virtual desktop

on the screen

not found.

Desktop

You can use pointerx, pointery, and pointerxy clicked

is

to determine

where the user

in a widget:

$x = $widget->pointerx() $y = $widget->pointery() ($x, $y) = $widget->pointerxy{) All the coordinates returned are relative to the

desktop (even

if it is

a virtual desktop).

Screen Information The following methods virtual

all

return information based

on the screen (which can be

a

desktop or a normal desktop) and the colors of the desktop.

Screen

Name

Each screen you use has a name associated with

it.

To

get the

name, use the

screen method: $name = $widget->screen()

The name returned will be formatted as " displayName, screenlndex" " as the screen name. dows 95 machine returned " :

Screen Height

.

My

Win-

.

and Width

The screen height and width is really just the resolution of the screen. Sometimes you might need information to determine how large a window can fit on a user's display. To get the height and width of the screen in pixels, use the screenheight and screenwidth methods: $height = $widget->screenheight $width = $widget->screenwidth()

( )

299

Screen Information

If

my

resolution

returns 1024.

If

is

768x1024, then screenheight returns 768 and screenwidth

you prefer

to get the size of the screen in millimeters, then use

screeninmheight and screeninrnwidth: Sheightmm = $widget->screermimheight

( )

$widthinm = $widget->screenirinwidth()

;

The same

resolution, 768x1024, returns 203 millimeters as the height

meters as the width for

Cell

my

and 270

milli-

monitor.

Count

The number

of cells in the default colormap

$count = $widget->screencells

My Windows

95 machine has 64

retrieved

is

by using screencells:

( )

cells in its default

colormap.

Screen Depth To determine

the

number

of bits per pixel your screen has, use the

screendepth

method: $depth = $widget->screendepth()

The depth of

my Windows

95 machine

is

16 bits per pixel.

Color Type The type

of color

is

defined by

class,

and

it

will

be "directcolor", "gray-

scale", "pseudocolor", "staticcolor", "staticgray", or "truecolor". To determine the class for the screen that contains the widget, use screenvisual: $type = $widget->screenvisual

To determine

(

)

the class of color for the widget

$type = $widget->visual

itself,

use visual:

( )

To find out the entire list of visualsavailable method:

classes available for the current setup, use the

©list = $widget->visualsavailable

Each element instance,

color

on

16".

in

@list describes

my Windows

the visual

and the color depth

for that visual. For

95 machine, ©list contained only one item: "true-

;

;

;

;

300

Chapter

Methods for Any Widget

1 6:

Server Type The type of

server

is

available through the

$server_type = $widget->server

My Windows

( )

95 has a server type of "Windows 4.0 67109975 Win32".

Widget Viewable?

Is the

A

server method:

widget

You can

is

determined viewable

ask the widget

$isviewable

viewable

itself if

if

it is

the widget

$widget->viewable

=

returns

all

of

its

ancestors are mapped.

( )

the widget can be

1 if

and

viewable by using the viewable method:

viewed and

if

not.

Atom Methods Each widget

is

name (you can

assigned a name, which get

it

for

These methods are used

To

an atom. The atom has a

called

is

name method) and

each widget by using the

internally to

string

a 32-bit ID.

handle things such as the selection mechanism.

name

get the 32-bit ID for a given widget, send the

atom

of the widget to the

method: $id = $widget->atom($widget->name(

You can do so,

the opposite

)

)

and use the ID

to get the

name

of the atom back.

To do

use the atomname method: $naine = $widget->atoninaine($id)

;

Ringing a Bell To make

the computer

$widget->bell

( )

beep

at the user, call

bell:

;

Clipboard Methods The following methods manipulate the dows clipboard (either Unix or Win32).

To add

data to the clipboard, use the

internal

call

a value.

Win-

)

clipboardAppend, you can

-format option with

also the

clipboardAppend method:

$widget->clipboard;^pend( "data to add"

When you

Tk clipboard and

The -format by

specify a format by using the default

is

"STRING", but

it

can

Selection

also

Methods

301

be "ATOM". Another option can be specified, -type, which takes a

as

"STRING" or "FILE_NAME".

To

clear out the clipboard, use

$widget->clipboardClear

Any To

(

string

such

clipboardClear:

)

data in the clipboard will be removed.

find out

what

is

in the clipboard, see the

selectionGet method

in the sec-

tion entitled "Getting the Selection."

Selection

Methods

Some widgets allow

the user to

tion

make

and

a selection in the text, entry,

a selection. For

listbox widgets.

example, the user can make

You can manipulate

the selec-

X

selection)

by using the following methods.

Clearing the Selection To

from any widget

clear the current selection

(this will also clear

an

use SelectionClear: $widget->SelectionClear

You can

specify a

;

-selection

BOARD". The default

is

option,

which takes

either

"PRIMARY" or "CLIP-

"PRIMARY". Using "CLIPBOARD" clears out the clipboard

as well.

Getting the Selection To determine what

the current selection for the application

$selection = $widget->SelectionGet

You can

also specify the

is,

use SelectionGet:

( )

-selection option with

the

SelectionGet method:

$clipboard = $widget->SelectionGet (-selection => "CLIPBOARD");

The -selection method takes either "PRIMARY" or "CLIPBOARD". The default is "PRIMARY", so if you don't specify -selection, you will get back the value that represents the current selection in the application. Using "CLIPBOARD" will return the value in the clipboard.

Assigning a Callback You can

call

invoked

when

SelectionHandle

to assign a callback that will automatically

the selection associated with

$win changes:

$widget->SelectionHandle($win => \&subroutine)

be

;

;

;

302

Chapter

When $win owns

specify the options -format, -type,

with the same possible values

shown

SelectionHandle with an empty callback

is

Methods for Any Widget

the selection, the callback will be invoked (in this example,

You can

siibroutine).

1 6:

in the

and -selection

preceding code example.

If

you

call

string as the callback, the previously assigned

removed.

Determining Owner You can find out which widget on the screen currently owns the selection by calling SelectionOwner (a widget owns the selection if it has something selected in it): $widget = $widget->SelectionOwner

You can BOARD"

( )

;

-selection option with who owns the

also specify the

as the value to determine

"PRIMARY" or "CLIP-

either

selection, or the current clip-

board value, respectively.

Owner

Setting the To

force a widget to

own

the selection, call

SelectionOwn:

$widget->selectionOwn()

You can

also specify

which type of

selection to force

by using the -selection

option with "PRIMARY" or "CLIPBOARD". Finally, you can specify a -command

option with an associated callback that will be invoked tion

is

when

that widget's selec-

forced away.

Destroying a Widget You can

destroy

Tk: Exists :

is

by

widget

a

calling

destroy on

the

widget

(using

if

recommended):

$widget->destroy() if Tk: Exists ($widget) :

If

the widget

is

a parent of

any other widgets, the other widgets are destroyed as

well.

Focus Methods When

your application

is

running, you can force a widget to have the keyboard

focus by calling focus on that widget: $widget->f ocus

You might want start

typing

first.

(

to

)

do

if you have an entry widget into which the user should focus right before MainLoop causes the widget to get the

this

Calling

Grab Methods

303

you press the Tab key, the focus automatically changes from the next (remember that you can tell when a widget has the focus

focus right away.

one widget

to

If

by the highlight rectangle around

it).

There are several methods that allow you to

manipulate the focus.

To make

the focus follow the

mouse around, use focusFollowsMouse:

$widget->focusFollowsMouse(

)

method is buggy under both Windows 95 and Unix. A patch just recently came out for Tk8, so if you want to use this method and it isn't working, make sure you get the patch.

This

To

find out

which widget has the

$who = $widget->f ocusCurrent

To

(

focus, call

focusCurrent;

)

even

force a widget to have the focus

if

the application

isn't

currently active,

f ocusForce:

call

$widget->focusForce()

This

To

is

not a nice thing to do, so

find out

none of the widgets

To

not use

which widget had the focus

$which = $widget->f ocusLast If

try to

in the

find out the order in

(

it.

last, call

f ocusLast:

)

window

has the focus, the toplevel

which the focus

will

is

returned.

change, you can use the focusNext

and focus Prev methods: $nextwidget = $widget->f ocusNext $prevwidget = $widget->focusPrev() ( )

Grab Methods When

a

mouse

input to

window does

a "grab"

it

window

means

that

it

holds

all

of the keyboard and

windows in the application to receive input. There is also a global grab, which means that no applications in the entire system can get input except the one window that has done the itself.

global grab. These

To do

methods

will

not allow any other

are usually called from a toplevel widget.

a local grab for the widget, use grab:

$widget->grab(

A

That

)

means that you can interact with other windows in the system but not with other windows in the application. To do a global grab, use grabGlobal: local grab

$widget->grabGlobal

( )

; ;

;

;

;

304

Chapter 16: Methods for Any Widget

$widget->grabGlobal

To

(

)

"ungrab", call grabRelease:

$widget->grabRelease

To

find out

(

)

;

which widget has done

$who = $widget->grabCurrent

To

a grab, call

( )

find out the current grab state of a

$status = $widget->grabStatus

The grabStatus method

©windows

=

$widget,

$widget->grabs

Interapplication

call

grabStatus:

;

( )

returns a string that

To find out all the windows grabs to get a list back:

grabCurrent:

is

that are currently

"none", "local", or "global".

under the influence of grab, use

()

Communication

You can

use the send command to have Perl/Tk (and even Tcl/Tk) applications communicate back and forth. The arguments include an application to talk to and the

command

to execute in that application.

$widget->send( "application" => callhack)

You can

also specify the option -async,

which

will return control

immediately

instead of waiting for the callback to execute.

By

default,

your application

an error to another application trying to

will return

you want to actually receive communications from other applications, define Tk :: Receive $widget "coitimand") and be very careful with what you do with the command string. Allowing any application to send communicate with

it.

If

,

(

unknown commands

When script

to

your application can be dangerous.

doing interapplication communication, with the

-7" switch,

which forces

Waiting for Events to At certain points in your application, pens. For instance,

if

you

is set.

To have

a

program wait

it

is

a

good idea

your Perl

Happen it

makes sense

to wait until

something hap-

window and want you can use waitVariable to

until a variable's

$widget->waitVariable(\$var)

to run

checking.

create a ColorEditor

color the user selects to a variable, variable

taint

value

it

is

changed,

call

to assign the

wait until the

waitVariable:

Waiting for Events to Happen

305

Processing will continue as soon as the value contained within $var

something

different.

To

wait until a

$widget->waitVisibility(

To

wait until a widget

$widget

visible,

is

is

changed

to

use waitVisibility:

;

)

destroyed, call waitWindow:

is

$widget->waitWindow()

When you

call

these methods, nothing will

happen

in

your program

until the

requested for event has taken place.

An

alternative to

waitWindow

widget methods are

still

$widget->OrLDes troy (sub

File There

is

available ...

{

OnDestroy, where you specify a

when you });

a special

is

method

when

a

shows how

it

notified

in Perl/Tk called

file is

fileevent. You can use

readable or writable. Here

meant system because we use the Unix tail command):* that

use Tk; open (FH,

can be used

(this

code

"tail -f -n 25 text_file|")

|

is

an example snippet of

die "Could not open file!\n";

-width => 80, -height => 25) ->pack( -expand => 'readable', [\&insert_text] )

sub insert_text {

my $curline; if

($curline = )

{

$text->insert end' $curline) $text->yview( 'moveto' 100); (

'

,

,

}

else {

$mw->f ileevent (FH,

'

readable

" '

,

" )

}

}

Thanks

to

my

friend Phivu

Nguyen

for sharing his

code with me.

watch

be executed on a Unix

|

(FH,

to

is

;

$mw->fileevent MainLoop

it

to

my $inw = MainWindow->new() my $text = $mw->Scrolled( "Text"

*

The

Events

and be code

callback.

use OnDestory:

1)

;

;

Chapter 16: Methods for Any Widget

306 This short program

an

around and waits

sits

box with

insert into a text

the

until a file is readable and then does newly read information. You can also use

'writable'. $inw->fileevent (FH, If

you get

'writable',

callback);

rid of the callback portion, the callback will

callback with an

empty

string (" ")

and the callback

be returned. Replace the

removed.

is

Parsing Command-Line Options it is standard practice to specify command-line options when you are invoking an application, especially a graphical program. Starting your program as myscript -geometry "80x40" would not be unusual. To have Perl/Tk automatically parse and apply these command-line options for you, just call CmdLine immediately after you create your MainWindow.

In the Unix world,

$inw->CmdLine

In Tk4,

if

)

;

you want

and leave some ments you want



(

for it

to

have CmdLine stop processing command-line arguments

you

to deal with,

add a double dash

to leave for you; for instance,

(



)

before the argu-

myscript -geometry "80x40"

-rayopt.

In Tk8, the processing of options will stop

when

the

first

unknown

option

is

found.

Another way to deal with command-line options

is to use the Perl Getopts modProgramming Perl (O'Reilly, 1997) to find out how to use the methods available in Getopts. The methods inside Getopts don't handle the options for you; it just puts them in a structure that's easier to deal with.

Take

ules.

a look in

Tim.e Delays when you'll want to be able to delay the program a bit before going on, or maybe you'll want to execute the same command every minute. To have the program sleep for x number of milliseconds, call after with the number

There are times

of milliseconds: $widget->af ter {milliseconds)

To

;

many

specify a callback that will be called after so

ing,

send a callback as the second argument

to

after:

$id = $widget->af ter (milliseconds, callback) #

i.e.

$id = $widget->af ter (1000, \&do_something)

milliseconds instead of wait-

307

Time Delays

If

you want to execute af terldle:

a subroutine after the

program has been

idle for a while,

call

$id = $widget->afterIdle(caIIjbacA:)

To

cancel the

call

to

after

;

or afterldle,

use afterCancel with the $id

returned by after: $widget->afterCancel ($id) You can also do this: $id->cancel #

( )

You can have

the

program repeatedly

call

the

same callback by using

the

repeat

method: $widget->repeat (milliseconds, callback)

;

# i.e.

$widget->repeat (600, \&update_status) If

you destroy $widget, any

celed for you.

calls to

after and repeat

are automatically can-

Configuring Widgets with configure and cget Every widget included

(and some not included, but

in the Perl/Tk distribution

available separately) can use the

configure and cget methods. No matter

the

widget, the arguments to these functions are the same, and the results passed back

have the same format.

The configure method allows you the widget.

It

to assign or

change the value of an option to

can also be used to retrieve the current value of the option. The

cget method cannot assign than that of configure.

values, but simply retrieves

them with simpler syntax

The configure Method The

basic format of the

$widget->conf igure

(

configure method [

is

as follows:

option -> newvalue,

Depending on the arguments passed

to

it,

...

]

)

;

configure method can do

the

three

things:

change the values of the options

$widget



Set or



Get the current value of any option for $widget



Get the current values for

To

set or

change the value

have appeared

in the

all

for

for

of the options for

$widget

an option, send the option pair exactly as

it

would

widget creation command:

$widget->conf igure -option => newvalue); (

309

;

310

;

;

Appendix A: Configuring Widgets with configure and cget

Whatever

effect the option

has will take place immediately. To see the current val-

ues for a single option, send the option you are interested

depends on whether configure

return value

configure

context. In the following line,

value

is

being assigned to an

called in

is

in as the

called in

is

list

list

argument. The

context or scalar

context (since

its

return

array):

@info = $widget->configure(-highlightthickness) In

context, an array of scalars

list

is

returned.

The

results of this call

-highlightthickness highlightThickness HighlightThickness

The following

2

look

like this:

2

five values are in the returned array:

Option name Option name from the option database (also as appear in the .Xdefaults file)

1

2

Class in the option database

3

Default value of the option

4

Current value of the option

Often, call

you're interested in

all

configure

is

would

it

the current value of the option.

by

in scalar context

If that's

the case,

assigning the result to a scalar:

$val ~ $widget->configure -highlightthickness print "$val\n"; (

The

If

result

would

you want

)

be:

to see the

list

of values for

all

of the options the widget supports, use

this format:

@config

@conf ig

=

$widget->configure{)

now

is

an array of

to utilize Tk::Pretty,

which

arrays.

will

do

The all

easiest

the hard

then put the information into a readable form: use Tk; use Tk: Pretty; :

$widget = $inw->Button;

©config = $widget->configure; print Pretty ©config;

way

to print out this information

work of

traversing the arrays

is

and

The configure Method

The

result

311

as follows:

is

-activebackground activeBackground, Foreground, ttececec ttececec -activeforeground' ,activeForeground, Background, Black, Black] -activeimage activelinage, Activelinage,undef ,undef '-anchor' 'anchor' Anchor, 'center' -background background Background, #d9d9d9 center #d9d9d9 -bd '-bitniap' 'bitmap' Bitmap, \indef,undef] borderWidth] '-bg' 'background' -borderwidth borderWidth, BorderWidth, 2,2], -command command Command, undef, bless [CODE (0x8189888) ,Tk: Callback) '-cursor' 'cursor' Cursor, undef ,undef -disabledforeground' ,disabledForeground,DisabledForeground, #a3a3a3 #a3a3a3 -fg' foregroiind' -font font Font, -Adobe -Helvetica-Bold-R-Normal *-i20-*-*-*-*-*-* -Adobe-Helvetica-Bold-R-Normal *-120-*-*-*-*-*-* -foregroiind' 'foreground' Foreground, Black, Black] -highlightbackground' ,highlightBackground, '-height' 'height' Height, 0,0] HighlightBackground, #d9d9d9 -highlightcolor ,highlightColor, #d9d9d9 HighlightColor, Black, Black] -highlightthickness highlightThickness HighlightThickness,2,2] '-image' image' Image, undef undef] ,[' -justify justify' Justify, 'center' 'center' -padx' ,padX, Pad, 3m, 9] -pady ,padY, Pad, Im, 3] -relief 'relief Relief 'raised' 'raised' -state' 'state' 'normal -takefocus takeFocus, TakeFocus, undef, undef State, 'normal -text text Text undef Do_Something] -textvariable textVariable Variable, undef undef -underline' 'underline' Underline, -1, -1] -width' 'width' Width, 0,0], -wraplength' ,wrapLength,WrapLength, 0, 0] [

'

[

'

,

'

,

'

'

'

'

[

]

'

,

]

[

'

'

]

[

'

,

]

,

,

'

[

[

'

[

'

'

'

,

,

,

,

'

,

[

,

'

'

'

]

[

,

'

,

]

'



,

'

'

'

,

'

'

,

,

'

'



[

'

]

,

'

,

,

[

,

[

,

'

,

[

,

'

'

'

[

'

]

'

,

'

'

,

'

[

,

'

[

,

,

]

[

,

'

,

,

]

]

'

,

]

[

,

'

,

]

,

[

,

'

,

[

,

'

'

,

,

'

[

,

'

[

'

'

[

,

'

'

,

'

,

,

'

,

'

'

,

,

,

'

[

'

,

,

'

]

]

'

[

:

]

'

,

,

(

]

[

'

'

,

,

'

'

,

,

'

'

[

'

,

,

,

'

,

,

[

,

'

,

'

,

[

,

'

,

,

'

,

'

,

may look nasty and ugly, it distinguishes between the different you by adding the and characters and the commas that separates them. Usually, you would only look at this list for debugging purposes. The default values for each widget are listed at the end of this appendix.

Although lists

of

this list

lists

for

]

[

The cget Method Instead of using

configure

to retrieve values,

you can use the cget method:

$widget->cget (-option) It

only returns the current value (or address

option rather than the entire

list

ing for "configuration get." Here

that is

if

the option stores a reference) of the

configure

an example of

print $b->cget (-highlightthickness) ## Prints this:

,

returns.

how

"\n";

2

# return reference print $option_menu->cget (-textvariable) "\n"; # return actual value " \n" print $ { $option_menu->cget -textvariable } :

,

:

(

)

# or...

$ref = $option_menu->cget (-textvariable) print $$ref, "\n";

,

Think of cget as stand-

to use cget:

;

312

Appendix A: Configuring Widgets with configure and

cget

Default Values for Each Widget in Table

Form The following tables contain all of the options for each standard widget (in Tk8). The five columns represent the five values returned in the arrays for each option when configure is used. Note that column 5, "Current Value," will probably not

mean much to you, but I've included when you run the same code. The information

in the tables

( )

for

completeness because you'll get

was created by using

the correct widget in for Widget): $w = $inw->Widget->pack; @conf ig = $w->conf igure print Pretty ©config;

it

this

code snippet

it

back

(substitute

Default Values for Each Widget in Table

Form

313

4J

4J

^

ic V t 3

u

0)

S

s

^

^

^

^ O o p ^ 4J d md PQ

^

r-H

4-)

4J 4J

(D

jj

^

g m

g

4J

4J

W

W

q3

^^ OJ

Q)

4J

a

^ ^

s U

^ m ^

V.

Q) r-l

s 4J w

4-1

4-1

4-1

0)

0)

0)

T!

Ti

T3

^

^

^w H Q CO

^

U (d

h

^

^

^

5

^ -d Ha

R

^

'ii

o

Eh

4-)

4-)

4J

4J

S

00



r-^

^

5

PQ

pQ

u

rH

(1)

CO

P

dJ

CO

CO 4H CO -rl

CO

0)

3

u

4J

M-l

W

W

T3

^ ^

B

4-)

0)

u ^4

^

^

CD

o

^

CO

4J

4-1

4-)

4->

TS

•H

CO

j3

p

^ '3 Hd

m

r-l 4-1

4-1

1

CO

1

0)

4-)

i 4J

1

OJ

4-)

4-)

•d

Tl

^

CO

3

lU

Q i 1 4J

^

OJ

S

(C3

•H

0)

o

1

4H

-H x;

QJ

H

&i

4-)

Htn H w K ^

tn

-H

•H

lU

CO :=!

h3

Ti

02

u

fe

^

^

-H

•H

4-)

4J

U

u

O

p o

9i

Sh

M

^ ^

^

CO CO

^

Ti

5

5

T3

•H

H

S

IS

a H^ ^ M^ 13 M§, ^H -o u U U u u § ^ ^ ^ B 4-)

o

-H

S^

(d

4-)

d g H o u

o M ^ s

H

d)

rH

^ 0)

73

CO

^

4J

^ (U

M o

c

^ o

4H

4H

4-1

4-)

01

^tn ^tn

Di H rH

•H rH Xl

X3

•H

tn

tn

^

-H XJ

xl

u

'd

p O

o

o

tn

^ ^ c o *^

g

p fe

s cq

U

(0

a ^

o

>

•H

4-)

r 1

0)

^

(1)

Cn

T5

4-1

M

B o

•H

m

-r-(

OJ

QJ

>

>

H H 4J

4.)

^ 1

^ '

M o ^u § '

a

^

p

4^

u

4!3

^ s '

1

B 1

•H 1

S s

4H Ti 13

Q)

(ri

T!

g K o u

U

^ 1

d

o 4J

1

^^

rH

W

13 (0 4-1

t3 1

1

OJ r-\

^

4-1

CO •'^ 1

-H

0)

4-)

tn

X!

CO

1

•n

4H H 4J

5!

M o rH O u

Xu

2!

13

S-l

>1

4H (U

CO CO

1

>!

-H rH X! •H

'd '3

u

u

4J

X!

o

^

nJ 4-1

d

-d

^

4H 1

tn

tn H rH

(U

XI

tn

•^

rH Ti x^ g

O

n o

4H

1

4J

XI

tn

U

fi

1

H Htn ^ 1

4-)

4J

XI

X^

4-1

X!

4J

tn

tn

•H

x;

H o u OJ

^u

1

_ 3 o

0)

•H rH Xl tn

tn

-H

-H

XI

Xl

1

>i

1

CO

n 13

.g 1

1

M

Appendix A: Configuring Widgets with configure and cget

314

u 3

u 3 13

> 4^

c V h

CU

0)

u

u

(d

(d

1'W 1o

^

4-)

4-1

4J

4J

3 u fc

U

-d

rH

OJ CO

(rt

iH (fl

rH

iH

M

g f^ o a

3

m

U

14H

0)

0)

-d

T)

4H 4J

d

5? T-K

^

n

p9

1

^

o o

o

rH

^^

4->

in

CO

CN

^

0)

u 3

V

—3 rt

> 3

u (d

1 1 v^

4-)

1 4J

4J

4J

PQ

(jQ

3

ri H

vJ2

8 o

M-l

dJ

(1)

fe

-H

4J

0)

rH

(d

5

0)

y 3 d 5 -d

-H 13

4-)

> 4J

rH

W

0)

i

J A 4J

A:;

u

CO

^4

4J

4J

u CD

c c

1

CO

.9

a

8 o

4-1

o

0)

rH (d

(0 1

HH 0)

•H rH 4J

(d CO

1

1

>

4-)

4-)

1

1

^4

A

1

rH

4-)

%

0)

04 1

0) 4-)

5

0)

-H

'd

(d

u a 3 3 O

^

8

-d

M

0)

AJ

U

^d iH

5

Ti

-d •H

3 o

a

H.

o

s>

0) CO

-H

M O

4H

CO

o rH o

C O U

^ 6

a

^di 4.)

^bi •H

^

•H

3Cn •^

1

0)

T)

Ai

O

iri 1

^

^ ^ ^ ^

§

4J

5 •H

^ ^ 1

316

Appendix A: Configuring Widgets with configure and cget

4J

a

O

to

mo

W M

-H

(U

M-l

u

T^

o

u o

o

Io

Iu

Iu

1 Q)

d

1O

O •H

u

4->

U

D>

(0

o

c o

0)

u o

a

O

T)

•H JJ

u

a

o

I

u

5 s

5'

Default Values for Each Widget in Table

Form

317

u 3




S

1

1

rH

(d

1

1

Appendix A: Configuring Widgets with configure and

320

4-)

u 3

0)

a

(C

ca 4-1

u

^

t

M

o

C u 3

4-1

S 00 ^"^ u

•g

0)

5/

4->

4J

m u

M-l

4-1

^ -g

i 4-1

4-1

•H

3

Id

0)

•H '3

"3

rH

(d

rd

-d ca 05

u M

1

r-l

•H

c i 4-1 (1)

^

>j

-H

'3

rH

a a

S

S

to CO

u

1u

1

M

U

c c o •o

a

^^ ^ H

5

'd

4J

-d •H

^

^u ?

o Ot

1u

-S ll

S 1

g

1

1

u

4-)

)~i

4J

^

a

^ V
i

•H

^ i13 a a

•H

-H 1

(U

rH

T)

1

1

'S

^

•H

§

4J

B

4J

4J

4J

1

1

1

•H rH 0)

a 1

1

Default Values for Each Widget in Table

Form

321

4->

o

x>

3

CQ

MH

'B

>

CO 4^

4_)

a u k4

Eh

^

u

u r-i 1

W m rH

O o

^

4-1

-H 0)

CO

u 3

> 3 rt

u

Q rH 1

o o d

V s rS c

^ m

f1

u H rH

Vh

^

(1)

J-)

v.

Tl -H

r^

'^

T)

4-)

(1)



% hJ

Pi frt

D s ^

a u

t:!

C^

a («

ii

3

S

S

Eh

u 3

V 3

4-)

a >

•S.

Cn

13

>

•H

e

^

rj

c u H 3

Cn

•H

s

y

u

g 4J SP

iH

U

0)

MH ii '§

^ o

^ ^ o

MH

O

J '2

4H Jj •O

H 4J

4-)

^Cn

X! Cn

•H

•H

rH

^Cn

rH Xi

•H

•H

di

s

"5

S 4J 5P

13 •H

g

^u

0)

^ o

m >

•H

-H

•H

4J

4.)

4J

(0

^

1

'

^ '

O

1U

}H

rH

H g

^

-9

'S V4

^ s s ^ 1

MH

-H

a;

>

1 o

5 d

13

'

1

1

O

4-)

tH

^cn

fl

5 5 M

S

Eh

i 3 ^U Q

u

4-)

§i

u 3

§

0)

1

4-)

a o

cn

1

MH

14H

1

'

Default Values for Each Widget in Table

Form

323

u

u

Ti

1 u

'^

^ X c>

^ a

fl)

IH

O

fa d)

(1)

> -H

H>

4->

4-)

C) (C

t) (0

"d

'd

^^ s

s

'^

T?

^ s s •^

O

o u

s

^

324

Appendix A: Configuring Widgets with configure and

W W (U

4-1

-H

U

rH Xi CO

'd

1 u O

"^ 4J

-a 0)

rH

H iH

•H

H

^D) ^Di

^

CO

m

'^

u

& 4-)

9^

1

s

u o

-H

% 3

'd

^

f?

OJ

rH 0) -1

^

If)

;c!

h-1

•H

4J

Ui

rH

T)

(Tl

^

t

•g

u

i

c c o

^ 4J

(1)

^

-H

^

rH

rH (1)

A'

1

^

T)

hi

0)

fl

:3

rH

1

^ ^ 4J H -0 1

1

rH Ul

1

I

^

326

Appendix A: Configuring Widgets with configure and cget

V 3

d)

V r^

o 1C ^ V P t 3

£ m u

u

1

r-\

Q C

rH

"3

4J

3

U rH

•^

1

1 5J

Q)

4-)

4-)

fp

5?

^

^

0)

1

1 1 U

'0 1

u

m ij d

-H 4-)

^ rH

CN

^

4J

T)

rH

OJ to

frt

•H

fO r-i 14H

00 rH

rH

rH

n

s

g ^ g

^

MH

5/

Q)

4J

T)

CO

rH

V 3

4J

&

TJ

u

§

Cfl

0)

U

fe

a y>

^u

U

3

4-)

4-)

3 vH

3

o

rH

Q

pQ

PQ

13 4J to

^

w

U

c •H

rH

pQ

Ig

(d

4.)

4J

to

CO

^

^

H

^u

rH

%U 1 o 4J PQ ^tn 4J

^ •U

^ ^ ^ ^

^

u

U

>i M-l

&

CO CO 0)

B u

?

328

Appendix A: Configuring Widgets with configure and cget

4-)

C o

^

1c u jj

5 o c

to

o

CO 4J

^

4-)

rH

T) •H

•a

X

Ai

4J

73

CO

O

g

rH

^u *H

•H

r-l

CN

cn 0}

•H

4-)

4-)

AJ

OQ 4J

en

4-)

m

B o

V g

1

)H

73 -H

CJ

4H

4-)

>i

^ 73 a a

0)

u

-H rH

rH

0)

0) 0) (0

4:3

73

4J

73

73

u

1

•H 4J

c c o

U

5

73

O

^U

0)

^ o

n3

CQ

M

4-)

u 4J

Qi Cn

I

1

1

1

^

M-l 1

1

1

a o

M 1

§

(U

4-)

k

4J

•H

-H rH Xi D)

3M 5

H

3Cn

4-1 1

CJ

3 > U

1

1 ^Di 0)

O rH O u

•H

4-)

73

0)

iH

tj •H

>H

1

11

?l

OJ to

•H 1

1

1

'i->

>H 0) to

.2 1

4H 4H

1

1 S 73 4->

CJ

4-)

4-)

^

1U

4H

U

(U

u

0) to

0) to

0) to

-H rH

rH

C!

c

2

0) to

•H 1

•H 1



^

-H 1

1

1

1

^

0)

1

Default Values for Each Widget in Table

Form

329

XJ

s Eh

u 3

^

IS

•H rH 41

V 3

4-)

u

1a

tn

•H

U

MH 4-)

W

f^

o ^ o o o

d

8

MH -d

B

00

MH

0)

0)

Ti

TJ

u (0

^

?^

4J 4J

u 3

•i

U

rH

0)

rH

4J

rH

a g

W

1

C^

0)

-d

B

4J

S tn -y

u 3

(U

u 3

^en •H

? 3

! 1

:3

3

^ H

!

0}

^

o

O

u ^ ^01 ^01 4->

4-)

•H

•H

rH Xi

rH

•H rH

4-)

H

^d) •H (U

Ho

^01

^

-g

i

Q)

^

u o •-\ o

01

H

b K X

^01 ^01 •H

m

g u

o

c

>;

-H ffi

u o o

u

rH

3

^

4H

4H

Q)

0)

0)

0)

•H

-g

r-H

^ ^

(V

B

B

^

Pi

8 o

r-i

b

4H

d)

0)

^ M Eh

'S

s a> u u

B

(0

3 a) CO

Xi

V

CO

-d

•H

•H

D > S

1u *H

-g

g

^

u ^

u

o

o

S

^ S

-H

•H

•H

fe

§,

rH

rH

Q)

0) Vh

rH jd 0)

•^

•^

CO

0)

4-)

9^

4H 4H

U

X3

^

CO

o w 6

U O 4-1

o 4-1

di

H ^

0)

8

01

^01 ^01

4H

3

4H 0)

g

4H iJ -g

•^

4H J^ TJ

•H

B

S

0)

rH

s (U u u

o

rH 4-1

QJ

(0

3

J^

c 4-)

0) CO

CO

3

>

§ TJ •g

w V

u

i
H

^Qu

M 5^

4H 0)

% ^ ^ p,

•H rH

s U V

s o 0)

0)

rH 4-)

CO 1

1

rH

4H

1

3 0)

CO

•H

•H

4-)

>

1

1

1

i -d 1

operating System Differences

Perl

was

Unix systems. The Tk module was meant

originally written for

X Window

with the

System, which

is

the graphical user interface associated with

Unix. Since then, Perl has been ported for use

on many other

platforms, including

Macintosh and Microsoft Windows (both 95 and NT). The same

module, although the ports for

have Perl available on

all

it

for use

followed along a

bit

more

is

Tk

true of the

now we X Window

slowly. So

platforms and Perl/Tk available for both the

System (which can be emulated or run on many different platforms) and Microsoft

Windows. There are very few differences between

Window System and how ences

come about because

functions that the

how

Perl/Tk operates on the Unix

Microsoft

X Window

Windows

doesn't have

System has. Throughout

this

all

of the different

book, you

may have

seen references to a method that didn't work on Windows 95 or that worked ferently

One

on Windows

big

Appendix

difference C,

Fonts,

95.

I

X

operates on Microsoft Windows. Most of the differ-

it

won't be covering

all

dif-

those minor differences again.

between Unix and Windows

is

how

to

specify

fonts.

covers font specifications in detail; see that appendix for

information for both Unix and Windows.

Unix book should work well under Unix systems. There might be subtle differences between the different flavors of Unix (such as what type of value you get back on a Solaris machine compared to the values you get back on a Linux machine), but nothing that will cause your program to crash.

All of the

methods

All of the

screen shots for

listed in this

system running the

this

book, except where noted, were taken from a Linux

X Window

System with Motif-style windows. The

window

331

Appendix B: Operating System Differences

552

manager I

used

I

was fvwm, but

specifically

don't cover the differences

style of the

dow

the style of

windows

between window managers and

window. There are many other books

System and the window managers

it

is

how

similar to

mwm.

they change the

available that discuss the

X Win-

uses.

Windows NT and 95 When you

window

create a Perl/Tk

comes up looking For instance,

it

will

have a small x

cation. Just to the left of that

To

the

left

for

x

all

of the Maximize button

be a small button

X Window

window

95, the

that

maximizes the window.

a small bar that will iconify the application.

is

that gives options to minimize,

standard features of an

in the

Windows

or

in the upper-right corner that will kill the appli-

will

In the upper-left of the application

menu

Windows NT

your other windows do for those operating systems.

just like all

is

a small "Tk" that,

clicked, will display a

if

maximize, or close the application. These are

MS Windows window. The same

System version of a Tk application;

it

functionality

just

looks a

is

little

present

different

(see Figure B-1).

Exit

Exit

Figure B-1.

Exit

A Win52 window and an X Windows window

Windows 95 Problems I

used both a Windows 95 machine and a Windows

NT

4.0 (Service

Pack

3)

some minor problems running applications under Windows 95. Windows NT did not seem to have the same problems, so if I had a choice between 95 and NT, I would develop and run Perl/ Tk on Windows NT. Here is a list of some of the problems I ran into while I was testing Perl/Tk applications under Windows 95 (note that these are not necessarily reproducible 100% of the time; I just wanted you to be aware that I did run into some minor problems): machine



I

created a

click •

to test the

on the

code

in this

book.

MainWindow with one

I

did find

button, resized the

window, and couldn't

Exit button.

The same scenario as the preceding after it was resized caused the button

item; clicking to

be pressed.

anywhere

in the

window

Windows NT and 95



When

I

333

tabbed between applications, clicked in another application, and then

went back

to the

icon in the

start

Tk app,

it

didn't recognize the

bar seems to

(There doesn't seem to be any solid

fix this.

reproducible cause and effect for loss of •

The -underline option doesn't seem underline a as a



menu

letter in a

mouse. Clicking on the app

mouse

to

recognition.)

work properly when

I

attempted to

option, so the corresponding key could be used

keyboard shortcut.

Some methods (most

of which you wouldn't use because they are obscure)

These were noted throughout the book as

didn't return a reasonable value.

they were discussed. •

When

I

clicked in a text widget to give

it

the keyboard focus and then clicked

elsewhere, the text widget didn't give up the focus. switch between widgets within the doesn't

seem

and won't •

When

I

to

want

to give

up

window once

the focus (the cursor stays as an

interact with the button at

tried to display a

option), the

photo

You can use

as

Shift-Tab to

text has the focus, but I

it still

bar cursor,

all).

an image

in a button (by using the

-image

photo looked garbled.

Other than these minor problems, most of which probably wouldn't apply to a run-of-the-mill application, everything

worked

well.

Selections

X Window

System, the user can select text by simply highlighting it. In Windows, you have to highlight the text and put it in the clipboard by typing CTRL-C (for Copy), pasting it back with CTRL-V or the equivalent for the In the

Microsoft

application you're running. Perl/Tk does not interact with the clipboard like

this.

There are several widgets that have an -exportselection option (such as

list-

box and text) and still work as indicated; if they won't copy the selected text to the clipboard.

are set to zero, however, they

Fonts

This appendix describes

how

to use the

new methods

in

TkS.O to create and main-

-font option. You can still some methods to create your own named fonts and perform operations on them. First I'll go over the simple way to use a font string, which works in both versions. Then we'll get into the more comtain fonts. In Tk4,

you could only pass

a font string to

pass a font string in TkS.O, but you can also use

plicated

methods

available with TkS.O.

The Font String When cates •

there

which

Specify the

explained •



name

you need to pass ways to specify a font

for a widget,

a string that indistring:

fontCreate method (fontCreate

of a font with the

later in this

Use the name of in

is

chapter in "Font Methods").

them and

can be interpreted by the graphics display

a font that

Unix system running

X Windows).

are very hard for

specify a font in a string,

your system.

334

-font option

Use a string that describes the font and follows a predefined format (see Appendix B, Operating System Differences); for example, "Times 12 Normal."

cally a

To

a

is

font to use. There are several

you

humans first

to

have

These

strings usually

have

(typi-

asterisks

comprehend. to

know which

fonts are available

on

335

The Font String

Determining Available Fonts In Unix,

you must specify

by using

fonts

a long, drawn-out syntax with a lot of

asterisks that represent families, size, type,

you can get

a

and so on. In the

X Window

System,

command

of Unix fonts by running the

list

xlsfonts > font_file

The file named f ont_f ile will now contain a huge list of fonts that you can use on your system. Be careful when picking fonts from this huge list. If you are going to be running your application from more than one system, the font you pick might not be available on all systems. you use Microsoft Windows, you'll have a different way of seeing what fonts are available. Click on the Start menu and select Settings -^ Control Panel. Once the Control Panel appears, double-click Fonts and a window similar to the one shown If

in Figure C-1 appears.

i\

Anal

Italic

13

Arial

Narrow

j] Bookman Bookman

^

Old Style

Q

Arial

Narrow Bold

|t|

Buccaneer Regular

|r] Antique Olive Bold

1'^ Arial

Narrow Bold

|%1 Antique Olive Italic

ffl Arial

Narrow

S Q @ 3

@

j^iAlbertus Extra Bolcl

Medium

I't]

Albertus

Q

Antique Olive

92

Aria!

Vt\ Burton's

Italic

N]

Italic

Nightmare

Celtic Gaelige

Regular

Black

gBard

Bold

[^Bookman

Old Style

gCG Times Bold

[^ Bookman

Old Style Bold

^ CG Times

Italic

;

Century

Arial

Anal Bold

Italic

Schoolbook m M CG Times

augie

Bold

Italic

font(sl

95 System

system has most of the standard fonts and a few that

Internet,

Old Style Bold

Aria!

Figure C-1. The Fonts from a Windows

My

Sirrilatityl

to specify them.

If

I've

downloaded over the

want to use these fonts I have to know how you double-click on a font name, another window appears and

such as augie and Bard.

If

I

displays detailed information about the font (see Figure C-2).

The information about

the font includes

drive (64K in this case), sizes.

The

Arial font starts at 12 points

option to specify

name

what version

of the font

this font for a (Arial),

it

how much is,

and

its

and goes up

space

name.

it

It

takes also

to 72 points.

up on

lists

To use

the

widget (for instance, a button), you need to

the size,

and the type (normal,

bold, or

the hard

the available

italic).

-font

know

the

With these

;

336

Appendix

B Aiiai (TiueType)

C:

Fonts

«FF^

Done

Rtint

Arial (TrueType) Typeface name: Anal

Version:

64 KB MS core font: V2. 00

Typeface

© The Monotj^e Corporation pic

File size;

Data © The

Monotype Co

ab c d e fg h

ij

kl

mnopq

r stu

vwxyz

ABCDEFGHIJKLMNOPQRSTUVWXYZ

J

1234567890.:, ;("*!?') 12

The quick brown

18

The quick brown

24

The quick brown

fox jumps over the lazy dog.

fox

jumps

V.

ovi

fox jur

Figure C-2. The Arial font details

three pieces of information, That's

all

there

is

to

it.

To

you can build a

font string:

"Arial

create a button with this font, use the

$nTW->Button(-text => "Exit", -command => siib { exit -font => "Arial 24 normal ") ->pack ()

24 nonnal' -font option:

},

Figure C-3 shows a button with the default font, and one with a larger font.

Figure C-3-

If

the

A

name

default size font button

and one

of the font has spaces in

the string the

it

with Arial

24

such as Times

New Roman, you

still

build

same way:

-font => "Times New Roman 12 normal"

* "

You might

also see a font specified with curly braces

{Arial} 12 {normal}

").

The

around the name and the

curly braces arc not required.

style of the font (e.g.,

Font Methods

You might

337

see an error on the console

when

using

this

type of font specification:

SplitString 'Times New Roman 12 normal' at script line

You can

7

I know, there is no easy way to get rid Tk module will deal more gracefully with this error no longer appears).

ignore these errors, and as far as

of them. Hopefully, later versions of the this (initial tests

I

don't

with Tk 8.0

recommend changing

because

you'll

that

on any of the standard widgets is available. The only place the text widget, and then only if

the font for the text

have to worry about whether the font

you might absolutely have you

show

to

change font

is

in

are actually going to format the text.

One more

thing:

There

is

a Tk::Fonts

module

available, but

it

doesn't

work

cor-

under Microsoft Windows (95 or NT). If you are using X Windows, you should play around with the Tk::Font a bit; it does have some useful features. rectly

Font Methods The following methods which contains Tk8.0.

are available only with the newest version of Perl/Tk,

Create The f ontCreate method

creates a

$widget->f ontCreate

$naine =

( )

new

font.

;

$naine = $widget->fontCreate(for2tr2an7e)

You can where

either specify a font

X is

a

name

or

;

one

will

number. You can specify options

be generated

in the format "fontJ^f

for the font:

$name = $widget->fontCreate(-size => 12); $name = $widget->fontCreate(fontname, -size => 12)

The options you can use

to create a font are as follows:

-family => name The family name can be "courier", "times", or "helvetica". If you specify one of these, the closest match on your system will be used. You can also specify the

name

of a font that

"Moon Runes"), but

it

-size => amount The amount specified for the be. If the amount is positive, negative, the font will pixels.

is

specific to

your machine

(for

example,

might not show up on other systems.

how

you want the font to If the amount is be sized by using the absolute value of the amount in font size indicates

big

the font will be sized in points.

;

;

;

;

;

338

Appendix

-weight => "normal" "bold" The -weight option determines

C:

Fonts

|

the thickness of the font.

-slant => "rcatian" "italic" The slant of the font is how far it tips over to one side. By default, "reman" means that the font is upright. Specifying "italic" as the value for -slant |

will

the font to the right slightly.

tilt

-underline => If you want

1

|

the characters to be underlined, specify

1

for the

-\inderline

option.

-overstrike => 1 A line is drawn through |

the text

when -overstrike

has a value of

1.

Configuring You can change

by using the fontConf igure configure method does on any widget:

the options associated with a font

method. This method works

just like a

%optionsNvalues = $widget->fontConfigure(fontna7ne) $value = $widget->f ontConf igure (fontname, -size) $widget->fontConfigure(foI:tJ:ame, -size => 24); # Change size to 24

You can use

the

same options with

f ontCreate

and fontConf igvire.

Actual Information If

a specified font size

another font is

size, or

actually displayed

and

their values, call

is

not available on the user's system, the system substitutes

even

a different font altogether.

You can

by using the f ontActual method. To get f ontActual with just a font name:

find out a

list

of

which font all

options

%vals = $widget->f ontActual (fontname)

To

get the actual value for just

one option:

$value = $widget->fontActual(fontname, -size)

Again,

the options used in f ontCreate can be used with f ontActual.

all

Deleting To

one or more

delete

fonts,

use the f ontDelete method:

$widget->fontDelete(fontname) $widget->f ontDelete (fontl, font2) If

the font

the widget

with the the

new

is

currently being used

isn't

name

using

it

anymore.

;

by a widget, If

you

it

will not actually

re-create a font

be deleted

until

by using fontCreate

of the original font, the widgets that use the original font will use

font information.

Font Methods

339

Text Size You can

find out

how much

space a text string that uses a particular font would

take by calling f ontMeasure.$pixels = $widget->f ontMeasure (fontname,

The value returned

$pixels

into

is

texts tring)

;

only an estimate because characters such as

"\t" or "\n" aren't expanded before the measurement

is

taken.

Font Metrics between lines, and fontMe tries method to fontMetrics with only a font

Metrics are details about a font: the ascent, descent, space

whether or not the font

is

proportional.

get this information about a

name

you

gives

all

named

You can use

font. Calling

the

the metrics and their values for that font:

%values = $widget->fontMetrics (fontname)

You can

also find out the value of a specific metric

$value

Note

$widget->f ontMetrics

=

you cannot change

("

fontname"

,

by passing

it

in as

an option:

-ascent);

They

when

the font

is

Measures the highest part of the font above the baseline. Amount returned

is

that

a font's metrics.

are calculated

created.

The

valid metric options are as follows:

-ascent in pixels.

-descent Measures the lowest part of the font below the baseline. Amount returned

is

in

pixels.

-linespace Measures the distance between two

Amount

returned

is

lines

of text that use the

same

font.

in pixels.

-fixed Returns

1

if

the font

is

amount of space, such

a fixed width font

(all

as in Courier). Returns

characters take if

the font

up

is

(each character takes up a different amount of space based on

skinny

it is;

the letter

"I"

takes

up

less

space than "M").

the

same

proportional

how

fat

or

;

Appendix

3*^0

Families

& Names

To

all

find out

the font families that exist

on

To determine

=

$widget->f ontFamilies

the

names of

all

( )

;

the fonts that are defined, call f ontJSFaines:

©names = $widget->fontNames

()

Fonts

a particular $widget's display, call

fontFamilies: ©families

C:

Index

Symbols ,

-

menubutton widget, 222

(comma), 6 (minus sign), 36-37

overview, 52 pack, 19 place, 48

=>, 6

\

radiobutton, 96

36

195

text item,

A

anonymous

appearance, widget (see

accelerators, 231 activate

method, 150

add method, 243-244 adding text, 197 Addltems method, 227, 234 addtag method, 201 Advertise method, 285 after method, 306 afterCancel method, 307 afterldle method, 297, 307 aligning text, 178

style)

application grid,

activating scrollbar elements, 136

all tag,

subroutines, 63

267

name, 265, 295 applications, communicating among, 304 appname method, 295 arcs creating,

option

188

188-189

list,

arrows line item,

191

scrollbar,

132

aspect method, 262

199

allocation rectangle, 22-28

expanding, filling,

Alt key,

19,

assigning) 19,

25

24

274

anchoring widgets allocation rectangle, 27

basic button, 58

bitmap item, 190 checkbutton, 83

createWindow method, 198 image item, 191 label,

103

assigning callbacks (see callbacks,

atom, 300 (see also widgets,

name)

atom method, 300

atomname method, 300 automatic

window

resizing, 32

B background color (see

color, options)

basic button

anchoring, 58

341

342

Index

basic button ^continued)

anonymous

subroutines, 63

bisque method, 293

bitmap

border width, 58 callbacks, 58, 62-64

189

creating,

displaying

color options, 58-59, 72-74

bitmap item, 190

configuring, 79

checkbutton, 84

creating, 57

label widget, 103

cursor options, 58

menubutton widget, 222

disabling, 64

radiobutton, 96

item option

displaying

list,

images, 59, 61

options, 190

text, 60,

setting

(i(i

name and

location, 58

(see also image)

79

flashing,

189

border width

focus, 59 font, setting, 58,

66

basic button, 58

height, 59

canvas widget, 186

invoking, 79

checkbutton, 84

keyboard mapping, 72

entry widget, 109 frame widget, 252 label widget, 104

naming conventions, 12 option

list,

58-60

padding, 59 relief,

size,

listbox,

menu

59

143

widget, 239-240

menubutton widget, 222

70

state,

59

radiobutton, 96

style,

68

scale widget, 211

59

justification,

text

wrapping, 60

tags,

underlining characters, 59

toplevel widget, 258

width, 60

bbox method canvas widget, 183, 202 listbox,

bounding box, 151 (see also bbox method) browse mode, listbox, 144 buffering, space, 38

151

Button method, 57 button (see basic button, checkbutton, or

text widget, 173

method, 300 bind method, 270-272 canvas widget, 184 bell

radiobutton)

ButtonPress event, 276

ButtonRelease event, 276

label widget, 107 listbox,

164

widget, 155

variable options, 59

152

c

uses, 280

using with text tags, l68 valid

129

scrollbar,

text

argument

list,

271

binding events, 270-280

items using tags, 201

bindtags method, 280

callbacks

arguments sent back, 272 assigning basic button, 58, 62-64

canvas widget, 187 checkbutton, 83-84, 87

Index

343 entry widget, 111

scrollable region, 183

menu

scrollbars with,

widget, 239, 241

138

radiobutton, 96

scrolling options,

scale widget, 211, 213

tags,

text indexes with,

130, 133

scrollbar,

uses, 181

text widget, 157 bind method, 272

width, 187

canvasBind method, 184, 201 canvasx, canvasy methods, 202

stop processing, 279 (see also subroutine)

Caps Lock key, 274 Perl)

Canvas method, 182 canvas widget, 181-209 adding

caret symbol, 36

cascade

menu

adding, 235 item, 229

194

text,

cascade method, 235

188

arc item,

196

translating coordinates, 202

selection, 301

Camel book, 64 (see also Programming

185

199-201

bind method, using, 184

cascading menu, 247

binding, 201

cells

method, 292

bitmap item, 190

cget

method

bounding box coordinates, 202

basic button, 79

callbacks, assigning, 187

canvas widget, 198

color options, 186-187

entry widget, 118

configuring, 198

format, 311

coordinate system, 182

frame widget, 256

creating

label widget, 108

bitmaps, 189

listbox,

canvas, 181

menu

147

widget, 243

cursor options, 186

menubutton widget, 233 optionmenu widget, 249

deleting

overview, 309

188

items,

radiobutton, 100

items, 203 tags,

display

204 list,

scale widget, 2l6

changing, 203

scrollbar,

134

example, 206

character spacing (see marks)

focus, setting, 187, 204

checkbutton, 81-93

height, 186

anchoring, 83

indexes, text item, 196

bitmap, displaying, 84

inserting other widgets

in,

197

border width, 84

item type, determining, 204

callbacks, assigning, 84

items, moving, 202

color options, 83-85

line item,

option

configuring, 92

191

list,

184-187

creating, 83, 234

oval item, 193

cursor options, 84

polygon item, 194

flashing, 93

rectangle item, 194

focus, 85

relief,

187

scaling,

font, setting,

height, 84

205

scroll options,

187

84

544

Index

label widget, 103-104

checkbutton ^continued) image, displaying, 84, 90

line item,

indicator

listbox widget, 143

color, setting,

menu

89

192

widget, 239

displaying, 84

menubutton widget,

hiding, 89

oval item, 193

storing status, 85

postscript method, 204

222, 225

invoking, 93

radiobutton, 96-97

on and

scale widget, 211-212

option

off values, 88

83-85

list,

overview, 81

129-130 195

text tags, l64

85

relief,

scrollbar,

text item,

155-157

state,

85

text widget,

style,

91

toplevel widget, 258

text justification,

turning

on and

84

off,

scrollbar,

93

underlining characters, 85

130

setting for application,

count, 292

width, 85

cell

with menubutton widget, 228

determining

wrapping text, 85 Checkbutton method, 83 checkbutton method, 234

circle tag,

frame widget, 252 204

postscript,

toplevel widget, 259, 266

problems, 255

Colormap

199

292

if full,

options

child widgets, 6, 290

children method, 290

293

colormap

event, 276

Circulate event, 276

colormapfull method, 292

method, 291 with frame widget, 256 client method, 265

colormapwindows method, 266 columns

class

classes,

clipboard, manipulating, 300

clipboardAppend method, 300 clipboardClear method, 301 Cmd-Line method, 306 coding

style,

setting,

38

spanning, 37-38 (see also grid)

comma, 6

command method,

234, 266

command-line options, 306 communication among

8

color basic button, 72-74

applications, 304

corruption, 255

widgets, 133

depth, 253, 259, 292

compare method, 173

highlight rectangle, 78

composite widget, 281-289

listbox,

advertise, calling, 285

145

options arc item,

alias, creating,

188

286

configure, calling, 286

on

basic button, 58-59

creating based

bitmap item, 190 canvas widget, 186-187

defining options, 287

checkbutton, 83, 85

example, 282

entry widget, 109-110

frame widget, 252

a frame, 284

delegates, calling, 286

file

location,

283

ConfigSpecs method, 286

345

Index

counting items in a listbox, 150

Configure event, 276

method

configure

createArc method, 188

basic button, 79

createBitmap method, 189

button widget, 313-314, 316-317,

createlmage method, 190

319-323, 325, 327-329

createLine method, 191

canvas widget, 198, 312 checkbutton widget, 316

createOval method, 193

entry widget, 118,317

createRectangle method, 194

format, 309

createText method, 194

frame widget, 255-256, 319 label widget, 108,

320

147

listbox,

createWindow method, 197 creating

basic button, 57

listbox widget, 321

menu

createPolygon method, 194

widget, 243, 322

canvas widget, 181 checkbutton, 83

menubutton widget, 221, 233 optionmenu widget, 249

entry widget, 109

overview, 309

label widget, 103

frame widget, 251

radiobutton, 100

listbox,

radiobutton widget, 323

menu

scale widget, 21 6, 325

menubutton, 220

scrollbar,

optionmenu widget, 248

134

scrollbar widget, 327

328

text widget,

141

widget, 238

toplevel widget, 329

ovals,

193

polygons, 194 radiobutton, 94 rectangles, 194

configuring basic button, 79

scale widget, 210

canvas widget, 198

scrollbar widget, 128

checkbutton, 92

text widget,

entry widget, 118

toplevel widget, 257

label widget,

menu

108

widget, 243

menubutton widget, 233 optionmenu widget, 248

widget, 6-7 current tag, 199 curselection method, 149

cursor

radiobutton, 100

changing, 75

scale widget, 216

insert,

scrollbar,

127, 134

toplevel widget, 260

154

115, 119

options basic button, 58

Construct method, 284

canvas widget, 186

container

checkbutton, 84

frame widget, 252

entry widget, 109-110

frames, 107

containing method, 297

frame widget, 252 label widget, 104

Control key, 274

menu

coordinate system, canvas widget, 182

menubutton widget, 222

coordinates

radiobutton, 97 scale widget, 211

event, 278 setting,

48

translating,

widget, 239, 241

scrollbar,

202

coords method, 202, 2l6

130

text widget,

156

toplevel widget, 259

346

Index

cursor {continued)

double modifier, 274 dtag method, 204 dynamic document list, 236

positioning, 196 setting

143

listbox,

text widget,

155

embedding widgets, 176

D

enlarging widget, 38

databases, option, 293

Enter event, 276

debars method, 196

entering passwords, ll6

debug function, 179 debugging code, 13, 179

Entry method, 109 entry widget, 108-123

defining event sequences, 273

assigning content to a variable, 111

deiconify method, 258, 262

delaying a program, 306

border width, 109 color options, 109-110

Delegates method, 286

configuring, 118

delete method, 172

creating,

canvas widget, 203 entry widget, 118 listbox widget,

menu

148

widget, 243-244

172

text widget,

deleting text, 118

determining contents, 119 focus. 111 font, setting,

110

indexes, 112-114

deleting

items from

inserting text, 120

canvas widget, 203 listbox,

menu

109

cursor options, 109-110

option

list,

password

148

items, 244

relief,

109-111

110

tags,

204

relief options,

text,

118, 172, 196

scrollbar use,

text tag,

170

state,

method, 136 deltag method, 204 delta

116

entry,

112

117

110

text justification,

demo, widget, 72

selecting,

depth method, 292

110

114

translating index values, 119

deselecting radiobuttons, 100

uses,

designing windows, 14

variable options, 111

Destroy event, 276

width, 111

destroy method, 302 destroy versus

exit,

108

with

12

listbox,

destroying widgets, 302

152

scrollbars,

137

Dialog widget, 281

entrycget method, 233, 243

disabling buttons, 64

entryconfigure method, 234, 243

display

list,

changing, 203

displayed values, 214

Ev method, 278 event button number, 278

displaying

menus, 245

coordinates, 278

widgets, 9

defined, 9

distances, screen, 295

height, 279

dlineinfo method, 173

keyboard information, 279

document

loop, 10

list,

dynamic, 236

347

Index

sequences, defining, 273

font, setting

type, 275, 279

basic button, 58

width, 279

checkbutton, 84

Exists

method, 295

exit versus destroy,

entry widget, 110 label widget, 104

12

exiting the application,

12

expanding allocation rectangle, exporting

listbox, 19,

109

text,

Expose event, 276 extended mode, listbox, 144

25

menu

143

widget, 239-240

menubutton widget, 222 postscript method, 205 radiobutton, 97 scale widget, 211 text

fileevent

item, 195

method, 305

tags,

l64

filling

allocation rectangle, 19, 24 listbox,

156

font string, 334

14

find method, 201

finding tags, 201 flash

text widget,

method,

79, 93, 100

flashing

basic buttons, 79

checkbuttons, 93 radiobuttons, 100 focus

fontActual method, 338

fontConfigure method, 338 fontCreate method, 334

fontDelete method, 338 fontFamilies method, 339

fontMeasure method, 338 fontMetrics method, 339

fontNames method, 339 fonts

basic button, 59

canvas widget, 187 checkbutton, 85

configuring, 338 creating,

338

families,

339

entry widget. 111

frame widget, 253, 255 label widget, 104 listbox,

widget, 239

menubutton widget, 223 options, 77

radiobutton, 98 scale widget, 212 scrollbar, setting,

130

204

text widget,

metrics, 339

specifying in buttons, 66

144

manipulating, 302

menu

337

deleting,

157

toplevel widget, 259, 267

focus method, 119, 204, 302

focusCurrent method, 303

focusFoUowsMouse method, 303 focusForce method, 303

Focusin event, 276 focusLast method, 303

focusmodel method, 267 FocusOut event, 276

text widget,

157

module, 66 withTk8.0, 334 foreground color (see color, options) fpixels method, 296 fraction method, 136 Tk:: Fonts

Frame method, 251 frame method, 267 frame widget, 251-256 adding a

label,

254

border width, 252 color options, 252

colormap options, 252

problems, 255 creating, 251

cursor options, 252 defined, 7

348

Index

frame widget {continued)

spanning, 38

height, 252

option relief,

sizing text widget,

252

label,

252-253

list,

253

specifying rows

width, 253

turning

on or

and columns, 39

off,

143

grid method, 267

frames, container, 107

functions

157

grid, setting,

method names)

(see the individual

158

space buffer, 38 spanning columns/rows, 37, 39 special characters, 36

253

style,

38

setting,

focus, 253, 255

gridColumnconfigure method, 43 gridForget method, 46 gridlnfo method, 46

geometry manager deciding which overview,

9,

gridLocation method, 46 to use, 56

15

(see also pack, grid, and place)

geometry method, 260, 296 get

method

gridPropagate method,

GUI design considerations, 14 reasons to use, 2

148

scale widget, 216 scrollbar,

H

136

text widget,

251

group method, 268

entry widget, 111,119 listbox,

A(),

gridRowconfigure method, 43 gridSize method, 47

hanging indent, l65

172

getNames method, 175

height

Getopts modules, 306

basic button, 59

gettags method, 201

button, 70

GIF support, 6l grab method, 303 grabCurrent method, 304 grabGlobal method, 303 grabRelease method, 304 grabStatus method, 304

canvas widget, 186

event, 279 frame widget, 252 label widget, 104

graphical user interface (see GUI)

listbox,

graphics (see image)

menubutton widget, 222

Gravity event, 277

postscript

gravity,

checkbutton, 84

createWindow method, 198

mark, 175

method, 205

radiobutton, 97

34-47 columns

setting, place,

grid,

setting,

143

text widget,

toplevel widget, 259

38

widget, specifying, 53

spanning, 38 configuring columns and rows, 42 creating an

empty

48

156

cell,

37

height method, 296

Hello World example

determining widget location, 46

anonymous

getting configuration information, 46

button

options, 38

callbacks, 62

padding widgets, 41 propagation, A6 removing widgets, 46

overview, 10-11

in,

subroutine, 63

57

positioning widgets, 20 highlight rectangle, changing, 78

349

Index

85

status, storing,

iconbitmap method, 263 iconify method, 263

(see also cursor, options) insert

iconmask method, 264 iconname method, 264 iconposition method, 264 iconwindow method, 264 icursor method, 119, 196 id method, 292 ID string, widget, 292 identify method, 137, 2l6 image

method

canvas widget, 196-197 entry widget, 120 listbox,

menu

147

widget, 244

text tag,

166

text widget,

items in a listbox, 147

menu text,

displaying

items, 244 120, 171, 197

installing the

basic button, 59

image item, 191

menu

checkbuttons, 93

in basic buttons, 61

menu

90

items, 245

radiobuttons, 100

label widget, 104

©ISA array, 282 ismapped method, 295

menubutton widget, 223 radiobutton, 97

itemcget method, 199

191

item,

5

basic buttons, 79

item, 232

in checkbuttons,

Tk module,

invoke method, 79, 93, 100, 245 invoking

checkbutton, 84 in a

155, 171

inserting

190

creating,

115, 119

insert cursor,

itemconfigure method, 199

indentation, setting, l65

index method canvas widget, 196

/

entry widget, 119

JPEG

file

listbox widget, 150

jump

scroll,

menu

justification, text

widget, 245

text widget,

172

support, 61

130

basic button, 59

checkbutton, 84

indexes

bounding box, 151 comparing values, 173

entry widget, 110

entry widget, 112-114

menubutton widget, 223

label widget,

radiobutton, 97

147

listbox,

menu, 242 text,

text

196

text widget,

I6I-I63

into numerical equivalent,

195

165

150

K

values, 119, 172, 245

indicator

keyboard

checkbutton, 89

information, event, 279

97

displaying, 84

options, status,

item, tags,

widget, 160

translating

color,

104

menubutton widget,

97

223, 225

mapping, 72 KeyPress event, 277 Key Release event, 277

350

Index

143

height,

indexes, 147

Label method, 103

inserting items,

102-108

label widget,

anchoring, 103

relief,

bitmap, displaying, 103

resizing,

color options, 103-104

scolling methods, 151

container frames, 107

selection options, 144, 149-150

cursor options, 104

turning grid on or

focus, 104

off,

with

image, displaying, 104

entry widget, 152

103-105

scrollbars,

padding, 104

Listbox

104-105

relief options,

138 (see Iistbox)

widgets, 33 lower method, 203

status messages,

106

text justification,

method

listing

104

setting font,

M

104

wrapping, 105 underlining characters, 104

MainLoop method, 257 MainLoop routine, 10-12

MainWindow

103

class,

257

variable options, 104

MainWindow method,

width, 105

MainWindow

Map

labels

12, 15

widget, 7

event, 277

frame, 254

mapping

frame widget, 252

margin, setting, 165

scale widget, 212, 214

markGravity method, 175

keys, 72

LabEntry widget, 281-282

markNames method, 176

Leave event, 277

marks, 175-176

line

markSet method, 176 markUnset method, 176

creating,

191

item options, 191

Smaster, 46

spacing, text widget, 157-158

maxsize method, 261

iistbox,

menu

141-153

active versus selected,

border width, 143 color options, 143, 145 configuring, 147

counting items, 150 creating,

l4l

cursor, setting,

143

150

displaying, 245

indexes, 242 uses, 218

Menu method, 238 menu method, 235 menu widget, 238-250 assigning callbacks, 239, 241

deleting items, 148

border width, 239-240

example

cascading menu, 247

filling,

143

width, 144

height, 104

uses,

144

scrollbar, assigning,

103

list,

146

146

retrieving elements, 148

configuring, 108

option

143

relief style,

border width, 104

creating,

147

options, 142

script,

152

color options, 239

141

focus, setting, font, setting,

144

143

configuring, 243 creating, 238

351

Index

cursor options, 239, 241 deleting

menu

items, 244

metrics, font, 339

minsize method, 261

example, 247 focus, setting, 239 font, setting,

methods (see the individual method names)

239-240

indexes, translating values, 245

menu invoking menu inserting

minus

sign,

36-37

modifier, 273

modules, Perl/Tk

items, 244

Getopts, 306

items, 245

Tk::Dialog, 257

item type, determining, 245

Motion event, 277

option

mouse cursor, changing, 75 move method, 202 moving items, canvas widget, 202

relief,

style,

239

list,

239 240

menubar, creating, 236 Menubutton method, 220 menubutton widget, 219-238 accelerators, 231

multiple

application, 265, 295

border width, 222 cascade menu, 235 item, 229

checkbutton item, 228 color options, 222, 225

command

145

name

bitmap, displaying, 222

menu

listbox,

TV

anchoring, 222

cascade

mode,

widget, determining, 291

name method,

291, 300

naming conventions, widget, 12 nearest method, 151

new method,

257

next method, 303

item, 227

configuring, 233 creating, 220

o

cursor options, 222

offsetting text,

examples, 236

on and

focus, setting, 223 font, setting,

222

l65

off values

checkbuttons, 88 radiobuttons, 98

height, 222

OnDestroy method, 305

image, displaying, 223

operating system differences, 145, 331-333

indicator options, 223, 225

option databases, 293

items, adding, 234

Optionmenu method, 248 optionmenu widget, 248-249

option

list,

221-224

padding, 223

configuring, 248

radiobutton, 235

creating,

radiobutton item, 227

overview, 281

relief,

248

ordering widgets, 29

223

separator, 235

organizing widgets (see geometry manager)

separator item, 231

orientation

state,

scale widget, 212-213

223

scrollbar,

text justification,

223

wrapping, 224

130

oval item options, 193-194 ovals, creating,

193

underlining characters, 224

overrideredirect method, 268

width, 224

overstrike, l65

Meta key, 275

owner, determining, 302

352

Index

quitting,

allocation rectangles, 22-28

anchoring widgets,

19,

using in Perl

27

Unix, 331

widgets, 33

Windows, 332

19

list,

ordering widgets, 29

overview, 9

packing order, 19 padding widgets, 19, 29 positioning widgets, 20

Photo method, 6l pictures (see image) pixels method, 295 place, 47-56 absolute coordinates, 49

anchoring widgets, 52

screen distances, 31

getting configuration information, 55

sizing text widget, 158

unpacking widgets, 32 with frame widget, 251 packForget method, 32 packlnfo method, 32 packing order, 19 packPropagate method, 32, 108, 251 packSlaves method, 33 padding

options, 48 relative coordinates,

specifying height

placeForget method, 55 placelnfo method, 55 placeSlaves method, 55 placing widgets (see place) pointerx, pointery, pointency methods, 298

Popup method, 245

label widget, 104

menubutton widget, 223

positionfrom method, 268 positioning

156

cursor,

widgets, 19, 29

window method,

50

and width, 53

polygons, creating, 194

basic button, 59

text widget,

1

with

getting configuration information, 32

option

scripts,

versions, 2

automatic resizing, 32 listing

12

reasons to use, 3 Tk::Fonts module, 66

pack, 16-34

196

widgets, 20, 22, 297

178

(see also pack)

parent method, 291

post method, 218, 245

parent widgets

postcascade method, 247

determining, 291

postscript method, 204

overview, 6

PostScript output, canvas widget, 204

with frames, 251

PPM/PGM

password entries, ll6 pathname method, 292 pathname, widget, 292

file

support, 61

prev method, 303 print, printf,

13

Programming

Perl

Perl, 64, 282,

protocol method, 265 history,

1

reference, general,

Tk extension

x

(see Perl/Tk)

Q

8

Quick Draw program, 207 quitting an application, 12

Perl/Tk

coding

style,

debugging

a program,

13

R

334 Getopts modules, 306 fonts,

history,

radiobutton, 93-100

1

installing,

anchoring, 96 1,

5

modules (see modules,

assigning callbacks, 96 Perl/Tk), 257

306

353

Index

label widget, 105

bitmap, displaying, 96

146

border width, 96 color options, 96-97

radiobutton, 97

configuring, 100

scale widget, 212

listbox,

creating, 94

scrollbar,

cursor options, 97

text

100

flashing,

font, setting,

toplevel widget, 259

97

height, 97

highlight rectangle, 97 indicator

97

color,

97

status,

invoking, 100

menubutton widget, 235 on and off values, 98

resizing

146

listbox,

retrieving elements

from a

listbox,

rgb method, 293

97

selecting

removing widgets, 46, 55 Reparent event, 278 repeat method, 307 reqheight method, 296 reqwidth method, 296 resizable method, 261

window, automatic, 32

96-98

list,

overview, 81 relief,

165

tags,

widget, 156

focus, 98

option

129-130

and

deselecting, 100

RGB

value, 293

menu example, 247

state,

98

right-click

style,

99

rootx, rooty

97

text justification,

method, 297

rows 38

underlining characters, 98

setting,

variable options, 98

spanning, 38

width, 98

(see also grid)

with menubutton widget, 227

wrapping,

text,

98

Radiobutton method, 95 radiobutton method, 235 raise

method, 203, 258

range of values, scale widget, 213 rectangle

Scale method, 206, 210 scale widget, 210-217

assigning callbacks, 211

border width, 211

changing

allocation (see allocation rectangle) creating,

194

highlight, 78, 97 relief

size,

215

color options, 211-212 configuring, 2l6 creating,

210

cursor options, 211

canvas widget, 187 checkbutton, 85

determining coordinates, 2l6 focus, setting, 212

entry widget, 110 font, setting,

frame widget, 253 label widget, 104 listbox,

menu

143

widget, 239

menubutton widget, 223

label options, 212, 214

option

211-212 212-213

range of values, 213 relief,

entry widget, 112

list,

orientation,

options basic button, 59

211

identifying parts, 216

212

setting value, 2l6 slider options,

212

148

354

Index

scale widget {continued)

method

Scrolled

212

state,

canvas widget, 181, 184, 203 scrollbar widget, 125-128

uses, 210

value increments, displaying, 214

scrolling

variable options, 212

canvas widget, 206

width, 212

listbox,

scaling the canvas widget, 205

151

121

text,

scan method, 152

search method, 174

scanDragto method, 121, 179, 206 scanMark method, 121, 179, 206

searching text widget, 174

scanning

sel tag,

canvas, 206 text,

see method, 150, 173

selectFrom method, 197

121

screen

selecting

distances

items in a listbox, 144

converting, 295 units,

radiobutton, 100

31

text

canvas widget, 197

information, 298

screen method, 298

entry widget, 114

screencells method, 299

selection

screendepth method, 299 screenheight method, 298

method, 121, 149

mode, 143

screenvisual method, 299

options, listbox, 149-150

screenwidth method, 298

selectionAnchor method, 150

scrollable region, canvas widget, scrollbar,

164, 167

selectClear method, 197

183

124-140

SelectionClear method, 301 selectionClear method, 149

SelectionGet method, 301

activating elements, 136

arrows, 132

SelectionHandle method, 301

assigning callbacks, 130, 133

selectionlncludes method, 149

border width, 129 color options, 129-130

SelectionOwn method, 302 SelectionOwner method, 302

communicating with other widgets, 133

selectionPresent method, 122

configuring, 127, 134

selectionRange method, 122

creating,

selectionSet method, 149

128

cursor options, 130

selectionTo method, 122

defining, 124, 135

selectTo method, 197

examples, 137

send method, 304

focus, setting, 130

separator, creating, 235

option

list,

129-130

separator item, 231

separator method, 235

orientation, 130 relief,

129-130

slider,

132

style,

server method, 300 server type, 300

131

set

method, 135, 2l6 method, 293

using one with multiple widgets, 138

setPalette

width, 130

setting tab stops,

with

Shift key,

entry widget, 117, 137 listbox, text, or

single

canvas widgets, 138

scrollbar, assigning to widget,

Scrollbar method, 128

144

159

274

mode,

listbox,

method, 150 size, widget, 296 sizefrom method, 269 size

144

Index

355

sizing

158

text widget,

tab stops, setting, 159

toplevel widget, 260 tabs, setting,

widgets (see pack) slider

arc item, scale widget, 212

132

scrollbar,

spacing

line item,

157-158

spanning rows and columns, 39 state

basic button, 59

checkbutton, 85 entry widget, 110

menubutton widget, 223 radiobutton, 98 scale widget, 212 text widget,

157

toplevel widget, 265 status label,

106

stipple pattern

arc item,

189 192

line item,

oval item, 193 text item,

195

text tags,

l64

193

oval item, 193 text item,

195

tagAdd method, 166, 168 tagBind method, l69 tagCget method, 168 tagConfigure method, l67, 172 tagDelete method, 170 tagLower method, 170 tagNames method, 171 tagNextrange method, 171 tagRaise method, 170 tagRanges method, 171 tagRemove method, 170 tags

canvas widget, 199-201 finding, 201 text,

stored values, 214

189

bitmap item, 190 create Window method, 198 image item, 191

character (see marks) line,

157, 165

names

tag

Tcl/Tk,

164-171 1,

4

tear-off items, 224

storing indicator status, 85 text style

adding, 197

basic button, 68

checkbutton, 91

frame widget, 253 menu widget, 240

deleting,

exporting, 109 in a

radiobutton, 99 scrollbar,

canvas widget, 194

indexes, 196

131 inserting,

subroutine

anonymous, 63 references, 64

syntax options, 6

screen distances, 31

120, 171

item indexes, 196 justification (see justification, text)

scanning, 121

(see also callbacks)

Sub widget method, 184 SUPER: :bind, 184 SUPER: :Populate, 285 switches, search method, 174

118, 196

entering, 108

scrolling,

121

selecting,

197

selection options, entry widget, 114 tags,

164-171

adding to existing

text,

border width, l64

changing

priority,

color options, 164 configuring, l67 creating,

l67

170

168

356

Index

deleting, 170

Tk Tk

example, 166

Tk::bind, 184, 201

text, tags

{continued)

font, setting,

l64

justification, text,

option

list,

relief,

165

(see Perl/Tk)

Tk::break, 279

l65

Tk::Button, 280

164—165

Tk::Dialog, 257

module, 66 284

Tk:: Fonts

removing tag from stipple pattern,

text,

170

164

Tk:: Frame,

Tk::JPEG, 61

284

underlining characters, l65

Tk:: Widget,

using bind method, l68

Toplevel method, 257

wrapping,

toplevel method, 291

text,

165

widget, 154-180

toplevel widget, 257-269

assigning callbacks, 157

application grid, 267

border width, 155 changing appearance, l64

border width, 258

color options, 155-157

colormap options, 259, 266 command property, 266

creating,

color options, 258

154

cursor options, 156

configuring, 260

cursor, setting, 155

creating, 257

debugging, 179

cursor options, 259

deleting text, 172

defined, 7

embedding other widgets, 176

focus model, 267

example, l60

focus, setting, 259

font, setting,

height, 259

156

icon

font use, 157 grid, setting,

bitmap, 263

157

height, 156

mask, 264

indexes, l6l-l63

name, 264 position, 264

inserting text, 171 justification values,

line spacing,

160

option

157-158

option

155-157

list,

padding, 156

setting tab stops,

tabs, tag,

260

262

265

width, 259

138

window

searching contents, 174

159

transient

158

properties, 265

method, 269

translating to

RGB

triple modifier,

157

state,

title,

uses, 257

scrollbars with,

sizing,

setting sizing, state,

156

relief,

258-259

list,

259

relief,

marks, 175-176

value, 293

275

type method, 204, 245

157 166

u

uses, 154

width, 157

underlining characters

wrapping (see wrapping, Text method, 154 time delays, 306 title

clipboard, manipulating, 300

method,

11,

text)

basic button, 59

checkbutton, 85 label widget,

262

104

menubutton widget, 224

357

Index

radiobutton, 98

165

text tags,

Unix fonts,

257-269

widgets anchoring, 27, 52

66

using Perl/Tk with, 331

Unmap

154-180

toplevel,

color values, 73

124-140

scrollbar, text,

event, 278

unpacking widgets, 32 unpost method, 247 update method, 297

checkbutton, 83 place, 48 children, determining, 290 creating,

demo

6-7

with

Tk module, 72

destroying, 302 displaying, 9

embedding, 176 value displayed versus stored, 214 increments, scale widget, 214

enlarging, 38 height, setting, 48

197

item,

range, scale widget, 213

listing,

variable options

33

name, 291

basic button, 59

entry widget. 111 label widget, 104

(see also atom)

naming conventions, 12 ordering, 29

radiobutton, 98 scale widget, 212

versions of Perl/Tk, 2

viewable method, 300 virtual desktop,

297

Visibility event,

278

visualsavailable method, 299

vrootheight method, 298

vrootwidth method, 298

organizing (see geometry manager)

padding, 29, 41 parent and child, 6 parent, determining, 291

pathname, 292 placing (see place) position, 297

positioning, 20, 22

(see also pack)

removing, 46, 55

w

resizing, automatic, 32

waitVariable method, 304

screen information, 298

waitWindow method, 305

size,

widget types

sizing,

basic button, 57-80

determining, 296 19

(see also pack)

canvas, 181-209

space buffer, 38

checkbutton, 81-93

specifying width

composite, 281-289

unpacking, 32

10&-123

entry,

frame, 251-256 label,

102-108

listbox,

141-153

and

height, 53

width, setting, 48 Widgettype method, 6 width arc item,

189

MainWindow, 7 menu, 238-248

basic button, 60

menubutton, 220-238 optionmenu, 248-249 radiobutton, 93-100 scale, 210-217

canvas widget, 187

button, 70

checkbutton, 85

createWindow method, 198 entry widget. 111

About the Author Nancy Walsh

a consultant for Sybase, Inc. She spent too

is

University of Arizona, changing majors a multitude of times

with a B.S. in computer science. Continuing on in Perl

and Java

few

in the last

ending up

she has worked mostly with

life,

Nancy has numerous hobbies, which hand and machine quilting), stained glass

still,

include quilting (pieced and applique,

(anything that doesn't break yet), martial arts (she

Kwon

years at the

finally

years.

In the family tradition of not sitting

black belt in Tae

many

and

Do), amateur radio

(QRP

approximately halfway to a

is

mostly),

and reading (anything

with words).

Colophon Our look

is

the result of reader comments, our

own

experimentation, and feed-

back from distribution channels. Distinctive covers complement our approach

to technical topics, breathing personality

and

life

distinctive

into potentially dry

subjects.

The

bird

on the cover of Learning Perl/Tk

hollandiae). This large, flightless bird steppes.

The emu

is

one of the

cousin the ostrich. Adult

is

is

a juvenile

emu {Dromaius

novae-

found throughout the Australian bush

largest birds in existence,

emus stand about

5 feet (1.5

second only

to

m) high and weigh up

its

to

120 pounds (55 kg). The grayish-brown emu's small wings contain only six or

seven feathers. They are hidden by the long, hairlike rump plumage. Emus have

which they use as defensive and offensive weapons limb can be broken by a kick from an emu. Their powerful legs make emus strong swimmers and fast runners; they can reach speeds of up to 50 km/hour. extremely strong

when

fighting.

legs,

A human

Male emus, which are

slightly smaller

eggs and the raising of the young.

than the females, tend to the incubation of

An emu

nest contains

up

to fifteen to twenty-

by several hens. Incubation of the eggs takes from twenty-five to sixty days. The large discrepancy in incubation time occurs because the male needs to leave the nest periodically to find food and drink. The length of time he is away affects the time for incubation. Newly hatched emus weigh about five

deep green eggs,

15 ounces (440 g).

laid

They

are fully

grown

at

two

to three years.

between emus and Australian farmers has always been an adveremu have been exterminated. Because emus can jump over high fences, it is difficult to keep them out of fields, where they eat

The

relationship

sarial

one; three coastal subspecies of

and trample crops. In the arid Australian bush, emus also compete with cattle and sheep for grass and water. On the other hand, emus eat many insects that would otherwise eat crops. In 1932 Australian farmers declared war on the emus, making an all-out effort to eradicate them. Fortunately, the between emus and farmers continues to this day. Edie Freedman designed the cover of

from the Dover

Pictorial Archive.

this

effort

failed.

The

battle

book, using a 19th-century engraving

Kathleen Wilson designed the back cover and

produced the cover layout with QuarkXPress

3. 32,

using the ITC

Garamond

font.

was done by Edie Freedman and modified by Nancy Priest, Garamond Light and Garamond Book fonts. The text was prepared in FrameMaker 5.5 by Mike Sierra. The illustrations were created by Robert Romano in Adobe Photoshop 5.0 and Macromedia Freehand 8.0. Quality assurance was provided by Ellie Fountain Maden, Jeffrey Liggett, Claire Cloutier LeBlanc, and Sheryl Avruch. This colophon was written by Clairemarie Fisher

The

interior design

using the ITC

services were provided by TIPS Technical by Judy Flynn, composition and indexing by Karen Brown of Scriptorium Publishing Services, Inc., proofreading by Rachel Anderson

O'Leary.

Publishing

Editorial

and production

—copyediting

of Archer Editorial, and project

Whenever RepKover

possible, our

or Otabind

management by Robert Kern.

books use a durable and .

If

flexible lay-flat binding, either

the page count exceeds the

for this type of binding, perfect binding

is

used.

maximum

bulk possible

gl^ More

^^

from O'Reilly

Titles

Perl Learning Perl on Win32 Systems

Perl in a Nutshell By Stephen Spainhour,



&

Ellen Siei'er

Nathan Patwardhan

^^jfH^iL^

^^HH|k

^^^^M

B^JwmJBI

]st Edition January 1999 674 pages, ISBN 1-56592-286-7

The perfect companion programmers, Perl

in

for

need

Perl.

know

to

It

a

to the

contains everything you

Perl questions.This wealth of information efficient, extraordinarily

is

is

paced course, leading Perl

and a Windows NT practitioner

^^^^3||

teach you to program in the language

V

that

promises

to

emerge as the

scripting

language of choice on NT. Based on the

an

into

&

August 1997

In this carefully trainers

most obscure

packed

Erik Olson

306 pages, ISBN 1-56592-324-3

^^Ki ^^^^r

working

a Nutshell

for all but the

1st Edition

^^^^H|

comprehensive reference guide

world of

By Randal L Schwartz, Tom Christiansen

^kl

WKfKfKKftKSglfn

"llama" book,

this

book

feanires tips for

PC users and new,

NT-specific examples, along with a foreword by Larry Wall, the

usable format.

creator of Perl, and Dick Hardt, the creator of Perl for Win32.

The Perl Cookbook By Tom

Christiansen

1st Edition

& Nathan

Mastering Regular Expressions

Torkington

By Jeffrey E. E Friedl

August 1998

794 pages. ISBN 1-56592-243-3

1st Edition January

and examples for anyone programming in Perl covers everything

Regular expressions, a powerful tool for

from beginner

manipulating ^ Regular Expressions

questions to techniques that even the most

experienced Perl programmers might learn from.

It

text

and

data, are

scripting languages, editors,

found

in

programming

environments, and peciahzed tools. In

contains hundreds of Perl

this

book, author Jeffrey Friedl leads you

through the steps of crafting a regular

"recipes," including recipes for parsing strings, doing matrix multiplication,

1997

368 pages, ISBN 1-56592-257-3

This collection of problems, solutions,

working with arrays and hashes, and performing

expression that gets the job done.

and uses them

complex regular expressions.

in

He examines a variety

of tools

an extensive array of examples, with a major

focus on Perl.

Learning Perl, 2nd Edition

Mastering Algorithms with Perl

By Randal L. Schuiartz & Tom Christiansen,

By Jon Orwant. Jarkko Hietaniemi &

Foreword by Larry Wall

Algorithms

2nd Edition July 1997 302 pages, ISBN 1-56592-284-0

John Macdonald 1st Edition August 1999 (est.) 480 pages, ISBN 1-56592-398-7

witli Perl

In this update of a bestseller, two leading Perl trainers teach you to use the

universal scripting of the

langu^e

There have been dozens of books on

most

in the

programming algorithms, but never before has there been one that uses Perl.

age

World Wide Web. Now current

Perl version 5.004, this hands-on tutorial includes a lengthy

Whether you are an amateur programmer

for

new

or

chapter on CGI programming, while touching also on the use of library modules, references,

and

in other languages, this

Perl's object-oriented constructs.

traditional

programming

easy-to-maintain

know

manner with

Perl. Topics

800-998-9938



and encryption.

[email protected] • http://www.orellly.com/

Our products are available at a bookstore or software store near FOR information:

800-998-9938



range in complexity

to statistical algorithms,

O'REILLY" TO order:

to carry out

tasks in a high-powered, efficient,

from sorting and searching analysis,

a wide range of algorithms

book will teach you how

you.

707-829-0515 • [email protected]

numerical



Perl Perl Resource Kit—UNIX Edition fij^^MMMEl^l^ Br Larry' Wall, Nate Patwardhan,

^Mf^W

Ellen

^^m^^

Brian Jepson

fr

VHHV

Perl documentation

enhanced software

it's

Tom

&

Christiansen

2nd Edition

September 1996 670 pages, ISBN 1-56592-149-6

Coauthored by Larry Wall, the creator of gives

Perl, the

issfs

you the most comprehensive collection of

RESOlRCi; KIT

Wall,

Randal L Schwartz

&

The Perl Resource Kit— UNIX Edition

V/X A

Developed

By Larry

November 1997 1812 pages, ISBN 1-36592-370-7

r^f^ f* I

2nd Edition

Perl,

1st Edition

j-^W| -*

David Futato

Siei'er,

Programming

second edition of this authoritative

guide contains a

and commercially

tools available today

langu^e and

in association with Larry Wall, the creator of Perl,

fiill

explanation of Perl

5. 003 features. It

version

covers Perl

syntax, functions, library

modules, references, and object-oriented features, and also explores

the definitive Perl distribution for webmasters, programmers,

invocation options, debugging,

common

mistakes, and

much more.

and system administrators.

Kit— Win32 Edition

The Perl Resource Kit provides:

Perl Resource



^j^KMMESMMtllM, By Dick Hardt, Erik Olson, David Futato & Brian jepson ^jj^

Over 1800 pages of

tutorial

documentation for Perl •

A CD-ROM containing

and in-depth reference and extensions,

utihties

in 4 volumes.

^m^^^ C^^^m

the complete Perl distribution,

plus hundreds of freeware Perl extensions and

utilities

T^^^i

a complete snapshot of the Comprehensive Perl Archive



Network (CPAN) Wall

as well as

new

software written by Larry

Jif\~,Y\.

1st Edition

^^ ^^' Resource M— Win32 Edition is

Rl'SOl

F^Ci;

they can find what they

—and more—

need on CPAN.

Now

all

the

power

include

your

fingertips.

of

The Perl Resource Kit

Win32

includes: •

and Linux

of CPAN, with an install

program

that ensures that all necessary

installed together Also includes

and a web-aware interface

of Perl. The Kit contains

Perl software

Win32 webmasters

some

from Dick Hardt's

the

for

and a

an easy-to-use search tool

that allows

you to get the

ActiveState

company along

definitive

A new Java/Perl

documentation

set

from O'Reilly

Advanced Perl Programming

latest

By Sriram Srinivasan

interface that allows

programmers

Java classes with Perl implementations. This

new

1st Edition August 1997 434 pages. ISBN 1-56592-220-4

to write

tool

was

This

written specially for the Kit by Larry Wall.

book covers complex techniques

managing production- ready Experience the power of Perl modules in areas such as CGI,

web

power and

of the latest commercial

modules are

version of each module. •

for

with a collection of hundreds of Perl modules that run on Win32,

A complete snapshot Solaris

Win32 and

and system administrators who have discovered flexibility

is at

who

KIT are expanding their platform expertise to

on One Convenient CD-ROM hackers know when to create their own, and

Perl Software Tools All

when CPAN

& CD-ROM

an essential tool for Perl programmers

just for the Kit.

Experienced Perl

August 1998

^^^ P^S^' Includes 4 books ISBN 1-56592-409-6 1'

spidering, database interfaces,

man^ng

mail and

news, user interfaces, security, graphics, math and

and explains methods

USENET

statistics,

and objects

and

before.

much more.

It

that

gives

Perl

for

programs

for manipulating data

may have looked

like

magic

you necessarv' background

for dealing with networks, databases,

and

GUIs, and includes a discussion of internals to help you program

more

efficiently

and embed Perl within C or C within

O'REILLY" JO order:

800-998-9938

[email protected]

• http://www.oreilly.com/

Our products are available aj a bookstore or software store near FOR information:

800-998-9938



707-829-0515



you.

[email protected]

Perl.

Web Programming CGI Programming on the World Wide Web

JavaScript: The Definitive Guide, 3rd Edition By David Flanagan & Dan

By Shishir Gunciavaram 1st Edition March 1996 450 pages, ISBN 1-56592-168-2 This

book offers a comprehensive explana-

tion of

who own

This third edition of the definitive reference

CGI and related techniques for people

to JavaScript covers the latest version of the

hold on to the dream of providing their

language, JavaScript 1.2, as supported by

information servers on the Web.

Netscape Navigator 4.0. JavaScript, which

It

starts

CGI

at the beginning, explaining the value of

and how subtle details of

Shafer

3rd Edition June 1998 800 pages, ISBN 1-56592-392-8

it

works, then moves

is

being standardized under the

ECMAScript,

swiftly into the

can be embedded

programming.

directly in

is

name

a scripting language

that

HTML to give web pages programming-

language capabilities.

Dynamic HTML: The

Definitive Reference

Learning VBScript

By Danny Goodman 1st Edition July

By PaulLomax

1998

1088 pages, ISBN 1-56592-494-0

Dynamic HTML: is

1st Edition July

an indispensable compendium for

content developers.

It

reference material for

CSS

616pages,

The Definitive Reference

style attributes,

of the

HTML

This definitive guide shows

how

tags,

by the various standards and the

and discusses techniques ActiveX controls to a

&

Web Client Programming

1st Edition February 1998 618 pages, 1-56592-383-9

This definitive guide

is

exclusively to teaching

"" '^^•"'""