![Linux程序设计(第4版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/825/26211825/b_26211825.jpg)
2.7 迈向图形化:dialog工具
在结束讨论shell脚本程序之前,我们还将介绍一个特性。尽管严格来说,它并不是shell的一部分,但是在通常情况下,它仅仅在shell程序设计中有用,所以我们将在这里讨论它。
如果你知道你的脚本程序只需要运行在Linux控制台上,则可以使用dialog工具命令,它以一种非常整洁的方式润色你的脚本程序。这个命令使用文本模式的图形和色彩,但它的确提供了友好的面向图形的解决方案。
一些Linux发行版默认并没有安装dialog工具。例如,对于Ubuntu来说,你可能必须添加公开维护的套件库来找到一个现成的版本。在其他Linux发行版中,你可能会找到一个已安装的替代工具gdialog。它和dialog工具非常相似,但它依赖GNOME用户接口来显示其对话框。然而,你得到的回报是你获得了一个真正的图形化界面。一般来说,你可以将任何使用dialog工具的程序中对dialog工具的调用替换为对gdialog工具的调用,从而获得程序的一个图形化版本。我们将在本节最后提供一个使用gdialog的程序示例。
dialog工具的整体思想非常简单:一个带有各种各样参数和选项的程序,它可以显示各种类型的图形框,范围涵盖从最简单的Yes/No框到输入框,甚至菜单选项。这个工具通常在用户执行某种类型的输入后返回,返回结果可以通过退出状态获得,或在用户输入文本时,通过标准错误流来获取。
在详细介绍它之前,我们先来看一个非常简单的使用dialog的例子。你可以在命令行上直接使用dialog,这对于程序的原型设计很有用。现在让我们创建一个简单的消息框,来显示传统意义上的第一个程序:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0083_0001.jpg?sign=1739287846-RrhZvrYom6JNcbNbDu8lyosYCEnpm8F6-0-b99cde80aca06f5a8d1c156fc3d9aafe)
执行它就会在屏幕上显示一个图形化的消息框,你可以通过OK对话框关闭它(见图2-3)。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0083_0002.jpg?sign=1739287846-X1XBzlO3Wk6O9DbRYST6TIutJk2qfmoS-0-ca7b9b2c947509d7f751039bb5010fd4)
图2-3
现在你已看出dialog的使用非常容易,接下来我们对它的各种可能性进行详细地介绍。表2-22列出了你可以创建的对话框的主要类型。
表2-22
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0083_0003.jpg?sign=1739287846-NOx9rfRo08c6JGEkAueun7Py2bRJzNHf-0-ea34ffa0e06ef23f5173e49e0daec40e)
还有一些其他的对话框类型(例如,进度框和密码框)可用。如果你想了解更多不常用的对话框类型,你也可以参考在线手册页。
如果想获得任何类型的允许文本输入或进行选择的对话框的输出,你必须捕获标准错误流,通常是把它指向某个临时文件以便后续处理。要想获得Yes/No对话框的输出结果,只需查看它的退出码,与所有设计良好的程序一样,返回0表示成功(例如,选择yes选项),返回1表示失败。
所有的对话框类型都有各种各样的用于控制的参数,比如控制显示的对话框的大小和形状。我们首先列出每种类型需要的参数(见表2-23),然后在命令行上演示其中一部分参数的用法。最后,你将看到一个简单的将几种对话框结合起来的程序。
表2-23
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0084_0001.jpg?sign=1739287846-44OrbYxOYkjj2EyKnDwD4T30epDrBQT3-0-3b4e6fd9baedd884d1bccecf9bdc446b)
除此之外,所有的对话框类型都有几个相同的参数选项。在此我们不一一列出,只介绍两个选项:--title和—clear。前者用于指定对话框的标题,后者用来完成清屏操作。完整的选项列表请查询手册页。
实验 使用dialog工具
让我们直接跳到一个很复杂的例子。一旦你理解了这个例子,所有其他的程序就非常简单了!在这个例子中,你将创建一个标题为Check me的复选框,它包括一条提示信息Pick Numbers。复选框高15字符,宽25字符,每个选项高3个字符。最后,你列出要显示的选项并设置了默认的开关选择。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0084_0002.jpg?sign=1739287846-d38Cw1Q3sNHhopw12EsEeekmqoZI9VF5-0-6cb9ba34efc36e18de503187e9aaa0a5)
图2-4显示了该命令执行的结果。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0084_0003.jpg?sign=1739287846-V3VLb2EPtaHN0MO1Yqw4B6e01dlQRkAj-0-e1680879609886f2e3fcd7f8b74cbdd3)
图2-4
实验解析
在本例中,--checklist参数用于创建一个复选框。--title选项将标题设置为Check me,下一个参数是提示信息Pick Numbers。
你接下来设置对话框的大小。它高15行,宽25个字符,3行被用于菜单。这个大小并不是最合适的,但是你可以从中看到内容的排列方式。
选项的设置看上去有点棘手,但你只需要记住每个菜单选项有3个值:
❑ 编号;
❑ 文本;
❑ 状态。
第一个菜单项的编号是1,显示的文本是one,状态设置为off。第二个菜单项的值分别是2、two和选中。依次继续直到菜单项设置完毕。
是不是很容易?你可以在命令行上尝试一下,看看它的使用有多么简单。为了能将这些放在一个程序中,你需要能够访问用户输入的结果。这一点很容易实现,对于文本输入,你只需要重定向标准错误流或检查环境变量$?的内容,$?的值实际上就是前一个命令的退出状态。
实验 一个更复杂的使用dialog工具的程序
我们来看一个名为questions的简单程序,它关注用户的响应:
(1)首先,该程序通过显示一个简单的对话框来告诉用户发生的事情。你不需要获得返回值或任何用户的输入,所以这看起来非常简单和友好:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0085_0001.jpg?sign=1739287846-sPfKlYJnNbDOP8bJNlTX2ngtB5S5CPE1-0-afd1305661b020b18bf3741b7664c7ca)
(2)然后用一个简单的yes/no对话框来询问用户是否要继续操作。我们用环境变量$?来检查用户是否选择了yes(返回码是0)。如果用户不想继续操作,就使用一个简单的信息框显示信息,信息框在退出之前不需要用户的输入。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0085_0002.jpg?sign=1739287846-aoWqhvXasNc63j8IvcTGuttsRbRd0CPo-0-58052da479319b4d4b99b53c1cd062ff)
(3)我们使用一个输入框来询问用户的姓名。重定向标准错误流2到临时文件_1.txt,然后再将它放到变量Q_NAME中:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0085_0003.jpg?sign=1739287846-se0YBYBab7OoUhuV7U92UDOmI8hwC2oq-0-ba65a2d0e95cef05f22c75521f19455f)
(4)现在显示一个菜单,它有4个不同的选项。你再次重定向标准错误流并且把它装载到一个变量中:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0085_0004.jpg?sign=1739287846-NNVXdhn9wNefyTGp5VlKRmn7xmBDn1nO-0-94522e6a4a014adb304b930eb19160df)
(5)用户选择的菜单项编号将被保存到临时文件_1.txt中,同时这个结果被放入变量Q_MUSIC中,以便你对结果进行测试:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0085_0005.jpg?sign=1739287846-pljvzqzYuZEGzKyMJmnE6bUba7RT9Cru-0-16144cdd267a322dde0cad32ccf278a3)
(6)最后,清除对话框并退出程序:
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0085_0006.jpg?sign=1739287846-s2hhAOXN1A1hywR4szbjZw2ZswR39lSZ-0-4234163e9f497471cc93744d1adb7388)
图2-5显示了屏幕上的输出信息。
实验解析
本例通过将dialog命令和一些简单的shell编程语句相结合,讲解了如何仅仅使用shell脚本来构建简单的GUI程序。程序从一个简单的欢迎页面开始,然后使用一个简单的--yesno对话框询问用户是否愿意继续操作。程序使用变量$?来检查用户的回答。如果用户同意,程序将获得用户的姓名并将它保存在变量Q_NAME中,然后使用--menu对话框询问用户喜欢哪种类型的音乐。通过将用户选择的菜单项编号保存到变量Q_MUSIC中,程序可以看到用户的回答并给出适当的回应。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0086_0001.jpg?sign=1739287846-zluZwWnBljI5xCGx4JX5vxFAIGvau62N-0-6d81b37d7910c666e984ed15a1a3540c)
图2-5
如果你运行的是一个基于GNOME的GUI,并且正在使用它提供的终端会话,你就可以使用gdialog命令来代替dialog。这两个命令有着相同的参数,因此你只需将调用的命令从dialog改为gdialog即可,其他的代码完全不需改动。图2-6显示了在Ubuntu系统中,使用上面脚本程序的gdialog版本时,屏幕的输出结果。
![](https://epubservercos.yuewen.com/08DD0E/14642180305205206/epubprivate/OEBPS/Images/figure_0086_0002.jpg?sign=1739287846-PsaJTnZPl6Fa7aWlnfkaVZtQg07t5DuG-0-7abd33843f75eac57278845ae120d3c3)
图2-6
这是从一个脚本程序中生成可用的GUI界面的非常简单的方法。