2010-12-07 4 views
1

Perl Tkx를 사용하여 사용자로부터 입력을 받고, 창을 닫고, 나중에 다시 할 수 있습니다. 사용자 입력을 위해, 나는 단지 몇 개의 버튼을 표시하고 있고, 사용자는 그 중 하나를 클릭한다. 버튼 중 하나에어떻게 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

더 나은 응답을 얻으려면 tk 태그가 추가되었습니다. – slebetman

+1

가끔 GUI 요소를 팝업하는 명령 줄 프로그램 (예 : GUI 없음)을 작성하려고하십니까?그것은 가능하지만 어색합니다. –

+0

@Michael - 예, 그게 내가하려는 일입니다. 그렇습니다. 어색하게하는 것 같습니다. – Tim

답변

2

내가 TKX 정말 익숙하지 않아요하지만 TK에 정말 잘 그런 식으로 작동하지 않습니다 사용할 수 있었던거야. 일반적으로 Tk 응용 프로그램은 비동기식입니다. 콜백 (자바 스크립트 같은)의 용어로 응용 프로그램을 다시 작성해야합니다.

기본적으로, 논리의 종류 :

sub do_something { 

    perform_some_action(); 

    prompt_user(perform_some_other_action); 
} 

프로그램이 기본적으로 메인 루프가 없어야합니다 :

sub do_something { 

    perform_some_action(); 

    my $result = prompt_user(); 

    perform_some_other_action($result); 
} 

은 같은 것으로 다시 작성해야합니다. 대신 프로그램 끝의 Tkx::MainLoop에 대한 호출이 주 루프가되며 이벤트를 처리하여 모든 처리를 수행해야합니다.

그렇기 때문에 차단을 에뮬레이트하는 몇 가지 메커니즘이 있습니다. vwait에 대한 자료를 읽으십시오. 비록 그것이 심지어 실행을 필요로한다고 생각합니다. Tkx::MainLoop 그래서 전체 프로그램 리팩터링을 반드시 피하는 것은 아닙니다.

  1. 메인 윈도우 (.)를 사용하지만 마지막에 그것을 파괴하지 않습니다 만들고 창을 파괴하는 방법에 대한 질문에

    는 두 가지 솔루션이 있습니다. 대신 그것을 숨기고 모든 아이들을 파괴하십시오. 다시 숨김으로써 .을 나중에 다시 사용할 수 있습니다.

  2. .을 숨기고 사용하지 마십시오. 대신 다른 창 (최상위 레벨)을 만들어 사용하십시오. 최상위가 .의 아이들이기 때문에 Tk를 망쳐 놓지 않고도 파괴 할 수 있습니다.

+0

나는 옵션 2를 좋아하지만 어떻게 다른 창을 만들고 '.'을 숨길 수 있습니까? 이 작업을 수행하는 데 필요한 실제 함수 호출을 찾을 수 없었습니다. – Tim

+1

Tkx 문서를보고 매우 짧음을 알았습니다. 모든 정보가 있지만 Tcl 및/또는 Tk에 대한 사전 지식이 있다고 가정합니다. 문서에서'my $ window = $ mw-> new_toplevel'을 실행하여 창을 만들 수있는 것처럼 보입니다. 어떤 위젯을 만들 수 있는지 알기 위해서는 Tk 매뉴얼을 읽어야합니다. http://www.tcl.tk/man/tcl8.5/TkCmd/contents.htm – slebetman

+1

OK, 문서를 더 읽었을 때, 메인 윈도우를 숨기는 것은 :'$ mw-> g_wm_withdraw()'. Tkx는 tcl/tk를 감싸는 얇은 포장지로보기에는 그리 좋지 않습니다. 대부분의 것들은 AUTOLOAD에 의해 처리되며 TK가 할 수있는 모든 것을 지원하는 훌륭한 일반적인 방법 인 Tcl 인터프리터에 직접 전달됩니다 (Tk의 차후 버전조차도). 유일한 것은 tcl에 친숙하지 않은 사람들이 그것을 사용할 수 있도록 문서를 개선해야한다고 생각합니다. 그러나 Tk 자체는 잘 문서화되어 있으므로 그리 나쁘지 않습니다. – slebetman

관련 문제