Discussion:
ISO a way to select programmatically an entry from a popup
(too old to reply)
Helmut Giese
2024-09-12 23:31:34 UTC
Permalink
Hello out there,
it seems like as long as a popup is posted the app cannot do anything
- in particular it cannot post any events. Consider this script:
---
package require Tk
foreach ch [winfo children "."] {destroy $ch}

# Turn $x & $y into absolute coords
proc mkAbsCoords {c x y} {
# get the canvas's coord relative to the toplevel
set xOfs [expr {[winfo rootx $c]}]
set yOfs [expr {[winfo rooty $c]}]
return [list [expr {$x + $xOfs}] [expr {$y + $yOfs}]]
}

proc popupMenu {c x y} {
catch {destroy .popup}
set popup [menu .popup -tearoff false]
set inactiveBG #b2b2b2
$popup add command -label "Choose an op" \
-background #b2b2b2 -activebackground #b2b2b2 \
-activeforeground [$popup cget -fg]
$popup add command -label "Op 1" -command {puts "Op1 selected"}
$popup add command -label "Op 2" -command {puts "Op2 selected"}
lassign [mkAbsCoords $c $x $y] x y
tk_popup $popup $x $y
}

set num [lindex $argv 0]
set c [canvas .c -width 200 -height 200]
pack $c
set id [$c create rectangle 50 50 150 150 -fill lightyellow]
$c bind $id <Button-3> [list popupMenu $c %x %y]
update
if {$num} {
set event Button
} else {
set event ButtonPress
}
event generate $c <$event> -button 3 -x 100 -y 100 -warp 1
puts "Back from '$event'"
if {$num == 0} {
event generate $c <ButtonRelease> -button 3 -x 100 -y 100 -warp 1
puts "Back from 'ButtonRelease'"
}
---
and this output:
---
Microsoft Windows [Version 10.0.19045.4894]
(c) Microsoft Corporation. Alle Rechte vorbehalten.

d:\proj\_ToolsSE\Skeleton\TclTests>tclsh tst.tcl 1
Back from 'Button'
Op1 selected

d:\proj\_ToolsSE\Skeleton\TclTests>tclsh tst.tcl 0
Back from 'ButtonPress'
Back from 'ButtonRelease'
Op1 selected
---
To me this seems to clearly indicate that the selection cannot be
influenced by the controlling app: control only returns when the
selection has happened - which is too bad.

Or is there a trick by which one can influence the selection from a
popup?
Any idea will be highly appreciated.
Helmut
Oh, this is on Windows 64 bit under Tcl 8.6.10
greg
2024-09-14 05:44:16 UTC
Permalink
Post by Helmut Giese
Hello out there,
it seems like as long as a popup is posted the app cannot do anything
---
package require Tk
foreach ch [winfo children "."] {destroy $ch}
# Turn $x & $y into absolute coords
proc mkAbsCoords {c x y} {
# get the canvas's coord relative to the toplevel
set xOfs [expr {[winfo rootx $c]}]
set yOfs [expr {[winfo rooty $c]}]
return [list [expr {$x + $xOfs}] [expr {$y + $yOfs}]]
}
proc popupMenu {c x y} {
catch {destroy .popup}
set popup [menu .popup -tearoff false]
set inactiveBG #b2b2b2
$popup add command -label "Choose an op" \
-background #b2b2b2 -activebackground #b2b2b2 \
-activeforeground [$popup cget -fg]
$popup add command -label "Op 1" -command {puts "Op1 selected"}
$popup add command -label "Op 2" -command {puts "Op2 selected"}
lassign [mkAbsCoords $c $x $y] x y
tk_popup $popup $x $y
}
set num [lindex $argv 0]
set c [canvas .c -width 200 -height 200]
pack $c
set id [$c create rectangle 50 50 150 150 -fill lightyellow]
$c bind $id <Button-3> [list popupMenu $c %x %y]
update
if {$num} {
set event Button
} else {
set event ButtonPress
}
event generate $c <$event> -button 3 -x 100 -y 100 -warp 1
puts "Back from '$event'"
if {$num == 0} {
event generate $c <ButtonRelease> -button 3 -x 100 -y 100 -warp 1
puts "Back from 'ButtonRelease'"
}
---
---
Microsoft Windows [Version 10.0.19045.4894]
(c) Microsoft Corporation. Alle Rechte vorbehalten.
d:\proj\_ToolsSE\Skeleton\TclTests>tclsh tst.tcl 1
Back from 'Button'
Op1 selected
d:\proj\_ToolsSE\Skeleton\TclTests>tclsh tst.tcl 0
Back from 'ButtonPress'
Back from 'ButtonRelease'
Op1 selected
---
To me this seems to clearly indicate that the selection cannot be
influenced by the controlling app: control only returns when the
selection has happened - which is too bad.
Or is there a trick by which one can influence the selection from a
popup?
Any idea will be highly appreciated.
Helmut
Oh, this is on Windows 64 bit under Tcl 8.6.10
Hello
with event, invoke and unpost

