Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Tk BrowseEntry with only the arrow button visible?

by elef (Friar)
on Dec 22, 2013 at 21:06 UTC ( [id://1068124]=perlquestion: print w/replies, xml ) Need Help??

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

Is there an easy way to use a BrowseEntry widget without the first item/current selection being displayed? I just want the arrow button to be visible until it's clicked. I tried -width => 1, but it doesn't work. The text field is small but it still shows up.
I also tried to hack the .pm but it's not working (not correctly, anyway).
I modified it so that the $e LabEntry widget is not packed (commented out line 77: $e->pack(-side => 'right', -fill => 'x', -expand => 1);). This works, but it causes the listbox to show up at the edge of the screen instead of below the button. This must be because the position is determined based on the position of the $e widget:
my $y1 = ($w->{_BE_Style} eq 'MSWin32' ? $a->rooty + $a->height : $e->rooty + $e->height + 3 # : $b->rooty + $e->height + 3 #edited ); my $bd = $c->cget(-bd) + $c->cget(-highlightthickness); # using the real listbox reqheight rather than the # container frame one, which does not change after resizing the # listbox my $ht = $s->Subwidget("scrolled")->reqheight + 2 * $bd; my $x1 = ($w->{_BE_Style} eq 'MSWin32' ? $e->Subwidget("entry")->rootx # ? $b->rootx #edited : $e->rootx # : $b->rootx #edited );



Fixing this so that $x1 and $y1 are set based on the position of the button is beyond my reach.
Is there a simpler solution? Is there a different drop-down list widget that is displayed as only a button?

Replies are listed 'Best First'.
Re: Tk BrowseEntry with only the arrow button visible?
by roboticus (Chancellor) on Dec 23, 2013 at 01:49 UTC

    elef:

    How about making the first entry an empty string or space?

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      The field still takes up space on the screen. I would like to make it go away completely, not just be empty.
Re: Tk BrowseEntry with only the arrow button visible? ( override Tk::BrowseEntry::SetBindings / sub Tk::JBrowseEntry::Popdown)
by Anonymous Monk on Dec 23, 2013 at 02:52 UTC

    Is there a simpler solution?

    DIY :)

    Is there a different drop-down list widget that is displayed as only a button?

    Don't know , maybe, would investigate tk j ... Tk::JFileDialog Tk::JComboBox Tk::JBrowseEntry ...

    Is there a simpler solution?

    Looking at a widgetdump, you can do  $jb1 ->Subwidget('entry')->packForget ; that works to hide it

    this messes up the width, so you'd have to bind the button to pack before invoking original button handler

    { my $parent = $jb1 ; my $arrow = $jb1 ->Subwidget('arrow'); my $callback = $arrow->bind('<Button-1>'); $jb1 ->Subwidget('entry')->packForget; $arrow->bind('<Button-1>', [ sub { my( $button, $jbl, $callbackarray ) = @_; warn "fucking @_\n"; warn "button($button) jbl($jbl) callback($callback)\n"; $jbl->Subwidget('entry')->pack(-side => "right", -fill => +'x', -padx => 0, -pady => 0, -expand => 1); my( $cb, @args ) = @$callbackarray; $cb->(@args); }, $parent, $callback, ] ); }

    This is only half ... if anything it tells you what to edit in Tk::JBrowseEntry :D in Tk::BrowseEntry::SetBindings ...

    update:

    #!/usr/bin/perl -- use strict; use warnings; use Tk; use Tk::BrowseEntry; Main( @ARGV ); exit( 0 ); sub Tk::BrowseEntry::Popdown { my ($w) = @_; if ( $w->{'_BE_savefocus'} && Tk::Exists( $w->{'_BE_savefocus'} ) +) { $w->{'_BE_savefocus'}->focus; delete $w->{'_BE_savefocus'}; } if ( $w->{'_BE_popped'} ) { my $c = $w->Subwidget('choices'); $c->withdraw; $w->grabRelease; if ( ref $w->{'_BE_grabinfo'} eq 'CODE' ) { $w->{'_BE_grabinfo'}->(); delete $w->{'_BE_grabinfo'}; } $w->{'_BE_popped'} = 0; $w->Subwidget('entry')->packForget; } } sub Tk::BrowseEntry::BtnDown { my ($w) = @_; return if $w->cget( '-state' ) eq 'disabled'; if ($w->{'_BE_popped'}) { $w->Popdown; $w->{'_BE_buttonHack'} = 0; } else { $w->Subwidget('entry')->pack(-side => 'right', -fill => 'x', - +expand => 1); $w->update; $w->PopupChoices; $w->{'_BE_buttonHack'} = 1; } } sub Main { my $mw = tkinit(); my $var = 'lelabel'; my $b = $mw->BrowseEntry(-label => "Label", -variable => \$var); $b->insert("end", "opt1"); $b->insert("end", "opt2"); $b->insert("end", "opt3"); $b->Subwidget('entry')->packForget; $b->pack; MainLoop; }
      Thanks.
      I tried your code posted as an update, and it mostly does what I want, but the entry field still shows up when I click the button. I would want it to stay hidden all the time. I tried removing the whole BtnDown sub, removing just the $w->Subwidget('entry')->pack line, and adding a packForget right after it. The result is the same in all three cases: the entry field is hidden, but the listbox that pops up starts at the left edge of the screen and stretches all the way to the button. I tried looking in the BrowseEntry.pm to see what sets the width but most of it goes way over my head. Adding -listwidth   => 30 brings me back to where I started: the listbox is the correct width but it's at the edge of the screen.

        :) ... blah blah ... :)

        so DIY , a button, onclick popup a toplevel, popoff when toplevel loses focus (or mainwindow gains focus)

        its easier to popup a genuine Tk::Menu ...

