Next
Frame, Text, Scrollbar, Scale 
Tcl/Tk Tutorial - Create GUI using Tk with Tcl Language
Button, Entry, Label

Widgets 1 : Button, Entry, Label

Three things need to be said about widgets. First is the path. This I have explained earlier. The paths of all widgets must be unique and will be used when ever that widget needs to be accessed. Second is the options. Each widget has some options which can be used to configure it. This is usually done when the widget is declared, but it can be done afterward also. The final thing is commands. Each widget has some commands which also can be used to configure it or make it do some thing.

But before we begin, we need to know a little about the pack command. I have explained this earlier but just doing it one more time so that you don't have to push the back button. Pack is a geometry manager. Another geometry manager is 'grid' and I like it better - we will explore that latter. Pack is much more simpler than grid.

The line pack .hello tells the interpreter to pack the widget called ".hello".
If the command was pack .hello -in .frame, the widget .hello will be packed in another widget called .frame. In the absence of the '-in' option, the specified widget is put in the main window.


button

This will make a button. It can be configured to execute some code when pushed. This will usually refer to a function so when the button is pushed, the function will run. An button is shown using HTML below.

Some Options
-text "TEXT" TEXT will be the text displayed on the button
-command "CODE" CODE will be the code that is executed when the button is pushed

proc push_button {} {
	... whatever ...
}
button .but -text "Push Me" -command "push_button"
pack .but

entry

An entry is a widget that displays a one-line text string and allows the user to input and edit text in it. When an entry has the input focus it displays an insertion cursor to indicate where new characters will be inserted. An entry element is shown using HTML.

Some Options
-width NUMBERWidth of the input field. NUMBER should be an integer.
-textvariable VARIABLEThe contents of the variable VARIABLE will be displayed in the widget. If the text in the widget is edited, the variable will be edited automatically. VARIABLE should be given without a preceding '$' sign.
-state STATE The state of the input field. It can be normal, disabled, or readonly. If it is readonly the text can't be edited.
Some Commands
SyntaxDescriptionExample
path get The text inside input field can be taken by this command set name [.ent get]
path delete FIRST ?LAST? Delete one or more elements of the entry. FIRST is the index of the first character to delete, and LAST is the index of the character just after the last one to delete. If last isn't specified it defaults to FIRST+1, i.e. a single character is deleted. This command returns an empty string. .ent delete 0 end
path insert index STRING Insert the characters of STRING just before the character indicated by index. Index is 0 for the first character. The word "end" can be used for the last character .ent insert end "Hello"

Example

proc push_button {} {
	.ent insert end "Hello"
}
entry .ent
button .but -text "Push Me" -command "push_button"
pack .ent
pack .but

label

This widget display text messages.

Example

proc push_button {} {
	.ent insert 0 "Hello "
}
label .lab -text "Enter name:"
entry .ent
button .but -text "Push Me" -command "push_button"
pack .lab
pack .ent
pack .but
Next
Frame, Text, Scrollbar, Scale 

Comments

Derek Sorensen at 29 Nov, 2007 02:00
Just following along with the tutorial - very clear and concise, thanks!

I came across a problem here though; I saved the first script as a file with the name "button.tcl" and tried to execute it using "wish button.tcl".

When I moved the mouse onto the form I got the following error:

---
unknown option "-state"
unknown option "-state"
while executing
"$w cget -state"
(procedure "tk::ButtonEnter" line 3)
invoked from within
"tk::ButtonEnter ."
(command bound to event)
---

It turns out the problem was the filename - renaming the file to btn.tcl solved the problem. Apparently button is a reserved word and naming a file using a reserved word can cause this error. I mention it here so that others who are as confused as I was might find it.

Thanks again for a very nice tutorial.

Derek
Reply to this.
Binny V A at 29 Nov, 2007 08:08
Thanks! I had no idea.
Reply to this.
Mahmood Naderan at 05 Nov, 2009 07:34
I have also the same problem when I wanted to run a simple program using "scale" widget and named it "scale.tcl". I now find out that the filenmae must be different from widget's name (keyword)
Reply to this.
Karen at 11 Nov, 2009 07:31
thank you very much..i have came across this problem..the explanation was really helpful..tq
Reply to this.
Anonymous at 12 Mar, 2008 11:59
Do we have a way to change a Widget once we have made it. I mean i made some button and used some command now i want that i use some other command for that button. Is there a way that can be changed.
Reply to this.
Anonymous at 30 Apr, 2008 12:33
You can use the path to the widget with the configure option. If you do .but configure in the above example it will give you all the settings for that button. One of these is -command... so you can do .but configure -command {puts "new command"} to change it.
Reply to this.
Anonymous at 15 May, 2008 03:07
Regarding the way of changing the response command for a button:
It is clearer to keep the response proc same, and only change the action within the proc, depending on some state variable. Such code is easier to read: one button -- one response proc. Otherwise, you get additional dependencies, things changing magically, etc. The clearer the structure of your program the better.

So, my suggestion would be to write your code this way:

proc push_button {} {
variable state

if { $state(button_action) eq "DO_SOMETHING" } {
DoSomething
} else {
DoSomethingElse
}
}