https://www.tcl.tk/man/tcl8.6/TkCmd/menu.htm#M41



event generate $c <$event> -button 3 -x 100 -y 100 -warp 1
#num 1 or 2, 0 is the label
.popup invoke $num
.popup unpost
greg
2024-09-14 11:38:26 UTC
Permalink
Post by greg
Post by Helmut Giese
Oh, this is on Windows 64 bit under Tcl 8.6.10
Hello
with event, invoke and unpost
https://www.tcl.tk/man/tcl8.6/TkCmd/menu.htm#M41
event generate $c <$event> -button 3 -x 100 -y 100 -warp 1
#num 1 or 2, 0 is the label
.popup invoke $num
.popup unpost
from manual
pathName unpost
Unmap the window so that it is no longer displayed. If a
lower-level cascaded menu is posted, unpost that menu. Returns an empty
string. This subcommand does not work on Windows and the Macintosh, as
those platforms have their own way of unposting menus.

My suggestion with unpost doesn't help with Windows.
greg
2024-09-14 11:38:26 UTC
Permalink
Post by greg
Post by Helmut Giese
Oh, this is on Windows 64 bit under Tcl 8.6.10
Hello
with event, invoke and unpost
https://www.tcl.tk/man/tcl8.6/TkCmd/menu.htm#M41
event generate $c <$event> -button 3 -x 100 -y 100 -warp 1
#num 1 or 2, 0 is the label
.popup invoke $num
.popup unpost
from manual
pathName unpost
Unmap the window so that it is no longer displayed. If a
lower-level cascaded menu is posted, unpost that menu. Returns an empty
string. This subcommand does not work on Windows and the Macintosh, as
those platforms have their own way of unposting menus.

