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] It looks like the upload-procedure of the wiki doesn't like .ico - files. <
> So, just copy any icon you like to the location of the program, and rename it to demo.ico ---- **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, change that "if 0"-section to "if 1") * Hotkeys (F1..F8, etc.) * Labels * Entry-fields * Messagebox * Title at top of window * Icon at top of window (currently, this needs an external file) * [frame]s, [pack] and [grid] to manage the layout There is lots of more advanced GUI-stuff not covered so far, e.g.: * Checkboxes * Radiobuttons * Fancy textformating, [font]s (i.e. for a nice help-window) * Listbox * 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. <
> BTW, I haven't found yet any good, nice, short routine for data-entry (such as m+ for menus). Also, there is no file-I/O for data or configuration. I haven't looked into the printing stuff yet, so if anybody thinks he is up to the task, you are welcome to fill in that part. ---- **See also** * [GUI Primer] - essentially my notes researching GUI-stuff on tcl/tk !!!!!! !!!!!! * http://wiki.tcl.tk/10705%|%Category Printing%|% - from that, some selected pages: ** [printing] - mostly discussion ** [Things holding Tcl back] <
> <
> ** [Printing under Windows] - not platform-independent ** [Printing text files under Windows] - using workarounds like exec, print, type, notepad ** [Printing a canvas under Windows] - using external utilities, via postscript or pdf *** [Printing a canvas using GhostScript] ** [Printing a text file to a lpr printer] - using filesystem/network/sockets ** [tclcups] - (page is in french ?) <
> <
> ** [Tcl/Tk Printing Support] - discussion and wishlist / GSoC 2009 *** http://wiki.tcl.tk/22182#pagetoc90d3f90b%|%GSoC 2009 - Printing%|% *** http://wiki.tcl.tk/22182#pagetoc66706faf%|%GSoC 2009 - Cicero refurbish%|% *** http://wiki.tcl.tk/22182#pagetoc3f61176f%|%GSoC 2009 - Glade Project%|% ** [Krzysztof Blicharski] - worked on "Tcl/Tk Printing Support" GSoC project (but no details there) ** [GSoC 2009 Executed Projects] - status "ok", but no details or links *** http://code.google.com/p/google-summer-of-code-2009-tcl/downloads/list *** http://svn.assembla.com/svn/tktopdf - "tk-to-pdf", Revision 154, 2009-08-18. <
>It looks like nobody cared after the project reached that point. ** [TkPrint] - List of several packages: *** http://pages.videotron.com/cclients/files/tkprint1.1.html%|%Tkprint 1.17%|% - 2002-02 "Free for non-commercial use" All in all, it looks like printing from Tcl/tk in a "native, portable way" is kind of a hard problem, and still mostly unsolved. <> Example | GUI