if 0 { <> ---- **Introduction** [MiHa] 2015-05-13: This is a demo for a tcl/tk-program with all the essential GUI-elements. <
> It acts as a simple invoice-program with menu, entry-form and output (planned: one printed page). All the data is just strings of text, no validation, no calculation. With ideas and code from the following pages: * [grid] - "Basic Example" * [Ask, and it shall be given # 8] - "grid-layouts" * [m+] - Menu-creator by [RS] * [ClockDemo] - console & debugging } ---- **Program 1** ======tcl # InvoiceDemo07.tcl - Mike Hase - 2015-05-19 # http://wiki.tcl.tk/29284 # Simple "invoice"-themed GUI-demo, with menu, form for data-entry, output to screen and printer. # (output to printer is not done yet) package require Tk set Prog(Title) "Invoice-Demo" set Prog(Version) "v0.07" set Prog(Date) "2015-05-20" set Prog(Author) "Mike Hase" set Prog(Contact) "me@example.com" set Prog(About) "A GUI-demo (disguised as an invoice-program:)\nPlus a printer-test." #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ global data maxFNr set FieldNames1 {"Date " Title Name Street City Phone} #set FieldNames2 { art1Nr art1qty art1desc art1price price1} set FieldNames2 { Article-Number Quantity Description Price Total} set fNr 0 set artNr 0 # Build data-entry form: ## Todo: put this form into its own dialog #: Frame for customer-data: frame .f1 ;# -background red set hdr [label .f1.lbHdr -text "Customer:"] grid $hdr -columnspan 2 -pady 8 foreach field $FieldNames1 { incr fNr set data($fNr) $fNr ;## Test set lb [label .f1.lb$field -text $field] set en [entry .f1.en$field -justify left -textvar data($fNr) ] grid $lb $en -padx 4 -pady 2 grid $lb -sticky e grid $en -sticky ew } #: Frame for article-data: # Same layout as above. Todo: place all fields for an article in one line frame .f2 ;# -background green incr artNr ;# Todo: extend to more articles set hdr [label .f2.hdr -text "Purchase:"] grid $hdr -columnspan 2 -pady 8 foreach field $FieldNames2 { incr fNr set data($fNr) $fNr ;## set lb [label .f2.lb$field -text $field] set en [entry .f2.en$field -justify right -textvar data($fNr) ] grid $lb $en -padx 4 -pady 2 grid $lb -sticky e grid $en -sticky ew } set maxFNr $fNr if 0 { ;# these buttons can be used as an alternative to the m+menu #: Frame for buttons: frame .f8 -background blue button .f8.b1 -text New -command { data0 } button .f8.b2 -text Test1 -command { data1 } button .f8.b3 -text Test2 -command { data2 } button .f8.b4 -text Show -command { showData } button .f8.b5 -text Print -command { printData } button .f8.b6 -text Exit -command { exit } grid .f8.b1 .f8.b2 .f8.b3 .f8.b4 .f8.b5 .f8.b6 pack .f1 .f2 .f8 -side top } pack .f1 .f2 -side top #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ # Menu: proc m+ {head name {cmd ""}} { #: Menu-creator "m+" by R.Suchenwirth and DKF, 2006-08-24, see http://wiki.tcl.tk/16327 # Uses the undocumented and unsupported feature ::tk::UnderlineAmpersand if {![winfo exists .m.m$head]} { foreach {l u} [::tk::UnderlineAmpersand $head] break .m add cascade -label $l -underline $u -menu [menu .m.m$head -tearoff 0] } if {[regexp ^-+$ $name]} { .m.m$head add separator } else { foreach {l u} [::tk::UnderlineAmpersand $name] break .m.m$head add command -label $l -underline $u -comm $cmd } } # GUI: define menu, bindings . configure -menu [menu .m] m+ &File &Open { Dummy "Open" } m+ &File &Save { Dummy "Save" } m+ &File ----- m+ &File &Exit exit m+ &Edit &Clear data0 m+ &Edit Testdata&1 data1 m+ &Edit Testdata&2 data2 m+ &Output &List showData m+ &Output &Print printData m+ &Help &About About m+ &Help &Help Help m+ &Help ----- m+ &Help &Debug { console show } bind all About bind all { console show } bind all exit bind all data0 bind all data1 bind all data2 bind all showData #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ proc Dummy {txt} { #: Alert: "Function X not implemented yet" bell tk_messageBox -icon warning -title "Demo" \ -message "Function '$txt' not implemented yet." } proc About {} { #: Short info about the program global Prog set txt "$Prog(Title) $Prog(Version) - " append txt "$Prog(Date)\nby $Prog(Author) - $Prog(Contact)\n\n$Prog(About)" tk_messageBox -icon info -message $txt -title "About $Prog(Title) $Prog(Version)" } proc Help {} { Dummy Help } ;# needs work #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ # Routines to edit/fill in data: proc data0 {} { #: Clear data in entry-fields for {set f 1} {$f <= $::maxFNr} {incr f} { set ::data($f) "" } } proc data1 {} { #: Fill entry-fields with testdata set ::data(1) "2015-05-13" set ::data(2) "Mr." set ::data(3) "Smith" set ::data(4) "Mainstreet 123" set ::data(5) "Newtown" set ::data(6) "555-6789" set ::data(7) "0815" set ::data(8) "2" set ::data(9) "T-Shirt" set ::data(10) " 9.99" set ::data(11) "19.98" } proc data2 {} { #: Fill entry-fields with testdata set fNr 0 set values { "2015-05-14" "Mrs." "Miller" "Highstreet 99" "Oldsville" "555-9876" "0816" "1" "T-Shirt XL" "12.34" "12.34" } foreach v $values { incr fNr set ::data($fNr) $v } } #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ # Output-Routines: proc listData {} { #: Show the data on the console global data maxFNr puts "INVOICE\n==" for {set f 1} {$f <= $maxFNr} {incr f} { puts "Field#$f : $data($f)" } puts "--\nTHANKS !" } proc showData {} { #: Show the data in a simple messagebox global data maxFNr set txt "INVOICE\n==\n" for {set f 1} {$f <= $maxFNr} {incr f} { append txt "Field#$f : $data($f)\n" } append txt "--\nTHANKS !" tk_messageBox -icon info -message $txt -title "ShowData" } # Todo: proc printData {} { Dummy printData } #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ #: Test+Debug: proc ? {} { help } proc help {} { puts "\n$::Prog(Title) $::Prog(Version)" puts "--" puts "argv0 : $::argv0" puts "argv : $::argv" puts "tcl/tk: $::tcl_patchLevel / $::tk_patchLevel \n" puts "d0,d1,d2,s,l:data0,data1,data2,listData,showData ?:help e:exit \n" } proc d0 {} { data0 } proc d1 {} { data1 } proc d2 {} { data2 } proc l {} { listData } proc s {} { showData } proc e {} { exit } #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+ #: Main: wm title . "$Prog(Title) $Prog(Version)" help # Todo: make and include an icon here if {[file exists demo.ico]} { wm iconbitmap . demo.ico } focus -force . ### EOF ### ====== ---- Example icon: [InvoiceDemo_icon] **Output** ======none Invoice-Demo: ... ====== ---- **Remarks** '''MiHa''': This is a nice small demo of a simple program using only basic, essential GUI-features: * Menu * Buttons (to see them, uncomment that "if 0"-section) * Hotkeys * Labels * Entry-fields * Messagebox * Title at top of window * Icon at top of window (currently, this needs an external file) * frames, pack and grid There is lots of more advanced GUI-stuff not covered so far, e.g.: * Checkboxes * Radiobuttons * Fancy textformating, fonts (i.e. for a nice help-window) * Listview * Scrollbars * dialog-windows separate from the main-window (i.e. for the data-entry form) But if any of that gets included, and the program gets more complex, <
> it might be better to put that into a separate program. The data is just simple strings of text, all of the same length, no validation, no calculation, no special logic, etc. <
> This definitely needs work for any real-world application. Also, there is no file-I/O for data or configuration. I haven't looked into the printing stuff yet, so if anybody feels competent, you are welcome to fill in that part. ---- '''See also:''' * [GUI Primer] * http://wiki.tcl.tk/10705%|%Category Printing%|% ** [printing] ** [Printing under Windows] ** [Printing text files under Windows] ** [Printing a canvas under Windows] ** [Printing a text file to a lpr printer] ** [Tcl/Tk Printing Support] ** [TkPrint] <> Example | GUI