从to :: menu小部件中删除子小部件/条目

时间:2011-05-31 18:23:10

标签: perl tk

我想为我的Perl / Tk程序实现历史记录/最近文件功能。

以下是我的程序的工作代码摘录,用于演示我的问题。

#!/usr/bin/perl 

use strict;
use warnings;
use English qw( -no_match_vars );

use Tk;

my @history_entries = qw(Back To The History);

my $mw      = MainWindow->new();
my $menubar = $mw->Menu();
$mw->configure( -menu => $menubar );
my $file    = $menubar->cascade( -label => '~File' );
my $history = $file->cascade( -label => '~History', );

build_history();

MainLoop();

#===  FUNCTION  ================================================================
#         NAME:  build_history
#      PURPOSE:  Polulate the history
#===============================================================================
sub build_history {
    foreach (@history_entries) {
        $history->command(
            -label    => $ARG,
            -command  => \&some_function,
            -compound => 'left',
        );
    }
    return;
}    # ----------  end of subroutine build_history  ----------

如您所见,条目是使用$history->command创建的,但每次调用build_history时如何删除它们?

我希望删除它们的原因是每次用户打开文件时,应删除最后一项(在本例中为“历史记录”),并将新项目放在列表顶部。所以我最多有(在这个例子中)四个条目。

欢迎使用Tk实现此功能的任何其他方式。

感谢您的时间。

更新: 我遵循了“mu”的建议,并尝试在调用函数之后使用children()函数获取子部件,如下所示:

my @child = $history->children();
foreach my $c ( @child ) {
    if ($c->Exists()){
        $c->destroy;
    }
}

程序退出时出现错误:

Can't locate object method "children" via package "Tk::Menu::Cascade" at /home/alex/Desktop/stack_history.pl line 28.

2 个答案:

答案 0 :(得分:2)

您可以先从菜单栏创建一个子菜单:

my $sub_menu = $menubar->Menu(-tearoff => 0);

然后你可以将这个子菜单传递给级联menuitem:

$file->cascade( -label => '~History', -menu => $sub_menu);

然后您可以在子菜单中添加/删除菜单项:

foreach (@history_entries) {
    $sub_menu->command(
        -label    => $ARG,
        -compound => 'left',
    );
}
...
$sub_menu->delete(0);     # Remove first element

使用此解决方案,您可以避免重新整理整个菜单。

答案 1 :(得分:0)

我最终重建了整个菜单。这就是我的代码看起来像atm的方式。我并不为此感到骄傲,但它有效...我愿意接受任何形式的建议。

#!/usr/bin/perl 

use strict;
use warnings;
use English qw( -no_match_vars );

use Tk;

# History entries are stored in array
my @history_entries = qw(Back To The History);

my $mw = MainWindow->new();
$mw->geometry('200x200');

my $menubar = $mw->Menu();

#Build menus
$mw->configure( -menu => $menubar );
build_menu();

$mw->Button(
    -text    => 'Update History',
    -command => \sub {

        #when a user opens a file insert_history is called.
        insert_history();
    }
)->pack( -side => 'bottom', -anchor => 'sw' );

MainLoop();

#===  FUNCTION  ================================================================
#         NAME:  build_menu
#      PURPOSE:  Update/Build the menu
#===============================================================================
sub build_menu {

    #delete the whole menu
    $menubar->delete(1);

    #built it again
    my $file = $menubar->cascade( -label => '~File' );
    my $history = $file->cascade( -label => '~History', );
    foreach (@history_entries) {
        $history->command(
            -label    => $ARG,
            -compound => 'left',
        );
    }

    return;
}    # ----------  end of subroutine build_menu  ----------

#===  FUNCTION  ================================================================
#         NAME:  insert_history
#      PURPOSE:  Do something with the array containing the history entries.
#                Then rebuild the menu.
#===============================================================================
sub insert_history {

    #make something with the array
    my $last_element = pop @history_entries;
    unshift @history_entries, $last_element;

    #update menu
    build_menu();
    return;
}    # ----------  end of subroutine insert_history  ----------