2010-12-07 9 views
1

En utilisant Perl Tkx, je veux obtenir des informations de l'utilisateur, fermer la fenêtre et peut-être le faire plus tard. Pour l'entrée de l'utilisateur, je montre juste quelques boutons, et l'utilisateur peut cliquer sur l'un d'entre eux. Voici ce que j'ai maintenant:Comment puis-je inviter l'utilisateur à plusieurs reprises avec Tkx?

sub prompt_user { 
    my $answer; 
    my $mw = Tkx::widget->new("."); ## the main window is unavailable the second time 
    $mw->g_wm_title("Window Title"); ## line 40 
    $mw->g_wm_minsize(300, 200); 

    my $label = $mw->new_label(-text => "Question to the user?"); 
    $label->g_pack(-padx => 10, -pady => 10); 

    my $button1 = $mw->new_button(
      -text => "Option One", 
      -command => sub { $answer = 0; $mw->g_destroy; }, 
     ); 
    $button1->g_pack(-padx => 10, -pady => 10); 
    my $button2 = $mw->new_button(
      -text => "Option Two", 
      -command => sub { $answer = 1; $mw->g_destroy; }, 
     ); 
    $button2->g_pack(-padx => 10, -pady => 10); 
    Tkx::MainLoop();  ## This blocks until the main window is killed 

    return $answer; 
} 

Ainsi l'utilisateur clique sur l'un des boutons, la fenêtre se ferme, prompt_user() renvoie 0 ou 1 (en fonction du bouton l'utilisateur a cliqué) et l'exécution se poursuit. Jusqu'à ce que j'essaie d'inviter à nouveau l'utilisateur. Puis-je obtenir une erreur:

can't invoke "wm" command: application has been destroyed at MyFile.pm line 40 

Je veux juste une façon de mettre en place un tas de boutons, laissez l'utilisateur clique, attendez de voir que l'on est cliqué, et peut-être le faire plus tard. Y at-il un moyen que je peux attendre une réponse au bouton clic sans détruire la fenêtre principale? Peut-être créer une sous-fenêtre? Je n'utilise pas Tkx depuis longtemps, et googling montre beaucoup d'exemples simples comme le code ci-dessus (en utilisant MainLoop/g_destroy), mais je n'ai trouvé aucun exemple de recréation de fenêtres. J'ai vu des choses sur une boîte de dialogue ou une boîte de message, mais celles-ci ne me conviennent pas. Je veux mettre du texte sur les boutons, et utiliser un nombre arbitraire de boutons (donc je ne veux pas être limité à oui/non/annuler, et seulement 3 options).

Mise à jour Voici ce que j'ai pu utiliser

# hide the main window, since I'm not using it 
my $mw = Tkx::widget->new("."); 
$mw->g_wm_withdraw(); 

# function to prompt the user to answer a question 
# displays an arbitrary number of answers, each on its own button 
sub prompt { 
    my $prompt = shift; 
    my $list_of_answers = shift; 

    # Note: the window name doesn't matter, as long as it's './something' 
    my $answer = Tkx::tk___dialog("./mywindowpath", # window name 
     "Prompt",   # window title 
     $prompt,    # text to display 
     undef,    # tk bmp library icon 
     undef,    # default button 
     @$list_of_answers); # list of strings to use as buttons 

    return $answer; 
} 

# use the button to ask a question 
my $index = prompt("Who was the best captain?", 
        [ "Kirk", "Picard", "Cisco", "Janeway", "Archer" ]); 
+0

Ajout de l'étiquette tk pour obtenir une meilleure réponse. – slebetman

+1

Essayez-vous d'écrire un programme de ligne de commande (c'est-à-dire sans interface graphique) qui affiche parfois des éléments de l'interface graphique?C'est possible, mais maladroit. –

+0

@Michael - oui, c'est exactement ce que j'essaie de faire. Oui, cela semble difficile à faire. – Tim

Répondre

2

Je ne suis pas vraiment familier avec TKX mais Tk ne fonctionne pas vraiment bien de cette façon. En général, les applications Tk sont asynchrones. Vous devriez réécrire votre application en terme de callbacks (un peu comme javascript).

En fait, ce genre de logique:

sub do_something { 

    perform_some_action(); 

    my $result = prompt_user(); 

    perform_some_other_action($result); 
} 

doit être réécrite à quelque chose comme:

sub do_something { 

    perform_some_action(); 

    prompt_user(perform_some_other_action); 
} 

Votre programme devrait en principe pas une boucle principale. Au lieu de cela l'appel à Tkx::MainLoop à la fin de votre programme devient la boucle principale et vous devriez faire tout le traitement en manipulant des événements. Cela dit, il existe certains mécanismes qui émulent le blocage. Lire la documentation pour vwait. Bien que, je pense que même cela nécessite un fonctionnement Tkx::MainLoop afin qu'il n'évite pas nécessairement de refactoriser l'ensemble de votre programme.

Sur la question de la façon de créer et de détruire les fenêtres, il y a deux solutions:

  1. Utilisez la fenêtre principale (.) mais ne détruit pas à la fin. Au lieu de le cacher et de détruire tous ses enfants. Vous pouvez ensuite réutiliser . en l'affichant.

  2. Masquer . et ne pas l'utiliser. Au lieu de cela, créez d'autres fenêtres (toplevels) et utilisez-les. Depuis toplevels sont des enfants de . ils sont sûrs de détruire sans tordre Tk.

+0

J'aime l'option 2, mais comment créer d'autres fenêtres et masquer '.'? Je n'ai pas été en mesure de trouver les appels de fonction réels nécessaires pour ce faire. – Tim

+1

J'ai regardé les documents Tkx et je les ai trouvés très, très courts. Toutes les informations sont là mais il suppose que vous avez une connaissance préalable de Tcl et/ou Tk. De la documentation, il semble que vous pouvez créer une fenêtre en faisant 'my $ window = $ mw-> new_toplevel'. Pour savoir quels widgets vous pouvez créer, vous devez lire le manuel de Tk: http://www.tcl.tk/man/tcl8.5/TkCmd/contents.htm – slebetman

+1

OK, après avoir lu les documents plus loin, la fenêtre principale est masquée : '$ mw-> g_wm_withdraw()'. Tkx ne semble pas trop mauvais pour une enveloppe fine autour de tcl/tk. La plupart du contenu est géré par AUTOLOAD et transmis directement à l'interpréteur tcl, ce qui est un bon moyen général de prendre en charge tout ce que Tk peut faire (même les futures versions de Tk). La seule chose est que je crois que la documentation devrait être améliorée afin que ceux qui ne sont pas familiers avec tcl peuvent l'utiliser. Mais Tk lui-même est bien documenté donc ce n'est pas trop mal. – slebetman

Questions connexes