This section contains a full listing of the address book application, as it should look in your program. This is a basic data entry application that highlights many of the functionalities of the Tcl/Tk language. At this point, you may wish to sort the dictionary to provide an alphabetical listing of the data, implement multiple field search capability, and toggle the state of the buttons and menu entries to limit the user's abilities in a logical manner or anything else you might want to add.
It's all there in Tcl/Tk. The only limit is your imagination.
# Source the Tk Package package require Tk #Configure the Window wm title . "Address Book" # Main Frame frame .main -borderwidth 1 -relief solid -padx 10 -pady 10 # Entry Widgets entry .main.efirst -width 25 entry .main.elast -width 25 entry .main.eaddress -width 50 entry .main.ecity -width 25 entry .main.estate -width 3 entry .main.ezip -width 5 entry .main.ephone -width 25 # Label Widgets label .main.first -text "First Name" label .main.last -text "Last Name" label .main.address -text "Address" label .main.city -text "City" label .main.state -text "ST" label .main.zip -text "Zip" label .main.phone -text "Phone" label .main.photo -text "Click to Update" -width 15 # Label for Photo Widget label .main.picture -background black # -width 15 -height 10 # Button Widgets button .main.previous -text "Previous" -width 15 -command previousRecord button .main.next -text "Next" -width 15 -command nextRecord button .main.add -text "Add" -width 15 -command addRecord button .main.save -text "Save" -width 15 -command saveRecord button .main.delete -text "Delete" -width 15 -command deleteRecord button .main.exit -text "Exit" -width 15 -command exit # Pack command pack .main # Grid command grid .main.efirst -row 0 -column 0 -sticky nw grid .main.elast -row 0 -column 1 -columnspan 2 -sticky nw grid .main.picture -row 0 -column 3 -rowspan 7 -sticky news grid .main.first -row 1 -column 0 -sticky nw grid .main.last -row 1 -column 1 -columnspan 2 -sticky nw grid .main.eaddress -row 2 -column 0 -columnspan 3 -sticky nw grid .main.address -row 3 -column 0 -columnspan 3 -sticky nw grid .main.ecity -row 4 -column 0 -sticky nw grid .main.estate -row 4 -column 1 -sticky nw grid .main.ezip -row 4 -column 2 -sticky nw grid .main.city -row 5 -column 0 -sticky nw grid .main.state -row 5 -column 1 -sticky nw grid .main.zip -row 5 -column 2 -sticky nw grid .main.ephone -row 6 -column 0 -columnspan 2 -sticky nw grid .main.phone -row 7 -column 0 -columnspan 2 -sticky nw grid .main.photo -row 7 -column 3 -sticky nw grid .main.previous -row 8 -column 0 -sticky ne grid .main.next -row 8 -column 2 -sticky nw grid .main.add -row 9 -column 0 -sticky ne grid .main.save -row 9 -column 1 -sticky nw grid .main.delete -row 9 -column 2 -sticky nw grid .main.exit -row 9 -column 3 -sticky nw # Menu Creation menu .menubar .configure -menu .menubar # Add the first item set File [menu .menubar.myfile] .menubar add cascade -label File -menu .menubar.myfile # Add entries $File add command -label "Add Record" -command addRecord $File add command -label "Save Record" -command saveRecord $File add command -label "Delete Record" -command deleteRecord $File add separator $File add command -label "Quit" -command exit set Edit [menu .menubar.myedit] .menubar add cascade -label Edit -menu .menubar.myedit $Edit add command -label "Find" -command findRecord # Bind the mouse click to the picture label bind .main.picture <B1-ButtonRelease> getPicture # Global Variables # Text file containing stored records global addressFile # Dictionary used for working with records global addressInfo # Current Record global currentRecord # Record Count global recordCount # Image File location global pictureFile set addressFile "address.txt" ######################################### # Procedures # ######################################### proc findRecord { } { set strLast "" toplevel .find frame .find.f -borderwidth 1 -relief solid -padx 10 -pady 10 entry .find.f.e -borderwidth 5 -relief solid button .find.f.ok -text "Find" -command {set strLast [.find.f.e get]; lookup $strLast} button .find.f.cancel -text "Cancel" -command {destroy .find} pack .find.f grid .find.f.e -row 0 -column 0 -columnspan 2 -sticky news grid .find.f.ok -row 1 -column 0 -sticky news grid .find.f.cancel -row 1 -column 1 -sticky news } proc lookup {strLast} { global addressInfo global currentRecord puts "LOOKING for $strLast" dict for {id info} $addressInfo { dict with info { if {"$strLast" == "$LNAME"} { puts "NAME: $LNAME" puts "FOUND ONE" set currentRecord "$ID" clearRecord loadRecord } } } } # This procedure is used to load and display a record # from the dictionary proc loadRecord { } { global currentRecord global addressInfo .main.efirst insert 0 [dict get $addressInfo $currentRecord FNAME] .main.elast insert 0 [dict get $addressInfo $currentRecord LNAME] .main.eaddress insert 0 [dict get $addressInfo $currentRecord ADDRESS] .main.ecity insert 0 [dict get $addressInfo $currentRecord CITY] .main.estate insert 0 [dict get $addressInfo $currentRecord STATE] .main.ezip insert 0 [dict get $addressInfo $currentRecord ZIP] .main.ephone insert 0 [dict get $addressInfo $currentRecord PHONE] # Load the photo if {[dict get $addressInfo $currentRecord PHOTO] > 0} { set pictureFile [dict get $addressInfo $currentRecord PHOTO] image create photo addressPhoto -file $pictureFile .main.picture configure -image addressPhoto } } proc clearRecord {} { .main.efirst delete 0 end .main.elast delete 0 end .main.eaddress delete 0 end .main.ecity delete 0 end .main.estate delete 0 end .main.ezip delete 0 end .main.ephone delete 0 end .main.picture configure -image "" } proc addRecord {} { global currentRecord global recordCount global addressInfo global pictureFile # Clear current entries clearRecord set pictureFile "" set currentRecord [expr $recordCount +1] } proc nextRecord {} { global currentRecord global recordCount if { $currentRecord < $recordCount } { # Clear current entries clearRecord incr currentRecord loadRecord } } proc previousRecord {} { global currentRecord global recordCount if { $currentRecord > 1 } { # Clear current entries clearRecord set currentRecord [expr $currentRecord - 1] loadRecord } } proc saveRecord {} { global currentRecord global recordCount global addressFile global addressInfo global pictureFile # No Records Exist if {$currentRecord == 0} { incr currentRecord incr recordCount } dict set addressInfo $currentRecord ID "$currentRecord" dict set addressInfo $currentRecord FNAME "[.main.efirst get]" dict set addressInfo $currentRecord LNAME "[.main.elast get]" dict set addressInfo $currentRecord ADDRESS "[.main.eaddress get]" dict set addressInfo $currentRecord CITY "[.main.ecity get]" dict set addressInfo $currentRecord STATE "[.main.estate get]" dict set addressInfo $currentRecord ZIP "[.main.ezip get]" dict set addressInfo $currentRecord PHONE "[.main.ephone get]" dict set addressInfo $currentRecord PHOTO "$pictureFile" # Write the records to the file set fp [open $addressFile w+] dict for {id info} $addressInfo { dict with info { # Create an entry for the file set data "$ID,$FNAME,$LNAME,$ADDRESS,$CITY,$STATE,$ZIP, $PHONE,$PHOTO " # Write the entry to the file puts -nonewline $fp $data } } set recordCount [dict size $addressInfo] # Close the file close $fp } proc deleteRecord {} { global addressFile global addressInfo global currentRecord global recordCount if {$recordCount > 0} { set myTitle "Confirm Request" set myMessage "Select OK to delete the current record" set response [tk_messageBox -message $myMessage -title myTitle -type okcancel -icon warning] if {$response == "ok"} { puts "DELETE COUNT: $recordCount CURRENT: $currentRecord" set tempDict [dict remove $addressInfo $currentRecord] clearRecord puts "IN DELETE" set fp [open $addressFile w+] puts "DELETE FILE ID: $fp" set recnum 0 dict for {id info} $tempDict { dict with info { incr recnum # Create an entry for the file set data "$recnum,$FNAME,$LNAME,$ADDRESS,$CITY, $STATE, $ZIP,$PHONE,$PHOTO " puts "---" puts "NEW DATA: $data" # Write the entry to the file puts -nonewline $fp $data } } flush $fp close $fp puts "POST DELETE FILE WRITE - READING IN NEW FILE" # Clean up the dictionary files unset addressInfo unset tempDict # If we deleted the last record this avoids trying to read in an empty file if {[file size $addressFile] > 0} { set fp [open $addressFile r+] fconfigure $fp -buffering line gets $fp data set recno 0 while { $data > 0 } { puts "DATA ADDED TO DICT: $data TO RECNO: $recno" set data2 [split $data ","] incr recno dict set addressInfo $recno ID [lindex $data2 0] dict set addressInfo $recno FNAME [lindex $data2 1] dict set addressInfo $recno LNAME [lindex $data2 2] dict set addressInfo $recno ADDRESS [lindex $data2 3] dict set addressInfo $recno CITY [lindex $data2 4] dict set addressInfo $recno STATE [lindex $data2 5] dict set addressInfo $recno ZIP [lindex $data2 6] dict set addressInfo $recno PHONE [lindex $data2 7] dict set addressInfo $recno PHOTO [lindex $data2 8] set pictureFile [dict get $addressInfo $recno PHOTO] gets $fp data } set recordCount [dict size $addressInfo] puts "NEW addressInfo recordCount $recordCount " set currentRecord 1 # Load the first record loadRecord } else { set myTitle "Missing Records" set myMessage "No records exist, please add an entry and click save" tk_messageBox -message $myMessage -title $myTitle -type ok -icon warning set currentRecord 0 set recordCount 0 set pictureFile "" } } } } proc getPicture {} { global currentRecord global addressInfo global pictureFile set types { {{GIF} {.gif} } {{PPM} {.ppm} } {{All Files} * } } set filename [tk_getOpenFile -filetypes $types] if {$filename != ""} { # Now that we have the path to the desired picture # we copy it to the working directory # Get the destination filename # by splitting the fullpath into # elements and retrieving the last set listFile [file split $filename] set listCount [llength $listFile] set listIndex [expr $listCount - 1] set pictureFile [lindex $listFile $listIndex] # If the pictureFile already exists within the # working directory we do not copy it again if { [file exists $pictureFile] == 0 } { # Copy the image to the current directory if {[catch {file copy -force "$filename" $pictureFile} sError]} { tk_messageBox -message "File Copy Error $filename to $pictureFile" } } # Update the dictionary entry dict set addressInfo $currentRecord PHOTO $pictureFile # Update the image onscreen image create photo newPicture -file $pictureFile .main.picture configure -image newPicture } } ############################################# # END OF PROCEDURES ############################################# # Create the dictionary from the file on disk # if it exists and contains entries if { [file exists $addressFile]} { # If the file exists check that it has contents # Since we are managing the file through the application we can assume # for the sake of our application that it is in the correct format if { [file size $addressFile] > 0 } { set fp [open $addressFile r+] gets $fp data while {$data >0} { set data2 [split $data ","] set recno [lindex $data2 0] dict set addressInfo $recno ID [lindex $data2 0] dict set addressInfo $recno FNAME [lindex $data2 1] dict set addressInfo $recno LNAME [lindex $data2 2] dict set addressInfo $recno ADDRESS [lindex $data2 3] dict set addressInfo $recno CITY [lindex $data2 4] dict set addressInfo $recno STATE [lindex $data2 5] dict set addressInfo $recno ZIP [lindex $data2 6] dict set addressInfo $recno PHONE [lindex $data2 7] dict set addressInfo $recno PHOTO [lindex $data2 8] # Open the file set pictureFile [dict get $addressInfo $recno PHOTO] # Read the data using the gets gets $fp data } close $fp set recordCount [dict size $addressInfo] set currentRecord 1 # Load the first record loadRecord } else { set myTitle "Missing Records" set myMessage "No records exist, please add an entry and click save" tk_messageBox -message $myMessage -title $myTitle -type ok -icon warning set currentRecord 0 set recordCount 0 set pictureFile "" } } else { set myTitle "Missing configuration file" set myMessage "No address file exists, please add an entry and click save." tk_messageBox -message $myMessage -title myTitle -icon warning set currentRecord 0 set recordCount 0 set pictureFile " " }
18.191.181.36