Re: Tk BrowseEntry with only the arrow button visible?
by kcott (Archbishop) on Dec 29, 2013 at 02:21 UTC

    G'day elef,

    From your description, it sounds like Tk::Optionmenu is what you're after. If you look in the widget demo, you'll see examples under "Menus: 3. Menubuttons.": there's sample code for Optionmenu() as well as a native_optionmenu() subroutine — one of these should be suitable.

    However, if you really must use Tk::BrowseEntry, this seems to do what you want:

    #!/usr/bin/env perl use strict; use warnings; use Tk; use Tk::BrowseEntry; my $mw = MainWindow->new; $mw->geometry('300x400+50+50'); my $ctrl_F = $mw->Frame->pack(-side => 'bottom'); $ctrl_F->Button(-text => 'Exit', -command => sub { exit })->pack; my $app_F = $mw->Frame->pack(-side => 'top', -fill => 'both', -expand +=> 1); my $be_var; my $be = $app_F->BrowseEntry(-variable => \$be_var); $be->insert(end => "Option $_") for 1 .. 9; $be->pack; $be->Subwidget('entry')->packForget; MainLoop;

    The entry box never appears.

    The listbox doesn't shift to the left (which you mentioned in another part of this thread). The default -side for pack() is 'left': perhaps look at whatever you've used for this.

    I wasn't entirely sure what you meant by "I just want the arrow button to be visible until it's clicked.". I'm on a *nix system: when the listbox appears, it covers the button. When I specified -style => 'MSWin32', the listbox appeared just below the button; with -style => 'unix', it returned to my OS's default of covering the button: perhaps consider that setting to get the look-and-feel you're after.

    -- Ken

      Thanks, but this does the same as a couple of the above solutions: the listbox that pops up starts at the left edge of the screen and stretches all the way to the button.
      Screenshot

      I have looked at optionmenu before, but it displays the first or currently selected option on the button. I could see no obvious way of displaying a small blank button without text. I'll play with it though.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1068124]
Approved by taint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (9)
As of 2024-03-28 09:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found