闇の光

读书笔记 经验感受

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Going Graphical -- The dialog Utility

在我们结束shell脚本讨论之前,有一个虽然不是shell的一部分但却有更多的特性,尤其对于shell编程来说使用也非常普遍,因此我们将在此对它做一番了解。

如果我们知道我们的脚本将只在linux控制台运行,有一种简洁的方法可以用来改善我们的脚本特色,它就是dialog,一个实用程序命令。该命令虽然使用文本模式图形和颜色,但看起来依旧有着令人愉悦的图形色彩。

注意:在一些发行版中,dialog不是默认安装的。比如在Ubuntu下你可能不得不添加公共软件仓库地址以获得一个对应的软件版本。另外,在一些发行版中,我们可能会发现在其中已经安装了一个叫gdialog的程序,看起来十分类似,不过它是基于GNOME用户界面来显示它的会话,只是返回来的是一个真正的图形界面。

整个dialog的思想都很简单——只是一个有着种类繁多的参数和选项的单一程序,而且这些参数和选项允许你用来显示不同种类的图形方框,所显示的范围也只是有着简单的Yes/No的输入方框以及甚至还拥有菜单选择。这个工具一般在用户进行输入操作之后返回,并且返回的结果可以由返回的状态或者是通过取回标准错误流输入的文本得到。

在我们深入了解之前,先让我们看一个简单的dialog运用。我们直接从命令行通过使用dialog创建一个简单的消息框:

dialog --msgbox "Hello World" 9 18

之后在屏幕上将显示一个带有OK对话框的图形消息框。
既然我们已经知道了dialog的操作是如此简单,之后让我们尽可能地了解更多与之相关的内容。下表为我们描述了我们可以创建的dialog的主要类型:

TypeOption Used to Create TypeMeaning
Check boxes--checklist允许我们显示列表项,且每一个都能被单独选择
Info boxes--infobox不用清屏就能直接返回的简单对话框
Input boxes--inputbox允许用户以文本方式输入
Menu boxes--menu允许用户从一列中选择单一的一项
Message boxes--msgbox向用户显示一条带有OK按钮的信息
Radio selection boxes--radiolist允许用户从一列中选择一个选项
Text boxes--textbox允许我们在一个有滚动轴的框中显示文件内容
Yes/No boxes--yesno允许你问一个问题,之后用户可以选择yes或no

一些额外的dialog对话框同样也是很有用的(比如计量器和密码输入对话框)。如果你想要了解更多不太常用的dialog类型,可以查阅相关的手册指南。

为了得到允许文本输入或选择的对话框的任何类型的输出,我们不得不捕获标准错误流,通常我们都直接将它送到一个临时文件中,之后再对它进行处理。而为了得到yes/no类型问题的结果,我们只需看退出代码,通常设计良好的程序都将返回0代表成功,而返回1则代表失败。

所有的dialog类型都有许多附加参数来用于控制,比如dialog所呈现的大小以及形状。我们在下表列出了每一种类型所需要的不同参数,之后我们将在命令行中示范操作他们中的一部分。最后,你将会看到在一个简单的包含几个dialog的程序。

Dialog TypeParameters
--checklisttext height width list-height [tag text status]...
--infoboxtext height width
--inputboxtext height width [initial string]
--menutext height width menu-height [tag item]...
--msgboxtext height width
--radiolisttext height width list-height [tag text status]...
--textboxfilename height width
--yesnotext height width

