基于Zenity的Bash脚本选项窗口重复弹出问题求助
问题原因与解决思路
问题根源
当你在select_letter对话框点击Cancel时,代码直接调用app_main()回到主菜单,但此时原来的select_letter函数并没有终止,它仍然留在函数调用栈中。当你再次选择“Analyze a Letter”并完成select_letter流程后,旧的调用栈会继续执行后续的select_letter_options,加上当前流程触发的select_letter_options,就导致了选项窗口弹出两次的问题——本质是递归调用引发的执行栈残留。
修复方案
移除子函数中直接调用app_main()的逻辑,改为通过返回值让上层的app_main控制流程,避免嵌套递归导致的执行栈混乱:
- 让
select_letter和select_letter_options在用户取消时返回错误状态(非0值) - 在
app_main中检查子函数的返回状态,决定是否继续执行后续步骤
修改后的完整代码
#!/bin/bash APP_NAME="bealeCrypter" function select_letter () { letter=("FALSE" "1" "Treasury location" "none" "FALSE" "2" "Treasury contents" "yes" "FALSE" "3" "Treasury beneficiaries" "none") LETTER_FILES=$(zenity --list \ --width=430 \ --height=235 \ --title="$APP_NAME" \ --text="What letter do you want to $1 ?" \ --checklist \ --multiple \ --column=Selection \ --column=Letter \ --column=Description \ --column=Decrypted \ "${letter[@]}") if [ $? -eq 0 ]; then if [ -z "$LETTER_FILES" ]; then select_letter "$1" fi return 0 # 正常选择完成,返回成功状态 else return 1 # 用户取消,返回错误状态 fi } function select_letter_options () { letter_options=("TRUE" "1" "Get the number of characters" "TRUE" "2" "Get the smallest number" "TRUE" "3" "Get the biggest number") LETTER_OPTIONS=$(zenity --list \ --width=350 \ --height=210 \ --hide-header \ --title="$APP_NAME" \ --text="Choose the analyze letter options :" \ --checklist \ --multiple \ --column=Selection \ --column=Id \ --column=Description \ --hide-column=2 \ "${letter_options[@]}") if [ $? -eq 0 ]; then if [ -z "$LETTER_OPTIONS" ]; then select_letter_options fi return 0 # 正常选择完成,返回成功状态 else return 1 # 用户取消,返回错误状态 fi } function app_main () { while true; do # 用循环代替递归,避免栈溢出 menu=("1" "Analyze a Letter") SELECTION=$(zenity --list \ --width=350 \ --height=210 \ --hide-header \ --title="$APP_NAME" \ --text="What to do ?" \ --column=Id \ --column=Selection \ --hide-column=1 \ --cancel-label=Quit \ "${menu[@]}") if [ $? -ne 0 ]; then exit 0 fi case "$SELECTION" in 1) select_letter "analyze" if [ $? -eq 0 ]; then # 只有select_letter正常完成,才调用选项函数 select_letter_options echo -e "LETTER: $LETTER_FILES\nLETTER_OPTIONS: $LETTER_OPTIONS" fi ;; *) continue esac done } app_main
关键修改说明
- 子函数取消时不再调用
app_main,而是返回1表示操作取消 app_main改用while true循环代替递归调用,避免递归栈积累- 调用
select_letter后检查返回值,只有正常完成时才执行select_letter_options
内容的提问来源于stack exchange,提问作者Momonosoke
相关产品推荐
相关产品推荐

