有什么方法可以从 TCL 本身而不是通过用户单击按钮来提供 tk_messagebox 输入吗?

Is there any way to provide tk_messagebox an input from TCL itself and not by the click of button by user?

我有一个触发 tk_messageBox 的条件。现在,在停留了比方说 10 秒之后,我希望它在没有任何点击或用户交互的情况下以“确定”输入消失。有什么办法可以做到吗?

        if {condition is matched} {
          set input [tk_messageBox -message $message -icon <iconType> -type <messageBoxType>]
         }

标准消息框不支持,因为至少一个平台上的底层 OS 对话框(不记得是 Windows 还是 macOS)不支持支持这种东西。

但是您可以访问对话框的脚本版本(Linux 上的默认版本)并注入触发器:

# Set up the timeout; I got the widget name by reading the sources
set handle [after 10000 .__tk__messagebox.no invoke]

# This is the internal name of the implementation
set answer [tk::MessageBox -type yesno -message "Foo"]

# Make sure we clear our timeout in case the user *did* pick something
after cancel $handle

不同的消息框类型对默认按钮(名称的最后部分)有不同的名称,但它们将是 okcancelno 之一或 abort,具体取决于对话框类型。哪个应该是显而易见的。 (或者,只需销毁 .__tk_messagebox window。我 认为 也选择默认值。)

这是使用顶层的另一种可能的解决方案:

set message "The quick brown fox jumps over the lazy dog"

if {condition is matched} {
    toplevel .new_window

    wm title      .new_window "Window title"
    wm geometry   .new_window 320x100
    wm minsize    .new_window 320 100
    wm maxsize    .new_window 320 100
    wm protocol   .new_window WM_DELETE_WINDOW {destroy .new_window}
    wm attributes .new_window -topmost yes

    set input -1

    pack [label .new_window.message -text $message] -fill none -expand 1
    pack [frame .new_window.buttons] -fill none -expand 1

    pack [ttk::button .new_window.buttons.button1 -text "OK" -command {
        set input 1
        destroy .new_window
    }] -side left -padx 5

    pack [ttk::button .new_window.buttons.button2 -text "Cancel" -command {
        set input 0
        destroy .new_window
    }] -side right -padx 5

    after 10000 {
        if {[winfo exists .new_window]} {
            destroy .new_window
            if {$input == -1} {
                set input 1
            }
        }
    }
}

变量 $input 保存用户输入值(0 或 1),在十秒超时后没有点击 window 将自动关闭默认值为 1(确定)。

但是请注意,在点击之前或直到超时到期之前,变量 $input 的值为 -1

编辑:为了避免后一种不确定的行为,您可能需要这样:

set message "The quick brown fox jumps over the lazy dog"

if {condition is matched} {
    toplevel .new_window

    wm title      .new_window "Window title"
    wm geometry   .new_window 320x100
    wm minsize    .new_window 320 100
    wm maxsize    .new_window 320 100
    wm protocol   .new_window WM_DELETE_WINDOW {
        set input 1
        destroy .new_window
    }
    wm attributes .new_window -topmost yes

    if {[info exists input]} {
        unset input
    }

    pack [label .new_window.message -text $message] -fill none -expand 1
    pack [frame .new_window.buttons] -fill none -expand 1

    pack [ttk::button .new_window.buttons.button1 -text "OK" -command {
        set input 1
        destroy .new_window
    }] -side left -padx 5

    pack [ttk::button .new_window.buttons.button2 -text "Cancel" -command {
        set input 0
        destroy .new_window
    }] -side right -padx 5

    after 10000 {
        if {[winfo exists .new_window]} {
            set input 1
            destroy .new_window}
        }
    }
    vwait input
}

暂停执行等待用户输入或默认答案。

再见