2013-12-12 2 views
1

모덜리스 대화 상자를 만들려고합니다. 대화 상자가 나타날 때마다 메인 GUI에서 실행중인 실시간 프로세스가 멈추고, 일부 재검색 한 후에 그 문제가 대화 상자에서 "vwait"명령을 사용하면 실시간 부분이 멈추게됩니다. 어떻게 현재 대화 모드를 만들어서 실시간 프로세스에 영향을 미치지 않도록 할 수 있습니까? 내가 proc 호출 할 때마다 다른 스레드에 msgDialog 넣어야합니까? 또는 다른 방법으로 그것을 할 수 있습니까?tcl/tk에 모덜리스 대화 상자를 만드는 방법

TCL 코드 :

proc MsgDialog {w message type icon} \ 
{ 


if {![winfo exists $w]} { 
    set dialColor white 

    image create photo .alert -format PNG -file alertIcon.png -width 40 
    image create photo .question -format PNG -file questionicon.png 

    toplevel $w -borderwidth 2 -relief raised -background $dialColor 
    wm overrideredirect $w 1 
    set x [expr { ([winfo vrootwidth $w] - 350 )/2 }] 
    set y [expr { ([winfo vrootheight $w] - 190)/2 }] 
    wm geometry $w 350x190+${x}+${y} 


    frame $w.msgPnl -relief flat -borderwidth 1 -background $dialColor -width 280 -height 140 
    place $w.msgPnl -x 0 -y 0 

    frame $w.imgPnl -relief flat -borderwidth 1 -background $dialColor -width 50 -height 140 
    place $w.imgPnl -x 285 -y 0 

    frame $w.btnPnl -relief flat -borderwidth 1 -background $dialColor -width 300 -height 50 
    place $w.btnPnl -x 0 -y 130 

    label $w.msgPnl.message -text $message -background $dialColor -justify center -wraplength 270 -font dialogFont 
    pack $w.msgPnl.message -anchor center -pady 20 -padx 10 -expand 1 -fill both 

    if {$type == "ok"} { 

     button $w.btnPnl.okbut -text "OK" -background black -foreground white -relief flat -command {set _res "ok"} -width 8 -height 2 -highlightthickness 2 -font boldFont 
     grid $w.btnPnl.okbut -row 1 -column 1 -padx 125 

    } elseif {$type == "yesno"} { 

     button $w.btnPnl.yes -text "Yes" -background black -foreground white -relief flat -command {set _res "yes"} -width 8 -height 2 -highlightthickness 2 -font boldFont 
     button $w.btnPnl.no -text "No" -background black -foreground white -relief flat -command {set _res "no"} -width 8 -height 2 -highlightthickness 2 -font boldFont 
     grid $w.btnPnl.yes -row 1 -column 1 -padx 50 
     grid $w.btnPnl.no -row 1 -column 2 

    } else { 

     button $w.btnPnl.okbut -text "OK" -background $btnColor -relief flat -command {set _res "ok"} -width 8 -height 2 
     pack $w.btnPnl.okbut -side top -anchor center 
    } 

    if {$icon == "alert"} { 
     label $w.imgPnl.alertI -image .alert -compound top -background $dialColor 
     pack $w.imgPnl.alertI -fill both -expand 1 -pady 20 

    } elseif {$icon == "question"} { 
     label $w.imgPnl.quest -image .question -compound top -background $dialColor 
     pack $w.imgPnl.quest -fill both -expand 1 -pady 20 
    } else { 
     label $w.imgPnl.alertI -image .alert -compound top -background $dialColor 
     pack $w.imgPnl.alertI -fill both -expand 1 -pady 20 
    } 

    raise $w 
    vwait _res 
    destroy $w 
    return $::_res 
} 
} 

나는 이런 식으로 뭔가를 시도했지만, 내가 얻을 때 잘못된 명령 이름 MsgDialog

set tid [thread::create {thread::wait}] 
::thread::send -async $tid {MsgDialog .dialog "Are you ready for measurement ?" yesno question} answer 
vwait answer 

if {$answer == yes} { 
#do something 
} 

답변

1

대화 상자 proc은 값을 반환하기 때문에 근본적으로 모달입니다. 따라서 사용자가 응답 할 때까지 값을 반환 할 수 없으므로 사용자가 응답 할 때까지 차단됩니다.

모덜리스로 만들려면 빌드하여 다시 만들어야합니다. 버튼은 모두 procs (전역 또는 일부 정규화 된 이름)를 호출하여 대기중인 일부 위치에서 사용자 값을 설정 한 다음 대화 상자를 제대로 파괴해야합니다.

이것은 반환 값이 전역이어야하고 창 ID 변수가 전역이어야하며 처리기 proc/procs가 전역이어야하며 어떤 방식 으로든 값을 원하는 모든 처리를 트리거해야 함을 의미합니다 그것은 내가 추측 할 수있는 특정 애플리케이션입니다. 공정한 작업이지만 스레딩 라이브러리를 통합하는 것보다 쉽습니다.

+1

넌 - 모드 상호 작용을 처리하는 좋은 방법은 상호 작용이 끝날 때 실행되도록 콜백을주는'MsgDialog '의 호출자를위한 것입니다. (그러면 실행 스레드를 풀어서 8.6의 코 루틴의 도움을 받아 작동하는 모달을 만들 수 있습니다.) –

+0

감사합니다. 에릭, 무슨 뜻인지 이해할 것 같아요, 창 ID를 어떻게 말하는 겁니까? –

+0

코드에서 $ w는 로컬 변수입니다. $ w에 저장된 값은 윈도우를 파괴하고있는 proc에서 사용할 수 있어야한다. 그리고 콜백을 전달하는 Donal의 제안은 proc의 이름을 하드 코딩하지 않고 버튼 누르기를 호출하는 강력한 방법입니다. –

0

당신이 단순히 vwait을 제거 봤어? 모달 대화 상자와 넌 모달 대화 상자의 차이점은 실제로 vwait를 호출하고 키보드와 마우스를 잡는 모달 대화 상자에 불과합니다.

+0

진정한 모달 대화 상자는 또한 잡기를 설정합니다. –

+0

좋은 지적. 고마워, 도날. 내 대답을 업데이트 할게. –

관련 문제