1

私は perl/tk GUI を書きました。stderr と stdout はポップアップ ウィンドウに書き込みますが、ポップアップ ウィンドウが破棄されたときにテキストをクリアできません (実際には取り消されます)。Tk::Stderr をインストールできなかったので、モジュールをスクリプトの最後に追加しました。以下は実際の例です。

次の行を Print サブルーチンに追加しましたが、やり過ぎです。

$text->delete('0.0', 'end');

私の疑いでは、Populate サブルーチンの次の行に何かが追加される可能性があります。

$mw->protocol(WM_DELETE_WINDOW => [ $mw => 'withdraw']);

しかし、私は何を知りません。ご支援いただければ幸いです。

#!/usr/bin/perl

use warnings;
use strict;
use Tk;
# use Tk::Stderr; << ** pasted module after main ** - honyok

# create main window
my $mw = MainWindow->new;
$mw->InitStderr;
$mw->optionAdd("*font", "-*-calibri-normal-r-*-*-*-120-*-*-*-*-*-*");
$mw->protocol('WM_DELETE_WINDOW'=> sub{exit});
$mw->geometry( "100x100");
$mw->resizable(0,0);# not resizable
# create buttons
my $button1=$mw->Button(-text=>'STDERR',-command=>[sub{print STDERR "Writing to STDERR\n";}])->pack;
my $button2=$mw->Button(-text=>'STDOUT',-command=>[sub{print STDOUT "Writing to STDOUT\n";}])->pack;

MainLoop;
# =========================== end main ==================================


##==============================================================================
## Tk::Stderr - capture program standard error output
##==============================================================================
## $Id: Stderr.pm,v 1.2 2003/04/01 03:58:42 kevin Exp $
##==============================================================================
#require 5.006;
package Tk::Stderr;
use strict;
use warnings;
use vars qw($VERSION @ISA);
($VERSION) = q$Revision: 1.2 $ =~ /Revision:\s+(\S+)/ or $VERSION = "0.0";
use base qw(Tk::Derived Tk::MainWindow);

use Tk::ROText;
use Tk::Frame;

##==============================================================================
## Populate
##==============================================================================
sub Populate {
    my ($mw, $args) = @_;
    my $private = $mw->privateData;
    $private->{ReferenceCount} = 0;
    $private->{Enabled} = 0;

    $mw->SUPER::Populate($args);

    $mw->withdraw;
    $mw->protocol(WM_DELETE_WINDOW => [ $mw => 'withdraw']);
    my $f = $mw->Frame(
        Name => 'stderr_frame',
    )->pack(-fill => 'both', -expand => 1);

    my $text = $f->Scrolled(
        'ROText',
        Name => 'stderr_text',
        -scrollbars => 'se',
        -label=>'Output/Errors',
        -wrap => 'none'
        #-background=>'slate grey'
    )->pack(-fill => 'both', -expand => 1);

    $mw->Advertise('text' => $text);
    $mw->ConfigSpecs(
        '-title' => [ qw/METHOD title Title/, "truGrid" ],
    );

    $mw->Redirect(1);
    return $mw;
}

##==============================================================================
## Redirect
##==============================================================================
sub Redirect {

    my ($mw, $boolean) = @_;
    my $private = $mw->privateData;
    my $old = $private->{Enabled};

    if ($old && !$boolean) {
        untie *STDOUT;# ** hacked this line ** - honyok
        untie *STDERR;
        $SIG{__WARN__} = 'DEFAULT';
    } elsif (!$old && $boolean) {
        tie *STDOUT, 'Tk::Stderr::Handle', $mw;# ** hacked this line ** - honyok
        tie *STDERR, 'Tk::Stderr::Handle', $mw;
        $SIG{__WARN__} = sub { print STDOUT @_ };# ** hacked this line ** - honyok
        $SIG{__WARN__} = sub { print STDERR @_ };
    }
    $private->{Enabled} = $boolean;
    return $old;
}


##==============================================================================
## DecrementReferenceCount
##==============================================================================
sub DecrementReferenceCount {
    my ($mw) = @_;
    my $private = $mw->privateData;

    if (--$private->{ReferenceCount} <= 0) {
        $mw->destroy;
    }
}

##==============================================================================
## IncrementReferenceCount
##==============================================================================
sub IncrementReferenceCount {
    my ($mw) = @_;
    my $private = $mw->privateData;

    ++$private->{ReferenceCount};
}


package MainWindow;
use strict;
use warnings;

my $error_window;

##==============================================================================
## InitStderr
##==============================================================================
sub InitStderr {
    my ($mw, $title) = @_;

    unless (defined $error_window) {
        $error_window = Tk::Stderr->new;
        $error_window->title($title) if defined $title;
    }
    $error_window->IncrementReferenceCount;
    $mw->OnDestroy([ 'DecrementReferenceCount' => $error_window ]);
    return $mw;
}

##==============================================================================
## StderrWindow
##==============================================================================
sub StderrWindow {
    return $error_window;
}

##==============================================================================
## RedirectStderr
##==============================================================================
sub RedirectStderr {
    my ($mw, $boolean) = @_;

    unless (defined $error_window) {
        $mw->InitStderr if $boolean;
        return;
    }
    return $error_window->Redirect($boolean);
}


##==============================================================================
## Define the handle that actually implements things.
##==============================================================================
BEGIN {
    package Tk::Stderr::Handle;
    use strict;
    use warnings;

    ##==========================================================================
    ## TIEHANDLE
    ##==========================================================================
    sub TIEHANDLE {
        my ($class, $window) = @_;
        bless \$window, $class;
    }

    ##==========================================================================
    ## PRINT
    ##==========================================================================
    sub PRINT {
        my $window = shift;
        my $text = $$window->Subwidget('text');
        $text->insert('end', $_) foreach (@_);
        $text->see('end');
        $$window->deiconify;
        $$window->raise;
        $$window->focus;
        $$window->update;# ** hacked this line ** - honyok
    }

    ##==========================================================================
    ## PRINTF
    ##==========================================================================
    sub PRINTF {
        my ($window, $format) = splice @_, 0, 2;

        $window->PRINT(sprintf $format, @_);
    }
}
1;
##==============================================================================
## $Log: Stderr.pm,v $
## Revision 1.2  2003/04/01 03:58:42  kevin
## Add RedirectStderr method to allow redirection to be switched on and off.
##
## Revision 1.1  2003/03/26 21:48:43  kevin
## Fix dependencies in Makefile.PL
##
## Revision 1.0  2003/03/26 19:11:32  kevin
## Initial revision
##==============================================================================
4

2 に答える 2

1

(別のフォーラムで回答されています。)

交換:

$mw->protocol(WM_DELETE_WINDOW => [ $mw => 'withdraw' ]);

と:

$mw->protocol(WM_DELETE_WINDOW => [ $mw => 'OnWithdraw' ]);

サブルーチンを定義します。

sub OnWithdraw{
    my $window = shift;
    my $text   = $window->Subwidget('text');
    $text->delete('0.0', 'end');
    $window->withdraw;
    return;
}
于 2012-09-18T13:56:23.477 に答える
0

私が見る限り、テキスト ウィジェットのコンテンツを残す動作は正しいです。ポップアップを閉じると、ウィジェットは破棄されませんが、そのまま維持され、新しい情報が追加されます。

于 2012-09-17T20:20:18.087 に答える