newLISP Fan Club

Forum => newLISP in the real world => Topic started by: jp on March 20, 2004, 10:10:26 PM

Title: newlisp-tk Entry widget does not display textvariable
Post by: jp on March 20, 2004, 10:10:26 PM
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!
Title:
Post by: HPW on March 20, 2004, 11:05:36 PM
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")
)
Title:
Post by: Lutz on March 21, 2004, 06:15:40 AM
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
Title:
Post by: jp on March 21, 2004, 08:45:13 AM
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
Title:
Post by: Lutz on March 21, 2004, 10:26:15 AM
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
Title:
Post by: jp on March 22, 2004, 07:07:33 AM
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
Title:
Post by: Lutz on March 22, 2004, 08:46:07 AM
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
Title:
Post by: jp on March 22, 2004, 02:56:18 PM
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
Title:
Post by: Lutz on March 22, 2004, 04:13:21 PM
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
Title:
Post by: jp on March 22, 2004, 10:24:11 PM
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
Title:
Post by: Lutz on March 23, 2004, 05:44:02 AM
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
Title:
Post by: HPW on March 23, 2004, 10:53:28 AM
>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.



;-)
Title:
Post by: newdep on March 23, 2004, 11:30:50 AM
And in the Second Edition its neighter on 198 nor 208 but at 170 :-)

(if we're talking about the global namespace callbacks..)
Title:
Post by: jp on March 23, 2004, 08:25:20 PM
> 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
Title: Transfer of Variable-contents from Tk to newLisp
Post by: gerhard zintl on March 25, 2004, 02:02:16 AM
(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
Title:
Post by: Lutz on March 25, 2004, 05:26:08 AM
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
Title:
Post by: HPW on March 25, 2004, 06:34:16 AM
>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.
Title:
Post by: Lutz on March 25, 2004, 07:19:53 AM
the demo examples shipped with the Windows version also show how to bind events to buttons, mouse etc.



Lutz
Title:
Post by: Lutz on March 25, 2004, 07:37:21 AM
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
Title: comprehensive example for an entry widget:
Post by: gerhard zintl on March 25, 2004, 08:17:08 AM
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
Title:
Post by: jp on March 27, 2004, 03:01:34 AM
listbox widget example
Title:
Post by: jp on March 27, 2004, 03:08:56 AM
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
Title:
Post by: jp on March 27, 2004, 05:34:47 AM
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
Title:
Post by: Lutz on March 27, 2004, 04:14:43 PM
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
Title:
Post by: jp on March 27, 2004, 04:35:41 PM
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
Title:
Post by: Lutz on March 28, 2004, 08:07:39 AM
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