0

テキスト検証が正しく機能しないという問題があります。基本的に、2 つのエントリ ボックスがあります。1 つは CVS のブランチの名前を入力するボックスで、もう 1 つはディレクトリ名を入力するボックスです。各ボックス内のテキストが変更されるたびに、そのテキストをプログラムで検証する必要があります。

GUI

これを行うには、オンラインのドキュメントでは、キーストロークによって入力ボックスの内容が変更されるたびに、「キー」オプションを使用して入力を検証するように指示されています。問題は、「キー」オプションを使用してプログラムを実行すると、入力ボックスに入力してもテキストが表示されないことです。

私のコードを以下に示します。

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

「キー」を別のもの (フォーカスアウトなど) に変更すると、正しく動作するように見えます。しかし、入力ボックスからフォーカスが外れたときだけでなく、キーストロークごとに検証することを本当に望んでいます。なぜこれが機能しないのですか?

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 に答える