Perl Tkx条目验证无效

时间:2014-12-22 14:02:32

标签: perl validation user-interface user-input tkx

我在使文本验证正常工作时遇到问题。基本上我有2个输入框,一个用于输入CVS中的分支名称,另一个用于输入目录名称。我希望我的程序在每次更改时验证每个框中的文本。

GUI

为此,documentation online表示要使用"键"每当按键改变输入框的内容时验证条目的选项。问题是,当我使用"键"选项然后运行程序,当我在输入框中键入时,不会出现任何文本。

我的代码如下所示:

use strict;
use warnings;
use Tkx;

# Initialize BRANCH and DIRECTORY
my ($BRANCH, $DIRECTORY) = ();

# DEFINE DISPLAY OBJECTS ###########################################################################

# Define main window
my $main_window = Tkx::widget->new('.');

# Define content frame
my $content_frame = $main_window->new_ttk__frame(-padding => '5 5 5 5');

# Define labels
my $branch_label    = $content_frame->new_ttk__label(-text => 'Branch'   );
my $directory_label = $content_frame->new_ttk__label(-text => 'Directory');

# Define entry boxes
my $branch_entry    = $content_frame->new_ttk__entry(-width => 20, -textvariable => \$BRANCH   , -validate => 'key', -validatecommand => \&check_state);
my $directory_entry = $content_frame->new_ttk__entry(-width => 20, -textvariable => \$DIRECTORY, -validate => 'key', -validatecommand => \&check_state);

# Define buttons
my $generate_list_button = $content_frame->new_ttk__button(-text => 'Generate', -state => 'disabled', -command => \&generate_list);

# POSITION DISPLAY OBJECTS #########################################################################

# Position content frame
$content_frame->g_grid(-column => 0, -row => 0);

# Position labels
$branch_label   ->g_grid(-column => 0, -row => 0);
$directory_label->g_grid(-column => 0, -row => 1);

# Position entry boxes
$branch_entry   ->g_grid(-column => 1, -row => 0);
$directory_entry->g_grid(-column => 1, -row => 1);

# Position buttons
$generate_list_button->g_grid(-column => 0, -row => 2, -columnspan => 2);

# Add padding
for my $child (Tkx::SplitList($content_frame->g_winfo_children)) {
    Tkx::grid_configure($child, -padx => 5, -pady => 5);
}

# Check the state of the program
sub check_state {

    # Check conditions are met to enable generate_list
    if ($BRANCH && $DIRECTORY) {
        if (-d $DIRECTORY) {
            $generate_list_button->state('!disabled');
        } else {
            $generate_list_button->state('disabled');
        }
    } else {
        $generate_list_button->state('disabled');
    }

    return 0;
}

Tkx::MainLoop();

如果我改变"键"它可以正常工作(如聚焦)。但我真的希望它能在每次击键后进行验证,而不仅仅是当焦点从输入框中取出时。为什么这不起作用?

2 个答案:

答案 0 :(得分:2)

您的check_state子程序始终返回0,表示“验证失败”并阻止 输入的文字。由于您没有真正验证文本 - 只是使用验证机制来触发相关小部件的状态更新 - 您应该返回1(无条件)。有关详细信息,请参阅(Tcl)Tk文档中的validatecommand

答案 1 :(得分:2)

返回0的子程序只是问题的一半。一旦我修复了条目验证没有正常运作。发生的事情是,每当它试图验证它实际上将验证前一个条目的条目时。

例如:

如果您键入“/ somedirectory”,它会尝试在每次击键时进行验证,在“y”的最后一次击键后,它将获得$DIRECTORY的值并对其进行验证。问题是此时$DIRECTORY将等于“/ somedirector”

要解决这个问题,我不得不做一些挖掘,所以我想发布我的发现,以防其他人遇到同样的问题。


解决方案是使用Tkx::Ev()来获取输入条目时的“当前”值。

(Tkx :: Ev(%P)获取新输入的值,以便验证正常运行)

# Define the entry box
my $directory_entry = $content_frame->new_ttk__entry(
    -width           => 20,
    -textvariable    => \$DIRECTORY,
    -validate        => 'key',
    -validatecommand => [\&check_dir, Tkx::Ev('%P')],
);

# Validate the entry box
sub check_dir {

    # Unpack input arguments
    my ($P) = @_;

    if (-d $P) {
        # Do something here
    } else {
        # Do something else here
    }

    return 1;
}