button .but -text "Push Me" -command "push_button"

Reply to this.
Anonymous at 16 Mar, 2008 10:34
if i use entry insert it gets appended each time i execute how can i overwrite the entry text
Reply to this.
Z. Wagner at 05 Apr, 2009 02:05
You have 2 method:

1. Delete the contents and then insert the new text.

2. Assign the new value to the variable configured with -textvariable directly by set.
Reply to this.
Anonymous at 29 Jun, 2009 10:51
add
.ent delete 0 end
before the
.ent insert 0 "Hello"
Reply to this.
Anonymous at 08 Apr, 2008 02:13
Is there any way to make a widget invisible? For example, I can change the foreground color of a label but I can't hide the button/entry etc.
Reply to this.
Anonymous at 04 Feb, 2009 01:31
How can we invoke or get another screen or frame if we click on button say "NEXT"
and also .. if we have 2 sets of radio buttons for eg: sex male and female
and city delhi or NCR... how can we let the user select one from each category...
I tried but if i clik on male and then click on delhi .. the male radio button gets de selected...
Reply to this.
Jrussell128 at 25 Mar, 2009 05:10
I know this may sound like a dumb question...But, is there a way to set the foreground color to a label or text widget?

I want colored text, and I'm sure there's a way somehow.
Reply to this.
Anonymous at 01 Jun, 2009 11:25
Why all paths begin with . ?
Reply to this.
amigojapan at 02 Jul, 2009 05:31
I think this is a pretty good example of a launch pad I made with this script.

proc push_button1 {} {
exec xeyes &
}
proc push_button2 {} {
exec xcalc &
}
proc push_button3 {} {
exec xterm &
}
button .but1 -text "X eyes" -command "push_button1"
button .but2 -text "calculator" -command "push_button2"
button .but3 -text "terminal" -command "push_button3"
pack .but1
pack .but2
pack .but3
Reply to this.
Anonymous at 24 Aug, 2009 11:57
Could anyone explain why the string "abcd" is never seen in the label? And how to fix this "problem" is the program below. Having worked with Visual Basic for so long my brains must have deteriorated.

****************************************

set debug_string "......"

label .txt_debug -textvariable debug_string
button .but -text "Push Me" -command "cmd"

pack .txt_debug
pack .but

proc cmd { } {
set sAstr1 "abcd"
set sAstr2 "efgh"
global debug_string

set debug_string $sAstr1


# wait 2000 milliseconds
set EndWait [expr [clock clicks -milliseconds] + 2000]

while { [clock clicks -milliseconds] < $EndWait } {
}
set debug_string $sAstr2
}
****************************************
Reply to this.
Anonymous at 18 Dec, 2009 07:30
Hi, i have a question, I've wrote a simple gui with an add and remove button to dynamically adding/removing an entry plus a browse button on my gui. The browse button calls tk_chooseDirectory to select a directory.
My question is that is there a way to get the patch of a widget? Because now I want to display the directory that I select in the entry left to the according browse button, but I couldn't find ways to know which of the browse button i've pressed after adding a few. Here's my code.

Thanks

#global variables
set current_row 2;
set current_entry "entry_";
list entry_list; #a list that contains the path oc each entry
list browse_button_list; #a list that contains the path of each browse button
list input_list;

frame .main
button .add_button -text "Add entry" -command "add_entry";
button .remove_button -text "Remove entry" -command "remove_entry";
entry .entry_1
button .browse_1 -text "Browse..." -command "browse";
lappend entry_list ".entry_1";
lappend browse_button_list ".browse_1";

grid .add_button -in .main -row 1 -column 1;
grid .remove_button -in .main -row 1 -column 2;
grid .entry_1 -in .main -row 2 -column 1;
grid .browse_1 -in .main -row 2 -column 2;
pack .main

proc add_entry {} {
global current_row browse_button_list entry_list;
set temp1 ".entry_";
set temp2 ".browse_";
append temp1 $current_row;
append temp2 $current_row;
entry $temp1
button $temp2 -text "Browse..." -command "browse";
grid $temp1 -in .main -row [expr {$current_row + 1}] -column 1;
grid $temp2 -in .main -row [expr {$current_row + 1}] -column 2;
lappend entry_list $temp1;
lappend browse_button_list $temp2;
incr current_row;
}
proc remove_entry {} {
global current_row browse_button_list entry_list;
set current_row [expr {$current_row-1}];
destroy [lindex $entry_list [expr {$current_row-1}]];
destroy [lindex $browse_button_list [expr {$current_row-1}] ];
set browse_button_list [lrange $browse_button_list 0 end-1]
set entry_list [lrange $entry_list 0 end-1]
}

proc browse {} {
variable state
global input_list;
lappend input_list [tk_chooseDirectory -initialdir D:/]
}
Reply to this.
Comment

Please dont enter you comments in this form - this is a fake form to confuse spamming bots. The next form is the real one.




Comment




Comment Formating : HTML tags a, strong, em, b, i, code, pre, p and br allowed. Other tags will be shown as code(< will become &lt;). Urls, Line breaks will be auto-formated.
Subscribe to Feed