2014-12-30 55 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; 
}