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!
Hello jp,
Welcome to the board.
Do not mix up variables in the TCL memory with the variables in newLISP.
(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")
)
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
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
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
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
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
Indeed you are right; under a new session newlisp fails to find the variable.
Jean-Pierre
Quote from: "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
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
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
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
Quote from: "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
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
>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.
;-)
And in the Second Edition its neighter on 198 nor 208 but at 170 :-)
(if we're talking about the global namespace callbacks..)
> 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
(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
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
>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.
the demo examples shipped with the Windows version also show how to bind events to buttons, mouse etc.
Lutz
here is a comprehensive example for an entry widget:
(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
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
listbox widget example
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
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
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
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
Those functions I mentioned are standard Tcl/Tk functions. In the 8000rc1 release I added some more explanations about handling variables with the global prefix ::.
Unfortunately I do very little Tcl/Tk stuff myself, so I depend on users like you pointing out specific problems they run into when interfacing with newLISP. This is how the 'scale' example got in to the manual showing how to work around a specific callback problem.
Before you told us that the :: prefix could be used, I didn't even know about it and tried to solve the problem doing a 'global varName' in each tk statement, which also works, but is kind of clumsy. I have the :: - technique now included in the manual.
Lutz