2014-12-30 68 views
2

我正在使用Perl Tkx应用程序,并且遇到有用/正确的错误消息时遇到问题。我试图使用croak,所以它会告诉我确切的位置,但每次它都会说错误位于“C:/Perl64/lib/Tkx.pm 347行”。错误处理使用Perl Tkx

我写了一个非常简单的脚本来证明所发生的事情:


#!/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(); 

当我运行此脚本,然后单击该按钮出现以下弹出框:

croak popup

我该如何让Tkx处理类似于使用croak的错误普通的Perl脚本?有没有办法强制croak打印到STDOUT或STDERR?


编辑:

迈克尔·卡曼带来了一个好点通常具有GUI控制台将被抑制,用户将不会看到发送到标准输出或STDERR一个错误,但如何找到一种修改“应用程序错误”对话框中的文本以说出有用的东西的方法?那可能吗?

对于最终用户而言,文本不一定非常有用,但至少应该被程序员理解,以便他们知道最终用户报告问题的位置。


EDIT2:

好吧,似乎使用dieconfess代替croak打印出更实用的错误消息的“应用程序错误”窗口,但一旦我点击“OK”节目刚继续并且不实际死亡。我怎样才能“杀死它直到它死了”并确保它保持死亡?


可能的解决方案:

这里建过迈克尔·卡曼的回应可能的解决方案。我修改了它稍微因为我觉得一个消息框看起来有点更好:)

#!/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捕获回调中的致命错误,并通过您所看到的“应用程序错误”对话框报告它们。 GUI应用程序与控制台断开连接并不少见,这意味着STDOUT和STDERR已关闭,并且任何写入它们的消息都将丢失。如果没有这个对话框,你的应用程序就会消失,用户不知道为什么。

例如

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. 

如果你需要对传统知识如何处理错误,您可以覆盖默认的处理完全控制。问题在于你必须在Tcl中做到这一点。这是一个最小版本,用于创建一个包含错误消息的对话框,并在应用程序关闭时退出。

Tkx::eval(<<'EOT'); 
proc bgerror {message} { 
    tk_dialog .error "Error" $message [] 0 Close 
    destroy . 
} 
EOT 
+0

'die'做同样的消息。我没有得到任何关于它死亡的有用信息。怎么样改变“应用程序错误”对话框,使它像'die'或'croak'一样工作,并通知你在你的代码中发生了什么? – tjwrona1992

+0

该对话框显示错误消息的内容。除此之外,没有办法影响它的行为。如果你使用'die'而不是'croak'(并且不要用换行符结束你的消息),它应该包含* your *代码中的文件和行号,而不是“.../lib/Tkx.pm”行347 ”。例如对我来说它说'死在c:\ temp \ foo.pl第11行。 –

+0

其实你是对的。嗯,我可以发誓我尝试了。好吧,现在仍然存在程序不会实际“死”的问题窗口保持打开状态,并且可以让您再次单击它。我怎么能“杀死它直到它死了”?一旦我点击错误消息上的“确定”按钮,我希望它死亡并保持死亡。 – tjwrona1992

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 "[email protected]\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 "[email protected]\n"; 
    $text->insert("end", "[email protected]\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 => "[email protected]"); 
    $mw->g_destroy; 
}