Page 1 of 2
newlisp-tk Entry widget does not display textvariable
Posted: Sun Mar 21, 2004 6:10 am
by jp
I have been trying to mimic the passing of a tcl variable into the newlisp-tk entry widget but alas, regardless the way I am trying to bring the variable into the entry widget it fails.
============ test.tcl
set ok {Entry!}
wm title . $ok
entry .e -width 30 -textvariable ok
pack .e
=========== test.lsp
(define (test)
(tk "if {[winfo exists .test] == 1} {destroy .test}")
(tk "toplevel .test")
(set! ok (tk "set display {entry!}"))
(tk "wm title .test " ok)
(tk "entry .test.e -width 30 -textvariable " ok)
(tk "pack .test.e")
)
Here the variable is assigned to the tk widget title but fails to be acknowledged by the entry widget.
Needless to say I have tried all sorts of combinations which come to the mind; nothing seems to let newlisp-tk to give a pre-established variable to the entry widget. Could someone be so kind to cast some light on it!
Posted: Sun Mar 21, 2004 7:05 am
by HPW
Hello jp,
Welcome to the board.
Do not mix up variables in the TCL memory with the variables in newLISP.
Code: Select all
(define (test)
(tk "if {[winfo exists .test] == 1} {destroy .test}")
(tk "toplevel .test")
(tk "global display;set display {entry!}")
(tk "global display;wm title .test $display")
(tk "entry .test.e -width 30 -textvariable display")
(tk "pack .test.e")
)
Posted: Sun Mar 21, 2004 2:15 pm
by Lutz
You also could put everything in one string, limited by [text] ...[/text]
(define (test)
(tk
[text]
if {[winfo exists .test] == 1} {destroy .test};
toplevel .test;
global display;
set display {entry!};
wm title .test $display;
entry .test.e -width 30 -textvariable display;
pack .test.e;
[/text]
))
I think the important thing here to mention is, that the -textvariable wants a variable name, not the contents string. And ist seems to work only with a top level variable. Taking the 'global display' statement away, things don't work anymore. Everyting newLISP passes to TCL/TK will be executed not at top level, but inside a subroutine, this is why the 'global display' statement was necessary.
Lutz
Posted: Sun Mar 21, 2004 4:45 pm
by jp
Thanks a lot Hans-Peter and Lutz for the prompt replies
Actually, I was aware that –textvariable expected a variable name and I did make an attempt to declare display as global but as I could not chain it properly it did fail so I made a synoptic representation instead.
Perhaps a paragraph on the newlisp-tk documentation should be devoted on the proper chaining of commands for the interfacing between newlisp and tk.
Now with the overcoming of the hurdles interfacing the tk entry widget nothing stand in the way of a true interactivity between newlisp and tk.
Jean-Pierre
Posted: Sun Mar 21, 2004 6:26 pm
by Lutz
Thanks Jean-Pierre for the suggestion and welcome to the discussion forum.
The next version of the manual will expand on this a little bit more. What we really need is a comprehensive example with all the basic widgets in it, explaining and showing all the specifics when interacting between newLISP and Tcl/Tk. I hope one day I will get around doing it.
Lutz
Posted: Mon Mar 22, 2004 3:07 pm
by jp
I realise, if one finds the constant calling of the global variable inopportune, one can directly access the variable with the following...
(define (test)
(tk "if {[winfo exists .test] == 1} {destroy .test}")
(tk "toplevel .test")
(tk "variable display")
(tk "set display {entry!}")
(tk "wm title .test $::display")
(tk "entry .test.e -width 30 -textvariable display")
(tk "pack .test.e")
)
Jean-Pierre
Posted: Mon Mar 22, 2004 4:46 pm
by Lutz
It works for the title but then I still get "cant read ::display no such variable", I think there was some thing still in your Tcl/Tk namespace from before? Try it with a fresh start of newLISP-tk.
Lutz
Posted: Mon Mar 22, 2004 10:56 pm
by jp
Indeed you are right; under a new session newlisp fails to find the variable.
Jean-Pierre
Lutz wrote:It works for the title but then I still get "cant read ::display no such variable", I think there was some thing still in your Tcl/Tk namespace from before? Try it with a fresh start of newLISP-tk.
Lutz
But the following seems to work!
(define (test)
(tk "if {[winfo exists .test] == 1} {destroy .test}")
(tk "toplevel .test")
(tk "variable display")
(tk "set ::display {entry!}")
(tk "wm title .test $::display")
(tk "entry .test.e -width 30 -textvariable ::display")
(tk "pack .test.e")
)
Jean-Pierre
Posted: Tue Mar 23, 2004 12:13 am
by Lutz
thanks Jean-Pierre, I will include this example in the manual, because the question about 'how to keep variable state' is asked frequently. It seems that the key is the 'variable varName' declaration and the reference to it with ::varName
Lutz
Posted: Tue Mar 23, 2004 6:24 am
by jp
Actually, 'variable ::varName' declaration and the reference to it with ::varName
The advantage of having direct access to tcl variables is to let tk have as many variables as it is deemed necessary for the good conduct of tk widgets processes, but also that newlisp can always modify them at will!
Jean-Pierre
Lutz wrote:thanks Jean-Pierre, I will include this example in the manual, because the question about 'how to keep variable state' is asked frequently. It seems that the key is the 'variable varName' declaration and the reference to it with ::varName
Lutz
Posted: Tue Mar 23, 2004 1:44 pm
by Lutz
It seems that the variable declaration (variable ::display) is not necessary at all. The global namespace prefix :: seems to be enough, and 'set' then instoruces the variable:
(define (test)
(tk "if {[winfo exists .test] == 1} {destroy .test}")
(tk "toplevel .test")
(tk "set ::display {entry!}")
(tk "wm title .test $::display")
(tk "entry .test.e -width 30 -textvariable ::display")
(tk "pack .test.e")
)
Lutz
ps: see "Practical Programming in Tcl and Tk" by Brent B. Welch, p.198
Posted: Tue Mar 23, 2004 6:53 pm
by HPW
>ps: see "Practical Programming in Tcl and Tk" by Brent B. Welch, p.198
This is correct for the third edition.
For the current fourth edition take a look at p.208.
;-)
Posted: Tue Mar 23, 2004 7:30 pm
by newdep
And in the Second Edition its neighter on 198 nor 208 but at 170 :-)
(if we're talking about the global namespace callbacks..)
Posted: Wed Mar 24, 2004 4:25 am
by jp
> It seems that the variable declaration (variable ::display) is not necessary at all.
I guess, it will depend entirely under which context we want the tcl variables to operate on, my impression is from the standpoint of newlisp, (variable display) will always be sufficient.
Jean-Pierre
Transfer of Variable-contents from Tk to newLisp
Posted: Thu Mar 25, 2004 10:02 am
by gerhard zintl
(define (test)
(tk "if {[winfo exists .test] == 1} {destroy .test}")
(tk "toplevel .test")
(tk "set ::display {entry!}")
(tk "wm title .test $::display")
(tk "entry .test.e -width 30 -textvariable ::display")
(tk "pack .test.e")
)
I'm just starting to experiment with newLisp.
How could you send back the content of the entry in ::display to newLisp?
Thanks in advance.
Gerhard Zintl
Posted: Thu Mar 25, 2004 1:26 pm
by Lutz
You could do the following:
(tk "set ::display")
or any other Tcl/Tk statement which would return the contents of the variable. This would return the contents of the entry widget in a string.
Read the chapter about "Writing applications with newLISP and Tcl/Tk" in the manual.
Lutz
Posted: Thu Mar 25, 2004 2:34 pm
by HPW
>How could you send back the content of the entry in ::display to newLisp?
I think he means how to push it back from the GUI to newLISP.
The we must bind an TK event (for eample return key in entry widget) to a proc, where we call a function in newLISP.
A look into newLISP-tk.tcl from the source may be usefull.
Posted: Thu Mar 25, 2004 3:19 pm
by Lutz
the demo examples shipped with the Windows version also show how to bind events to buttons, mouse etc.
Lutz
Posted: Thu Mar 25, 2004 3:37 pm
by Lutz
here is a comprehensive example for an entry widget:
Code: Select all
(define (entry )
(tk "if {[winfo exists .entry] == 1} {destroy .entry}")
(tk "toplevel .entry")
(tk "wm title .entry {entry example}")
(tk "entry .entry.e -width 30 -textvariable ::display")
(tk "bind .entry.e <Return> { Newlisp {(silent (get-entry-text))} }")
(tk "pack .entry.e"))
(define (get-entry-text )
(println (tk "set ::display")))
Whenever you hit the return/enter key you will see the contents of the entry widget displayed in the console. There are many other events you can bind to Tcl/Tk widget, get a book, i.e.: "Practical Programming in Tcl and Tk" by Brent Welch.
Lutz
comprehensive example for an entry widget:
Posted: Thu Mar 25, 2004 4:17 pm
by gerhard zintl
Hallo Lutz,
I tested your 'entry example' and it runs like a charm.
Thank you very much for your prompt help.
I have some experience with Tcl/Tk and also Brent Welch's book fourth ed.
My problem was the data transfer connection between TK and newLISP
Gerhard Zintl
Posted: Sat Mar 27, 2004 11:01 am
by jp
listbox widget example
Posted: Sat Mar 27, 2004 11:08 am
by jp
Lutz gave a comprehensive entry widget example.
Here is listbox widget example.
It is a file chooser, where one has simply to click a given file to either open or run it. One can easily extend it to make newlisp to distinguish directories and files and navigate drives and make newlisp to do all sorts of what not!
I choose to use start.exe from win98 instead of the internal command assoc since that command exists only on Win2k and WinXP.
Jean-Pierre
------------------------- fc.lsp
(define (listbox)
(tk
[text]
if {[winfo exists .fc] == 1} {destroy .fc}
toplevel .fc
set ::result ""
wm title .fc {File Chooser}
frame .fc.fr -borderwidth 10
pack .fc.fr -side top -expand yes -fill y
scrollbar .fc.fr.yscroll -orient vertical -command ".fc.fr.list yview"
scrollbar .fc.fr.xscroll -orient horizontal -command ".fc.fr.list xview"
listbox .fc.fr.list -width 20 -height 10 -setgrid 1 -yscroll ".fc.fr.yscroll set" -xscroll ".fc.fr.xscroll set"
button .fc.b -text {Exit All} -command exit
label .fc.lb -textvariable ::result
pack .fc.lb .fc.b -side top -fill x
grid .fc.fr.list -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
grid .fc.fr.yscroll -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
grid .fc.fr.xscroll -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
grid rowconfig .fc.fr 0 -weight 1 -minsize 0
grid columnconfig .fc.fr 0 -weight 1 -minsize 0
foreach i [lsort [glob *]] {
.fc.fr.list insert end $i
}
proc fiche {} {
set entry [open tmp w]
puts $entry $::result
close $entry
}
bind .fc.fr.list <ButtonRelease-1> {
set ::result [selection get]
set ext [string tolower [file extension $::result]]
switch -glob -- $ext {
"" { exec notepad $::result & }
".bat" { exec notepad $::result & }
".ini" { exec notepad $::result & }
".sys" { exec notepad $::result & }
".lsp" { fiche ; Newlisp {(entry)} }
default { exec c:/dos/start $::result & }
}
}
[/text]
))
(define (entry)
(eval (append '(load) (parse (read-file "tmp"))))
(delete-file "tmp"))
--------------------- end of code
Posted: Sat Mar 27, 2004 1:34 pm
by jp
Easier and little bit faster
Jean-Pierre
--------------------------- fx.lsp
(define (fx)
(tk
[text]
if {[winfo exists .fx] == 1} {destroy .fx}
toplevel .fx
wm title .fx {File Chooser}
frame .fx.fr -borderwidth 10
pack .fx.fr -side top -expand yes -fill y
scrollbar .fx.fr.yscroll -orient vertical -command ".fx.fr.list yview"
scrollbar .fx.fr.xscroll -orient horizontal -command ".fx.fr.list xview"
listbox .fx.fr.list -width 20 -height 10 -setgrid 1 -yscroll ".fx.fr.yscroll set" -xscroll ".fx.fr.xscroll set"
button .fx.b -text {Exit All} -command exit
label .fx.lb -textvariable ::result
pack .fx.lb .fx.b -side top -fill x
grid .fx.fr.list -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news
grid .fx.fr.yscroll -row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
grid .fx.fr.xscroll -row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
grid rowconfig .fx.fr 0 -weight 1 -minsize 0
grid columnconfig .fx.fr 0 -weight 1 -minsize 0
foreach i [lsort [glob *]] {
.fx.fr.list insert end $i
}
bind .fx.fr.list <ButtonRelease-1> {
set ::result [selection get]
set ext [string tolower [file extension $::result]]
switch -glob -- $ext {
"" { exec notepad $::result & }
".bat" { exec notepad $::result & }
".ini" { exec notepad $::result & }
".sys" { exec notepad $::result & }
".lsp" { Newlisp {(entry)} }
default { exec c:/dos/start $::result & }
}
}
[/text]
))
(define (entry) (eval (append '(load) (list (tk "set ::result")))))
-------------------- end of code
Posted: Sun Mar 28, 2004 12:14 am
by Lutz
Thanks for the comprehensive listbox example, a nice piece showing how to use the grid manager in Tk organizing several widgets.
Note that Tcl/Tk also has some built-in dialogs already, some of them for files too, try these:
(tk "tk_chooseColor")
(tk "tk_messageBox -message {Hello World!}")
(tk "tk_getOpenFile")
(tk "tk_getSaveFile")
All of these have many options but work in their minimalistic form shown here with useful return values.
Lutz
Posted: Sun Mar 28, 2004 12:35 am
by jp
Thanks Lutz
Perhaps all the outstanding features of the newlisp tk interface should be mentioned in the newlip-tk documentation to ease the interfacing and to prevent the inadvertent 'reinventing of the wheel'.
Jean-Pierre