使用Perl 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;
}
因此,用户单击其中一个按钮,窗口关闭,prompt_user()返回0或1(取决于用户单击的按钮),并继续执行。直到我尝试再次提示用户。然后我收到一个错误:
can't invoke "wm" command: application has been destroyed at MyFile.pm line 40
我只是想要一种方法来设置一堆按钮,让用户点击一个按钮,等待查看哪一个按钮,以后可能再做一次。有没有办法可以在不破坏主窗口的情况下等待按钮点击响应?也许创建一个子窗口?
我是新手使用Tkx,谷歌搜索显示了许多简单的例子,如上面的代码(使用MainLoop / g_destroy),但我找不到任何重新创建窗口的例子。我确实看到了关于对话框或消息框的内容,但那些不符合我的需求。我想在按钮上放置文本,并使用任意数量的按钮(所以我不想限制为是/否/取消,只有3个选项)。
更新 这是我能够使用的
# 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 :(得分:2)
我对Tkx并不熟悉,但Tk并不是那么好用。通常,Tk应用程序是异步的。你应该在回调方面重写你的应用程序(有点像javascript)。
基本上,这种逻辑:
sub do_something {
perform_some_action();
my $result = prompt_user();
perform_some_other_action($result);
}
应该重写为:
sub do_something {
perform_some_action();
prompt_user(perform_some_other_action);
}
你的程序基本上没有主循环。相反,在程序结束时对Tkx::MainLoop
的调用将成为主循环,您应该通过处理事件来完成所有处理。
话虽如此,有一些可用的模仿阻塞的机制。阅读vwait
的文档。虽然,我认为即使这需要一个正在运行Tkx::MainLoop
,所以它不一定避免重构你的整个程序。
关于如何创建和销毁窗口的问题,有两种解决方案:
使用主窗口(.
)但不要在最后销毁它。而是隐藏它并摧毁它的所有孩子。然后,您可以通过取消隐藏它来重复使用.
。
隐藏.
,不要使用它。而是创建其他窗口(toplevels)并使用它们。由于toplevels是.
的孩子,他们可以安全地摧毁而不会搞砸Tk。