BernieC has asked for the wisdom of the Perl Monks concerning the following question:

I have an app that uses Optionmenu and it is just the right widget for it (tried BrowseEntry, etc, and didn't like it as much). My problem it that the list of choices has gotten fairly large and having the scroll-arrowheads at the top and bottom works but is annoying. I'd rather have the options open as a multi-column list but I haven't the beginning of a clue how to hack Tk::Optionmenu to make that happen. Thanks!

Replies are listed 'Best First'.
Re: Multi-column Tk:Optionmenu?
by BrowserUk (Patriarch) on Nov 04, 2007 at 21:15 UTC

    This might help you.

    #! perl -slw use strict; use Tk; use Tk::Widget; my $mw = MainWindow->new; my $value = '?'; my $mb = $mw->Menubutton( -relief => 'raise', -textvariable => \$value )->pack; $mb->configure( -activeforeground => 'blue', -disabledforeground => 'black' ); #$mb->bindtags([$mb,ref($mb),$mb->toplevel,'all']); $mb->bind( '<Button-3>', $mb->bind( 'Tk::Menubutton', '<Button- +1>' ) ); $mb->bind( '<ButtonRelease-3>', $mb->bind( 'Tk::Menubutton', '<ButtonR +elease-1>' ) ); $mb->bind( '<B3-Motion>', $mb->bind( 'Tk::Menubutton', '<B1-Moti +on>' ) ); $mb->bind( '<Button-1>', sub{ Tk->break } ); $mb->bind( '<ButtonRelease-1>', sub{ Tk->break } ); $mb->bind( '<B1-Motion>', sub{ Tk->break } ); $mb->bind( '<Double-Button-1>', sub{ $_[0]->configure( -state => 'disa +bled' ); Tk->break; } ); my $menu = $mb->Menu( -tearoff => 0, -type => 'normal' ); $mb->configure( -menu => $menu ); for my $cell ( 1 .. 9 ) { $menu->command( -label => " $cell ", ## Critical whitespace! -columnbreak => (( $cell % 3) == 1 ), -hidemargin => 1, -command => sub { print $value=$cell } ); } MainLoop;

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Multi-column Tk:Optionmenu?
by zentara (Cardinal) on Nov 04, 2007 at 20:07 UTC
    If I were you, I would forget about trying to hack the Optionmenu, and just make your own menu. For instance, just make an icon in your app (or bind to the pointer location to have it open wherever you click), and when you click it, it opens a toplevel window containing whatever multicolumn widget you want. Persoanlly I would use a Canvas and write columns of text to it, tagging each text item to call an appropriate subroutine. Otherwise, you can search for examples of "Cascading menus". Hacking Tk menus can be daunting, there are alot of unamed AoA's nestled in them, and they are bears to figure out. It is easier to make your own, if you want alot of customization. See $menu->insert problem in Perl/Tk for an idea of how tricky it gets.

    But someone else may come up with an easy answer for you..... thats the way it goes with Perl/Tk. :-)


    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
      Thanks for the suggestion! I'm relatively new to Tk (I'm a very long time Perl and CGI hacker moving over to using Tk), and there are lots of chunks of Tk I'm not really familiar with (hell, that I barely know anything about..:o)). Canvas is one such, but it looks like it'd make for a simple solution for exactly what I want. Not to mention a VERY handy widget to have in my arsenal... So thanks again!
        I've looked at the Canvas widget and it is definitely a good thing for me to have in my Tk arsenal, but it feels wrong for this application. But the approach got me thinking and wouldn't this work: I'll have a button that pops open a new TopLevel, and I'll just populate the TopLevel with *radiobuttons*. no need that I can see for an intermediary layer of widgets. Just a simple loop with packing a frame into the TL, then packing *it* with radio buttons in for as long as a max-length column should be, then another frame, more radiobuttons, until I run out. They'll all store their value into the same var and have the same callback to deal with the menu selection. [I'd post sample code, but: 1) not written yet, and 2) it seems simple enough that I can't imagine it won't do what I need (or be all that difficult)). It's feeling like about five lines of Perl to do..:o) Am I missing something or is it really the case that this simple approach will get me what I was looking for?