My suggestion with unpost doesn't help with Windows.
greg
2024-09-15 13:01:02 UTC
Permalink
Post by Helmut Giese
Hello out there,
it seems like as long as a popup is posted the app cannot do anything
---
package require Tk
foreach ch [winfo children "."] {destroy $ch}
# Turn $x & $y into absolute coords
proc mkAbsCoords {c x y} {
# get the canvas's coord relative to the toplevel
set xOfs [expr {[winfo rootx $c]}]
set yOfs [expr {[winfo rooty $c]}]
return [list [expr {$x + $xOfs}] [expr {$y + $yOfs}]]
}
proc popupMenu {c x y} {
catch {destroy .popup}
set popup [menu .popup -tearoff false]
set inactiveBG #b2b2b2
$popup add command -label "Choose an op" \
-background #b2b2b2 -activebackground #b2b2b2 \
-activeforeground [$popup cget -fg]
$popup add command -label "Op 1" -command {puts "Op1 selected"}
$popup add command -label "Op 2" -command {puts "Op2 selected"}
lassign [mkAbsCoords $c $x $y] x y
tk_popup $popup $x $y
}
set num [lindex $argv 0]
set c [canvas .c -width 200 -height 200]
pack $c
set id [$c create rectangle 50 50 150 150 -fill lightyellow]
$c bind $id <Button-3> [list popupMenu $c %x %y]
update
if {$num} {
set event Button
} else {
set event ButtonPress
}
event generate $c <$event> -button 3 -x 100 -y 100 -warp 1
puts "Back from '$event'"
if {$num == 0} {
event generate $c <ButtonRelease> -button 3 -x 100 -y 100 -warp 1
puts "Back from 'ButtonRelease'"
}
---
---
Microsoft Windows [Version 10.0.19045.4894]
(c) Microsoft Corporation. Alle Rechte vorbehalten.
d:\proj\_ToolsSE\Skeleton\TclTests>tclsh tst.tcl 1
Back from 'Button'
Op1 selected
d:\proj\_ToolsSE\Skeleton\TclTests>tclsh tst.tcl 0
Back from 'ButtonPress'
Back from 'ButtonRelease'
Op1 selected
---
To me this seems to clearly indicate that the selection cannot be
influenced by the controlling app: control only returns when the
selection has happened - which is too bad.
Or is there a trick by which one can influence the selection from a
popup?
Any idea will be highly appreciated.
Helmut
Oh, this is on Windows 64 bit under Tcl 8.6.10
Hello,
Windows 10 , Tcl/Tk 8.6.13

Without a change in the proc popupMenu the script is frozen.

list tk_popup $popup $x $y


# and invoke index for the selction 0, 1 and 2
#.popup invoke $num


package require Tk

foreach ch [winfo children "."] {destroy $ch}



# Turn $x & $y into absolute coords

proc mkAbsCoords {c x y} {

# get the canvas's coord relative to the toplevel

set xOfs [expr {[winfo rootx $c]}]

set yOfs [expr {[winfo rooty $c]}]

return [list [expr {$x + $xOfs}] [expr {$y + $yOfs}]]

}



proc popupMenu {c x y} {

catch {destroy .popup}

set popup [menu .popup -tearoff false]

set inactiveBG #b2b2b2

$popup add command -label "Choose an op" \

-background #b2b2b2 -activebackground #b2b2b2 \

-activeforeground [$popup cget -fg]

$popup add command -label "Op 1" -command {puts "Op1 selected"}

$popup add command -label "Op 2" -command {puts "Op2 selected"}

lassign [mkAbsCoords $c $x $y] x y

list tk_popup $popup $x $y

}



set num [lindex $argv 0]

set c [canvas .c -width 200 -height 200]

pack $c

set id [$c create rectangle 50 50 150 150 -fill lightyellow]

$c bind $id <Button-3> [list popupMenu $c %x %y]

update

if {$num} {

set event Button

} else {

set event ButtonPress

}

event generate $c <$event> -button 3 -x 100 -y 100 -warp 1

puts "Back from '$event'"

if {$num == 0} {

event generate $c <ButtonRelease> -button 3 -x 100 -y 100 -warp 1

puts "Back from 'ButtonRelease'"

}





.popup invoke $num





#Output

if {0} {

tclsh exahgnn.tcl 0

Back from 'ButtonPress'

Back from 'ButtonRelease'

^C



tclsh exahgnn.tcl 1

Back from 'Button'

Op1 selected



tk_popup>tclsh exahgnn.tcl 2

Back from 'Button'

Op2 selected

}
greg
2024-09-15 13:09:51 UTC
Permalink
    list tk_popup $popup $x $y
.popup invoke $num
Bad idea, after that the script will no longer work for normal use.
Helmut Giese
2024-09-15 23:17:51 UTC
Permalink
Hello Greg,
many thanks for caring for my problem. It turned out that my question
was not precise enough:
I am developping unit tests for my app and tried to simulate user
actions. In this course I found out that during a popup window the app
doesn't react to any 'event generate' commands, neither mouse nor
keyboard events - and this seems to be true.
Many thanks again
Helmut

Loading...