我正在处理Perl Tkx应用程序,但我无法获得有用/正确的错误消息。我试图使用呱呱声,因此它会告诉我它确切的失败位置,但每次呱呱叫它只是说错误位于"在C:/Perl64/lib/Tkx.pm第347行。"
我写了一个非常简单的脚本来演示正在发生的事情:
#!/usr/bin/perl
use strict;
use warnings;
use Carp;
use Tkx;
my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
-text => "Hello, world",
-command => sub { croak; },
);
$b->g_pack;
Tkx::MainLoop();
当我运行此脚本并单击按钮时,我会看到以下弹出框:
如何使Tkx处理错误类似于在常规Perl脚本中使用croak?有没有办法强制呱呱打印到STDOUT或STDERR?
修改
迈克尔·卡曼提出了一个很好的观点,即通常使用GUI控制台将被禁止,用户永远不会看到发送到STDOUT或STDERR的错误,但是如何找到一种方法来修改"应用程序错误"对话框说些有用的东西?这可能吗?该文本不一定必须对最终用户有用,但至少应该是程序员可以理解的,这样他们就知道最终用户报告问题的位置。
EDIT2:
好吧,似乎使用die
或confess
代替croak
会向"应用程序错误"打印更有用的错误消息。窗口,但一旦我点击" OK"该计划只是继续,并没有实际死亡。我怎么能杀死它直到它死了#34;并确保它死了?
可能的解决方案:
这是Michael Carman的回应建立的可能解决方案。我稍微修改了一下因为我认为messageBox看起来更好一些:)
#!/usr/bin/perl
use strict;
use warnings;
use Tkx;
use Carp;
my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
-text => "Hello, world",
-command => sub { die "uh-oh"; },
);
$b->g_pack;
Tkx::eval(<<'EOT');
proc bgerror {message} {
tk_messageBox -title "Application Error" -message $message -icon error -type ok
destroy .
}
EOT
Tkx::MainLoop();
到目前为止,这是最好的解决方案,但仍有5天的时间仍然存在,所以请保持这些答案!
答案 0 :(得分:4)
croak
从调用者的角度报告错误。使用die
从代码的角度报告错误。
croak
,以便您可以按照代码的使用方式报告问题。 (例如,用于参数验证)GUI编程是一种镜像。您可以将代码注入由其他人编写的库中,而不是为其他人编写库。当您将代码引用传递给-command
时,调用方变为Tkx,因此从代码的角度报告任何错误会更好。
Tkx在回调中捕获致命错误,并通过&#34;应用程序错误&#34;报告它们。你正在看的对话。 GUI应用程序与控制台断开连接的情况并不少见,这意味着STDOUT和STDERR已关闭,并且写入它们的任何消息都将丢失。没有对话框,您的应用程序就会消失,用户也不会知道原因。
e.g。
use Tkx;
my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
-text => "Hello, world",
-command => sub { die "uh-oh" },
);
$b->g_pack;
Tkx::MainLoop();
当我运行此按钮(并按下按钮)时,对话框消息为
uh-oh at c:\temp\foo.pl line 9.
如果您需要完全控制Tk处理错误的方式,您可以覆盖默认处理程序。问题是你必须在Tcl中完成。这是一个最小版本,用于创建带有错误消息的对话框,并在应用程序关闭时退出。
Tkx::eval(<<'EOT');
proc bgerror {message} {
tk_dialog .error "Error" $message [] 0 Close
destroy .
}
EOT
答案 1 :(得分:0)
以下脚本将错误消息打印到STDOUT:
use strict;
use warnings;
use Carp;
use Tkx;
my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
-text => "Hello, world",
-command => \&error_test,
);
$b->g_pack;
Tkx::MainLoop();
sub error_test {
eval {
confess;
};
print "$@\n";
}
输出:
at ./p.pl line 20.
eval {...} called at ./p.pl line 19
main::error_test() called at /home/hakon/perl5/lib/perl5/Tkx.pm line 347
eval {...} called at /home/hakon/perl5/lib/perl5/Tkx.pm line 347
Tkx::i::DoOneEvent(0) called at /home/hakon/perl5/lib/perl5/Tkx.pm line 56
Tkx::MainLoop() called at ./p.pl line 16
修改强>
以下内容可用于将错误消息打印到Tk GUI的文本字段:
use strict;
use warnings;
use Carp;
use Tkx;
my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
-text => "Hello, world",
-command => \&error_test,
);
$b->g_grid(-column => 0, -row => 0);
my $text = $mw->new_tk__text(-width => 100, -height => 30);
$text->g_grid(-column => 0, -row => 1);
Tkx::MainLoop();
sub error_test {
eval {
confess;
};
print "$@\n";
$text->insert("end", "$@\n");
}
修改强>
要在显示错误消息后销毁窗口,您可以使用:
use strict;
use warnings;
use Carp;
use Tkx;
my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
-text => "Hello, world",
-command => \&error_test,
);
$b->g_pack;
Tkx::MainLoop();
sub error_test {
eval {
confess;
};
Tkx::tk___messageBox(-message => "$@");
$mw->g_destroy;
}