2014-12-30 3 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? есть ли способ заставить каркас печатать на STDOUT или STDERR?


EDIT:

Майкл Карман приносит хорошую точку, как правило, с графическим интерфейсом консоль будет подавлено, и пользователь никогда не увидит сообщение об ошибке отправлено в STDOUT или STDERR, но то, что о поиске способ изменить текст в диалоговом окне «Ошибка приложения», чтобы сказать что-то полезное? Это возможно?

Текст не обязательно должен быть полезен конечному пользователю, но должен быть по крайней мере понятен программисту, чтобы они знали, где искать проблему, когда она сообщается конечным пользователем.


EDIT2:

Хорошо оказывается, что с помощью die или confess вместо croak печатает сообщение более полезной ошибке в окне «Ошибка приложения», но когда я нажимаю «ОК» программа просто продолжается и фактически не умирает. Как я могу «убить его до тех пор, пока он не погибнет» и не оставит его мертвым?


ВОЗМОЖНОЕ РЕШЕНИЕ:

Вот возможное решение построено прочь ответ Майкл Карман в. Я изменил его немного, потому что я думаю, что 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 обычно используется при написании модулей, чтобы вы могли сообщить о проблемах в том, как используется ваш код. (например, для проверки аргументов). Программирование графического интерфейса является своего рода зеркальным отображением этого. Вместо того, чтобы писать библиотеку для кого-то другого, вы вводите свой код в библиотеку, написанную кем-то другим. Когда вы передаете ссылку на код -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. 

Если вам нужен полный контроль над тем, как Tk обрабатывает ошибки вы можете переопределить обработчик по умолчанию. Уловка заключается в том, что вы должны сделать это в Tcl. Вот минимальная версия, чтобы создать диалог с сообщением об ошибке и выйти из приложения, когда оно закрыто.

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

'die' делает такие же сообщения. Я не получаю никакой полезной информации о том, где она умерла. Как насчет способа изменить диалог «Ошибка приложения», чтобы он действовал как «die» или «croak» и информирует вас о том, где в вашем коде это произошло? – tjwrona1992

+0

В диалоговом окне отображается содержимое сообщения об ошибке. Кроме того, нет никакого способа повлиять на его поведение. Если вы используете 'die' вместо' croak' (и не заканчиваете свое сообщение новой строкой), он должен содержать номер файла и строки из * вашего * кода, а не «.../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; 
} 
Смежные вопросы