此外,所有的diglog类型都可以携带几个选项,我们不会在此将它们一一列出,除了需要注意这两个:

  • --title      允许你为对话框指定一个标题
  • --clear      使用它就是为了清屏
  • 若想了解所有的选项,请查阅相关的手册指南。

    下面让我来看一下一个有点复杂的例子。一旦你理解了这个例子,其他的dialog实例将变得容易。在这个例子中,你创建了一个带有标题“Check me”以及指令“Pick Numbers”的清单类型对话框。这个对话框高15个字符,宽25个字符,并且每个选项都要占领3个字符的高度。最后,你至少在显示这些列出的选项时,需要沿着一个默认的on/off选择。

    diag --title "Check me" --checklist "Pick Numbers" 15 25 3 1 "one" "off" 2 "two" "on" 3 "three" "off"

    原理:

    在这个示例中,参数--checklist指定了你将创建一个清单类型对话框。之后你使用--title选项来设置标题“Check me”,而接下来的参数则提示“Pick Numbers”的信息。然后你开始设置对话框的大小,15行高25字符宽,并有3行高的高度被用于菜单的显示。这虽然不是一个完美的尺寸,但足够你看到所有的东西都被呈现出来。

    选项的使用看起来有点错综复杂,但你需要全部记住的只是每个菜单项目都只有三个数值:标号、文本以及状态。第一个项目为1,显示为“one”并且设置为“off”。之后的菜单项目2显示为“two”,设置为“on”,即被此项被选中了。最后菜单项目3显示为“three”,设置为“off”。

    很容易,对不对?我们只需尝试将他们在命令行中运行就可以轻易地看出它们是怎样被使用的。为了将这些对话框放入一个程序中,我们需要能够访问用户所输入的结果,这是非常容易的。只需为文本输入将标准错误流重定向,或者检查系统环境变量$?,这样你就可以再次调用先前命令的退出状态。

    下面我们看一个使用dialog的更复杂一些的例子。

    我们先编写一个简单的程序questions,它用来接受用户响应的记录:

    1.开始先显示一个简单的对话框以告诉用户发生了什么,你不需要得到相关的结果或获取任何用户输入,因此我们可以这样简单地编写:

    #!/bin/sh

    # Ask some questions and collect the answer
    dialog --title "Questionnaire" --msgbox "Welcome to my simple survey" 9 18

    2.通过一个简单的yes/no对话框询问用户是否继续进行。通过使用环境变量$?来检查用户所选择的到底是yes(返回代码0)还是no。如果他不想继续进行,我们就会在退出前使用一个简单的不需要用户有输入的信息对话框:

    diag --title "Confirm" --yesno "Are you willing to take part?" 9 18
    if [ $?  != 0 ]; then
        dialog --infobox "Thank you anyway" 5 20
        sleep 2
        dialog --clear
        exit 0
    fi

    3.通过一个输入框询问用户的名字。重定向标准错误流2到一个临时文件_1.txt中,之后通过变量Q_NAME来进行处理:

    dialog --title "Questionnaire" --inputbox "Please enter your name" 9 30 2>_1.txt
    Q_NAME=$(cat _1.txt)

    4.在此处你将设置菜单项目为四个不同的选项,之后你再次重定向标准错误流并将它置入一个变量中:

    dialog --menu "$Q_NAME, what music do you like best?" 15 30 4 1 "Classical" 2 "Jazz" 3 "Country" 4 "Other" 2>_1.txt
    Q_MUSIC=(cat _1.txt)

    5.根据所获得的变量Q_MUSIC得到存储在临时文件_1.txt中的用户所选择的数字,你可以这样来设置结果:

    if [ "$Q_MUSIC" = "1" ]; then
         dialog --title "Likes Classical" --msgbox "Good choice!" 12 25
    else
         dialog --title "Doesn't like Classical" --msgbox "What a shame!" 12 25
    fi

    6.最后,清除最终的对话框,之后退出程序:

    sleep 2
    dialog --clear
    exit 0

    OK,现在我们可以通过shell编程只使用shell脚本来显示一个简单GUI程序了。

    注:如果你将运行于一个基于GNOME的GUI且只在其中使用终端会话的话,你可以使用gdialog命令来替代dialog。这两个命令拥有一样的参数,所以你完全可以使用gdialog替代dialog来执行相同的代码。
    posted on 2008-03-17 21:21  taizi  阅读(599)  评论(0编辑  收藏  举报