Как я могу неоднократно предлагать пользователю использовать Tkx? - PullRequest
1 голос
/ 07 декабря 2010

Используя 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, и поиск в Google показывает множество простых примеров, таких как приведенный выше код (с использованием 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" ] );

1 Ответ

2 голосов
/ 07 декабря 2010

Я не очень знаком с 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, поэтому не обязательно избегать рефакторинга всей вашей программы.

На вопрос о том, как создавать и уничтожать окна, существует два решения:

  1. Используйте главное окно (.), но не уничтожайте его в конце. Вместо этого спрячь его и уничтожь всех его детей. Затем вы можете позже использовать ., скрывая его.

  2. Скрыть . и не использовать его. Вместо этого создайте другие окна (toplevels) и используйте их. Так как верхние уровни - это дети ., их безопасно уничтожить, не испортив Tk.

...