Is there a way to use balloon on radiobutton in Perl Tk? I want to display a balloonmsg and statusmsg when I hover over the buttons, if possible. I've googled but it doesn't seem like there is any documentation on this functionality. I wrote a simple code to portray my idea because I can't share the original code:
use Tk;
use Tk::Balloon;
$window = new MainWindow;
$window -> title("Direction");
$window_frame = $window -> Frame();
$window_frame -> pack(-anchor => 'w', -fill => 'both');
$status_bar = $window_frame -> Label(-relief => 'groove') -> pack(-side => 'bottom', -fill => 'x');
$direction = 'Left';
foreach('Left', 'Right', 'Up', 'Down') {
$direction_button = $window_frame -> Radiobutton(-text => $_, -variable => \$direction, -value => $_)
-> pack(-side => 'left', -anchor => 'center', -padx => '15');
}
MainLoop;
And here is an image of the GUI:
The Tk::Balloon SYNOPSIS shows you can call Balloon on your main window and attach the balloon popup to each button, with the message showing up in your status bar:
use warnings;
use strict;
use Tk;
use Tk::Balloon;
my $window = new MainWindow;
$window->title("Direction");
my $window_frame = $window -> Frame();
$window_frame -> pack(-anchor => 'w', -fill => 'both');
my $status_bar = $window_frame -> Label(-relief => 'groove')
->pack(-side => 'bottom', -fill => 'x');
my $direction = 'Left';
foreach ('Left', 'Right', 'Up', 'Down') {
my $direction_button = $window_frame->
Radiobutton(-text => $_, -variable => \$direction, -value => $_)
->pack(-side => 'left', -anchor => 'center', -padx => '15');
my $balloon = $window->Balloon(-statusbar => $status_bar);
$balloon->attach($direction_button, -balloonmsg => "Go $_",
-statusmsg => "Press the Button to go $_");
}
MainLoop();
There is a custom message for each button.
The answer posted by user toolic gave me an idea on how to get to what I want. I created hash variable that contains my custom messages. By passing in the key, I was able to have a unique message for each button. Here's what it looks like:
use warnings;
use strict;
use Tk;
use Tk::Balloon;
my $window = new MainWindow;
$window->title("Direction");
my $window_frame = $window -> Frame();
$window_frame -> pack(-anchor => 'w', -fill => 'both');
my $status_bar = $window_frame -> Label(-relief => 'groove')
->pack(-side => 'bottom', -fill => 'x');
my %message = ('Left', 'Go West!', 'Right', 'Go East!', 'Up', 'Go North', 'Down', 'Go South');
my $direction = 'Left';
foreach ('Left', 'Right', 'Up', 'Down') {
my $direction_button = $window_frame->
Radiobutton(-text => $_, -variable => \$direction, -value => $_)
->pack(-side => 'left', -anchor => 'center', -padx => '15');
my $balloon = $window->Balloon(-statusbar => $status_bar);
$balloon->attach($direction_button, -balloonmsg => "$message{$_}",
-statusmsg => "Press the Button to $message{$_}");
}
MainLoop();
Related
I am creating a few Tk frames from an array. Each frame has a label and a status. The status is represented by the background option and the $color argument.
I have made the following example
#!/usr/bin/perl
use strict;
use warnings;
use Tk;
my $mw = MainWindow->new(-title => 'test');
my $main_frame = $mw->Frame()->pack(-side => 'top', -fill => 'x');
my #array = ('M024','M016','M032','M066','M065','M044','M096','M099');
foreach my $example ( #array ) {
Frame_creation($example, 'green');
};
MainLoop;
sub Frame_creation{
my ($name, $color) = #_;
my $exempleFrame = $main_frame->Frame()->pack(-side => 'left', -fill => 'x');
my $exempleLabel = $exempleFrame->Label(-text => $name, -background => $color)->pack(-side => 'left', -fill => 'x');
}
Once the frame is created, how do I target the frame in the future if I desire to modify it with a configure?
The handle $exempleFrame allows you to access the frame for modifying it via configure. You simply need to copy it somewhere so that you don't lose it when the subroutine exits
In your case you could have the subroutine return the frame handle
sub frame_creation{
my ($name, $color) = #_;
my $exempleFrame = $main_frame->Frame()->pack(-side => 'left', -fill => 'x');
my $exempleLabel = $exempleFrame->Label(-text => $name, -background => $color)->pack(-side => 'left', -fill => 'x');
return $exempleFrame;
}
and it could be pushed onto an array when you make the call
my #frames;
for my $name ( #names ) {
push #frames, frame_creation($name, 'green');
}
You can then make calls like
$frames[4]->configure(-background => 'red')
to set the attributes of individual frames
This may be better done differently depending on how you need to access the frames (for instance, a hash relating the frame names to their handles may be useful) but this method will give you a simple collection of frame handles, which may be sufficient
Note
As you have written your code, each label completely fills and obscures its frame parent, so setting the background colour of the frame will have no visible effect
Here's a complete program that retains your red label background, but adds (external) ten-pixel padding around the label so that its containing frame can be seen
#!/usr/bin/perl
use strict;
use warnings;
use Tk;
my $mw = MainWindow->new(-title => 'test');
my #names = qw/ M024 M016 M032 M066 M065 M044 M096 M099 /;
my #frames;
my $main_frame = $mw->Frame()->pack(-side => 'top', -fill => 'x');
push #frames, frame_creation($_, 'green') for #names;
$_->configure(-bg => 'red') for #frames;
MainLoop();
sub frame_creation{
my ($name, $color) = #_;
my $frame = $main_frame->Frame()->pack(
-side => 'left',
-fill => 'x',
);
my $label = $frame->Label(
-text => $name,
-bg => $color,
)->pack(
-side => 'left',
-fill => 'x',
-padx => 10,
-pady => 10,
);
$frame;
}
output
I use the Curses::UI::Grid to display the tabular data. The window consists of a table and a few buttons to navigate the data display window to other windows as illustrated below:
However, when the data is displayed, the focus goes to the first row and if I use the tab to shift the focus to next UI control, it never goes to the buttons at the bottom. It just cycle thru the cells of the first row.
Here is the code to reproduce the problem:
#!/usr/bin/env perl
use strict;
use warnings;
use Curses::UI;
use Curses::UI::Grid;
my $debug = 0;
# Create the root object.
my $cui = new Curses::UI (
-color_support => 1,
-clear_on_exit => 1,
-debug => $debug,
);
create_promote_deps_window();
$cui->set_binding( \&exit_dialog , "\cQ");
$cui->mainloop();
sub exit_dialog {
my $return = $cui->dialog(
-message => "Do you really want to quit?",
-title => "Confirm",
-buttons => ['yes', 'no'],
);
exit(0) if $return;
}
sub create_base_window {
my ($name) = #_;
$cui->add(
$name,
'Window',
-border => 1,
-titlereverse => 0,
-padtop => 2,
-padbottom => 3,
-ipad => 1,
-title => 'CTRL-Q to quiz',
);
}
sub create_promote_deps_window {
my ($name) = #_;
my $win = create_base_window($name);
my $grid = $win->add(
'grid',
'Grid',
-height => 14,
-width => -1,
-editable => 0,
-border => 1,
-process_bindings => {
CUI_TAB => undef,
},
# -bg => "blue",
# -fg => "white",
);
$grid->add_cell(
"otp",
-width => 10,
-label => "OTP"
);
$grid->add_cell(
"commit1",
-width => 10,
-label => "Commit#"
);
$grid->add_cell(
"otnp",
-width => 10,
-label => "OTNP"
);
$grid->add_cell(
"commit2",
-width => 10,
-label => "Commit#"
);
$grid->add_cell(
"overlap",
-width => 32,
-label => "Overlap"
);
my $button_callback = sub {
my $this = shift;
my $btn_name = $this->get();
if ($btn_name eq "Back") {
# give up promotion and return to promote window
$win->focus();
}
elsif ($btn_name eq "PromoteWithDeps") {
}
};
$win->add(
undef,
'Buttonbox',
-y => -1,
-buttons => [
{
-label => "< Back >",
-value => "Back",
-onpress => $button_callback,
},
{
-label => "< Promote w/ all deps >",
-value => "PromoteWithDeps",
-onpress => $button_callback,
},
],
);
my #data = (
['HDT-10', 'e3042b0', 'HDT-7', '6741e47', 'src/tc/b.p'],
['HDT-10', 'e3042b0', 'HDT-7', '6741e47', 'src/tc/a.p'],
['HDT-10', 'e3042b0', 'HDT-7', '6741e47', 'src/tc/c.p'],
['HDT-10', 'e3042b0', 'HDT-7', '66a3254', 'src/tc/c.p'],
['HDT-10', 'e3042b0', 'HDT-7', '66a3254', 'src/tc/b.p'],
['HDT-10', 'e3042b0', 'HDT-7', '66a3254', 'src/tc/a.p'],
['HDT-10', 'e3042b0', 'HDT-8', '8b65677', 'src/tc/e.p'],
['HDT-10', 'e3042b0', 'HDT-8', '8b65677', 'src/tc/d.p'],
['HDT-10', 'e3042b0', 'HDT-9', '3eefa90', 'src/tc/f.p'],
);
foreach my $f (#data) {
$grid->add_row(
undef,
# -fg => 'black',
# -bg => 'yellow',
-cells => {
otp => $f->[0],
commit1 => $f->[1],
otnp => $f->[2],
commit2 => $f->[3],
overlap => $f->[4],
}
);
}
$grid->layout();
return $win;
}
How can I customize the tab order so that user can shift the focus the buttons below the Curses::UI::Grid?
Thanks!
The difficulty you're encountering with tabbing out of the grid lies not with the window's tab ordering but in the fact that the Curses::UI::Grid provides its own bindings for Tab and Shift+Tab. A basic solution is to provide your own handler for when Tab and Shift+Tab are pressed when the grid has focus:
sub move_focus {
my $widget = $_[0];
my $key = $_[1];
if ($key eq "\t") {
$widget->parent()->focus_next();
}
else {
$widget->parent()->focus_prev();
}
}
You can then bind this handler to your grid:
$grid->set_binding(\&move_focus, "\t");
$grid->set_binding(\&move_focus, KEY_BTAB());
However, you might find using the cursor keys to move between cells is tedious, so perhaps you still want to be able to tab between cells and only jump to the buttons when the cursor is at the end of the row. In that case, your custom handler will need to be a little more intelligent:
sub move_focus {
my $grid = $_[0];
my $key = $_[1];
if ($key eq "\t") {
my $last_cell = $grid->get_cell($grid->{_cells}[$#{$grid->{_cells}}]);
if ($grid->get_foused_cell() == $last_cell) {
$grid->parent()->focus_next();
}
else {
$grid->next_cell();
}
}
else {
my $first_cell = $grid->get_cell($grid->{_cells}[0]);
if ($grid->get_foused_cell() == $first_cell) {
$grid->parent()->focus_prev();
}
else {
$grid->prev_cell();
}
}
}
I want to make a GUI application using Perl Tk module with a Menubar frame at the top, two frames at left and right for i/o and in the input frame, I want to have some options displyed at bottom aligned in row.
I wish to have multiple buttons/checkboxes at the bottom of a frame aligned in a row. I have tried options like -anchor=>'n', but none seem to work.
My current code puts "Click Here" on top of "Done" whereas I want them to be in a row. How should it be done(using pack geometry manager)?
#!/usr/bin/perl
use strict;
use warnings;
use Tk;
my $mw = MainWindow->new;
$mw->geometry("1000x500");
$mw->title("Text Formatter");
#-----------------Frames-----------------------#
my $main_frame = $mw->Frame()->pack( -side => 'top', - fill => 'x' );
my $top_frame =
$mw->Frame( -background => 'purple' )->pack( -side => 'top', -fill => 'x' );
my $left_frame =
$mw->Frame( -background => 'white' )->pack( -side => 'left', -fill => 'y' );
my $right_frame =
$mw->Frame( -background => 'white' )->pack( -side => 'right', -fill => 'y' );
#----------------Widgets-------------------------#
$top_frame->Label(
-text => "Simple Text Formatter",
-background => 'cyan'
) ->pack( -side => 'top' );
$left_frame->Label(
-text => "Enter the text here that you wish to format",
-background => 'yellow'
)->pack( -side => 'top', -fill => 'both' );
$right_frame->Label(
-text => "Formatted Text",
-background => 'yellow'
)->pack( -side => 'top', -fill => 'both' );
my $left_text;
my $exitButton=
$left_frame->Button(
-text => "Done",
-command => sub { exit }
)->pack( -side => 'bottom',-fill=>'both',-expand=>1);
my $executeButton =
$left_frame->Button(
-text => "Click here",
-command => sub { Echo($left_text); }
)->pack( -side => 'bottom',-fill=>'both',-expand=>1);
$left_text =
$left_frame->Text(
-height => 29.4,
-width => 71
)->pack( -side => 'left', -fill => 'both',-expand=>1 );
my $right_output = $right_frame->Text(
-background => 'black',
foreground => 'white',
-height => 40,
-width => 71
)->pack( -side => 'left',-fill=>'both',-expand=>1 );
MainLoop;
sub Echo {
my ($widget) = #_;
my $text = $widget->Contents();
$right_output -> delete('1.0','end');
my ($size,$maxlength,$lines)=(0,0,0);
my #data=split /\n/,$text;
foreach my $line(#data)
{
$lines++;
$size+=length($line);
$line=~s/\r|\n//g;
my $len=length($line);
$maxlength = $maxlength >= $len ? $maxlength:$len;
$right_output->insert('end',"->$line<-\n")
}
$right_output->insert("end","\n$lines lines,longest line has $maxlength characters,$size bytes total.")
}
I'd spend another frame (-side => 'bottom') and pack the buttons (-side => 'left') into it:
my $left_text;
my $buttons =
$left_frame->Frame()->pack(-side => 'bottom', -fill=>'both', -expand=>1);
my $exitButton=
$buttons->Button(
-text => "Done",
-command => sub { exit }
)->pack(-side => "left", -fill => "both", -expand => 1);
my $executeButton =
$buttons->Button(
-text => "Click here",
-command => sub { Echo($left_text); }
)->pack(-side => "left", -fill => "both", -expand => 1);
How it looks like:
All,
I have a win32 perl TK app i am working on, and to make this simple for the user, I would like drag N drop functionality for folders from windows explorer/desktop onto a widget (eg. textbox etc) in my app.
The reason is to eliminate manual directory/file select dialogs etc.
Some example code would be appreciated. Thanks in advance.
Jeremy.
There is the module Tk::DropSite which should work for you.
An example code can be found here: http://www.nntp.perl.org/group/perl.tcltk/2010/02/msg375.html
This is a working example code:
#!perl
use strict;
use Tk;
use Tk::DropSite;
use Tk::Pane;
my $textVariable = "drag here";
my $mw = MainWindow->new;
my $frame = $mw->Frame(
)->pack(-side => 'top', -expand => 1, -fill => 'x');
$frame->Label(
-text => "My Label",
-anchor => 'w',
-width => 10,
)->pack(-ipady => 1, -side => 'left');
my $entry = $frame->Entry(
-textvariable => \$textVariable,
-width => 40,
)->pack(-side => 'left');
$frame->DropSite(
-dropcommand => [\&AcceptDrop, $frame],
-droptypes => ('Win32'),
);
$mw->MainLoop;
sub AcceptDrop {
my ($widget, $selection) = #_;
my $filename;
$filename = $widget->SelectionGet(
-selection => $selection,
'STRING'
);
$textVariable = $filename;
} # /AcceptDrop
If you know German, have a look here: http://www.perltk.de/tk_widgets/howto_perl_tk_tkx_comparison.html
i know this is not a new question..but i try follow the solution working out from other post...but there are nothing to print out on my text area...if i directly print a sentence on my text file..it's work..why?
#!/usr/local/bin/perl
use Tk;
use File::Tail;
#Main Window
my $mw = new MainWindow;
$mw-> title ("Packet Analyzer Tool");
my $frm_1 = $mw -> Frame() -> pack();
my $frm_2 = $mw -> Frame() -> pack();
my $frm_3 = $mw -> Frame() -> pack();
my $frm_4 = $frm_3 -> Frame(-relief => 'groove', -borderwidth =>2) -> pack(-side => "left");
my $frm_5 = $frm_3 -> Frame() -> pack(-side => "right",-after => $frm_4);
my $but1 = $frm_1 -> Button(-text => "Start",
-command =>\&push_start)
-> pack(-side => "left", -anchor => 'nw', -ipadx => 30, -ipady => 35);
my $but2 = $frm_1 -> Button(-text => "Stop",
-command =>\&push_stop)
-> pack(-side => "left",-after =>$but1, -expand => 1,-ipadx => 30, -ipady => 35);
my $but3 = $frm_1 -> Button(-text => "Pause",
-command =>\&push_pause)
-> pack(-side => "left",-after => $but2 ,-ipadx => 30, -ipady => 35);
my $but4 = $frm_1 -> Button(-text => "Exit",
-command =>\&push_exit)
-> pack(-side => "left", -after => $but3 ,-ipadx => 30, -ipady => 35);
my $filter = $frm_2 ->Entry(-width => 65) -> pack(-side =>"left",-anchor => 's');
my $but5 = $frm_2 -> Button(-text => "Search", -command =>\&push_search)
->pack(-side => "left", -after => $filter, -ipadx => 10);
my $txt1 = $frm_4 -> Text(-width => 60, -height =>20)
-> pack(-side =>"left",-anchor => 's');
my $srl = $frm_4 -> Scrollbar(-orient=>'v', -command =>[yview => $txt]);
$txt1 -> configure(-yscrollcommand =>['set',$srl]);
$txt1 -> grid(-row=>1, -column=>1);
$srl -> grid(-row=>1, -column=>2,-sticky=>"ns");
my $txt2 = $frm_5 -> Text(-width => 15, -height =>20)
-> pack(-side=>"right", -anchor => 'e');
MainLoop;
#Executed START BUTTON
sub push_start
{
open my $fh,'<','/home/terrance/Desktop/perl/record.txt' || die $!;
my #contents = <$fh>;
foreach my $line (#contents)
{
$txt1 ->insert("end", $line);
}
#$txt1 -> insert ('end', "hello due\n");
}
Use perltidy on your code and add
use strict;
use warnings;
Then you'll catch
the $txt => $txt1 typo in my $srl = $frm_4->Scrollbar( -orient => 'v', -command => [ yview => $txt ] );
the missing my #contents = <$fh>;
the foreach my $line (#contetns) typo
On second thought: are you sure, the file exists and is accessible?