Communicating with Tk widgets from an oo::class object

Communicating with Tk widgets from an oo::class object

Post by sillymonke » Thu, 01 Oct 2009 04:37:25


Greetings!

I'm having problems controlling some aspects of Tk widgets from within
an oo::class object.
In the example below, I am trying (unsuccessfully) to use the menu
item's -command option to call a method:
-command my PrivateMethod

I've tried a dozen different ways, but so far no luck.
I'm also having similar issues with the ttk::scrollbar -yscrollcommand
option.

## CODE ##
package require Tcl 8.6
package require Tk 8.6

oo::class create myGui {
method showGui {} {
my variable ProgramName
set ProgramName "Example Program"

# window
wm title . "$ProgramName"
wm minsize . 240 120
grid [ttk::frame .f] -column 0 -row 0 -sticky nwes

# menu
menu .menubar
. configure -menu .menubar
.menubar add command -label "About..." -command my AboutThis
}

method AboutThis {} {
my variable ProgramName
tk_messageBox -title "About" -message "$ProgramName\nAbout my
program"
}
}

## USAGE ##
set vw [myGui new]
$vw showGui

Thoughts from the Tcl guru's?
Any advice for this confused Cocoa programmer is greatly appreciated!
 
 
 

Communicating with Tk widgets from an oo::class object

Post by sillymonke » Thu, 01 Oct 2009 10:13:41

After more digging I'm starting to find some clues.
This seems to be a namespace issue (no surprise there). Since
the .menubar widget exists in the global namespace, it (I'm guessing)
is looking for it's -command value in the same space.
So, how can I direct it to the method of an object? Is this possible?
Neither of these to work properly:

.menubar add command -label "About..." -command {[self
object]::AboutThis}
.menubar add command -label "About..." -command {[self object]
AboutThis}

Can Tk widgets be (easily) forced to exist in a namespace, and not as
children of "."?
Am I just completely off-target here?

 
 
 

Communicating with Tk widgets from an oo::class object

Post by Aric » Thu, 01 Oct 2009 14:14:15

On 29 sep, 19:13, " XXXX@XXXXX.COM "

> .menubar add command -label "About..." -command {[self> > object]::AboutThis}> > .menubar add command -label "About..." -command {[self objec>]
> AboutThi>} >>
> Can Tk widgets be (easily) forced to exist in a namespace, and not >s
> children of ".>?
> Am I just completely off-target here?

I'm no expert on TclOO, but if you change the name of the about method
to aboutThis (so that it is exported) and change your menu command to:

.menubar add command \
-label "About..." \
-command [list [self] aboutThis]

it should work.

If you are not committed to TclOO, you may also want to consider
Snit. Snit has special facilities for building GUI components, it's
stable, and it's extremely well documented and easy to learn (check
out the Snit FAQ: http://www.yqcomputer.com/
or http://www.yqcomputer.com/ ). Future versions
of Snit will probably use TclOO in the background.

Here's how your program might look in Snit:

package require snit

snit::widget myGui {
hulltype toplevel

component f
component menubar

variable ProgramName "Example Program"

constructor {args} {
install f using ttk::frame $win.f

install menubar using menu $win.menubar
$menubar add command \
-label "About" \
-command [mymethod AboutThis]

wm title $win $ProgramName
wm minsize $win 240 120
grid $f -sticky nsew
$hull configure -menu $menubar
}

method AboutThis {} {
tk_messageBox -title "About" -message "$ProgramName\nAbout my
program"
}
}

# usage:
# myGui .sampleGui

In your original program, you can only create one instance of the GUI
because it's hard-wired to the root window. The Snit version will
create as many instances of the GUI as you want, as long as you give
each one a unique name.

Enough evangelizing. I hope at least some of the above is helpful to
you.
 
 
 

Communicating with Tk widgets from an oo::class object

Post by Donal K. F » Fri, 02 Oct 2009 02:17:59

On 29 Sep, 15:37, " XXXX@XXXXX.COM "

> I've tried a dozen different ways, but so far no luck>
> I'm also having similar issues with the ttk::scrollbar -yscrollcomman>
> option.
[...>
> Thoughts from the Tcl guru's>
> Any advice for this confused Cocoa programmer is greatly appreciated!

I've thought about doing widgets with TclOO a fair bit in the past,
and you might want to check out the code in section 'Take 2' on
http://www.yqcomputer.com/ (It's a
little more code than I prefer to paste in a c.l.t message.)

Generally speaking, widgets *have* to be in the global namespace in
practice, and widget script callbacks are assumed to execute in the
global NS, so it's a bad idea to deviate from that. Gets
surprising... :-) The basic method of creating a callback that invokes
a method is like one of these two:

-command [namespace code [list my SomePrivateMethod $someArgument]]
-command [list [namespace which my] SomePrivateMethod $someArgument]

(Well, doesn't have to be -command of course.) For a public method,
you can go for this simpler code:

-command [list [self] somePublicMethod $someArgument]

I've not added any Snit-like conveniences for doing this sort of thing
more efficiently. Here's how you might do a 'mymethod' command:

proc ::oo::Helpers::mymethod {method args} {
list [uplevel 1 {namespace which my}] $method {*}$args
}

As you can see, it's pretty short (and that makes it available to all
methods too...)

Any more questions? Do ask here! I (or someone else) will get to them
as soon as I can.

Donal.