0

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

图形用户界面

为此,在线文档说,只要击键更改了输入框的内容,就使用“key”选项来验证输入。问题是,当我使用“key”选项然后运行程序时,当我在输入框中键入时,没有出现任何文本。

我的代码如下所示:

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();

如果我将“key”更改为其他内容(如 focusout),它似乎可以正常工作。但我真的希望它在每次击键后进行验证,而不是仅在焦点从输入框中取出时进行验证。为什么这不起作用?

4

2 回答 2

2

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

于 2014-12-22T14:55:22.523 回答
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;
}
于 2015-01-06T13:55:52.757 回答