jinfeng_wang

G-G-S,D-D-U!

BlogJava 首页 新随笔 联系 聚合 管理
  400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

http://www.ibm.com/developerworks/cn/linux/guitoolkit/newt/index.html




NEWT是在Linux下一个基于文本方式的窗口开发工具,最初是为Red Hat Linux的安装程序而设计的。本文将告诉您怎样一步步使用NEWT为自己的应用程序加上文本方式下的窗口界面。

NEWT简介

考虑到Red Hat Linux有软盘安装这一安装方式,安装代码运行于有限的资源环境中,特别是在有限的文件空间中。NEWT的大小一开始就成为一个重要的问题。为了最小化它所占的空间,NEWT的设计思想有下面几点:

  1. NEWT由C语言写成,而不是C++
  2. NEWT所有窗口的生成都是基于堆栈的数据结构,窗口的外观都是统一的模板,不由程序员修改
  3. 输入设备只支持终端键盘
NEWT 提供C语言的应用程序接口(API),它不直接进行低级屏幕操作,是在S-Lang 库上实现的。

 

组件(Components)

在NEWT中,每一个可显示的项目称为组件。组件主要有两类:Form组件与非Form组件。非Form组件是除Form以外的所有组件。Form逻辑地组织各个组件成为一个功能集。Form是一个容器组件,让其他组件都装在其上,有点类似gtk中的垂直盒(Vbox)和水平盒(Hbox)。当一个应用准备从用户中获得输入,就要run一个Form,这也类似于gtk中的gtk_widget_show()。Form组件可以包含其他任何组件,也包含其他的Form作为子Form。

每一个组件都是由一个属于newtComponent数据类型的变量唯一标志,这一变量必须由生成该组件的函数建立,而不能由程序员自己建立。属于newtComponent数据类型的变量其实只是一个指针。

NEWT程序的开始与结束

有三个函数是每个NEWT程序都必须用到的,头两个用于初始化系统。

int newtInit(void);
            void newtCls(void);

newtInit()必须是每个NEWT程序第一个调用的函数,用于初始化数据结构和重置终端于raw模式。大多数应用在newtInit()后立即调用newtCls(),newtCls()用于清除屏幕,这个函数不是必须的,但有助于优化屏幕。

当一个NEWT程序准备结束时,就要调用以下函数。
int newtFinished(void);

newtFinished()恢复终端在调用newtInit()前的状态,重置原来的输入状态。若没调用这函数,终端需重启才能回到命令行状态。

编译NEWT程序

在Linux上用gcc编译时带 -lnewt 参数。以下所说的函数都可在/usr/include/newt.h(Red Hat Linux 7.1)中找到。

标志

NEWT定义了若干个标志(FLAG),这里仅介绍常用的几个。

  • NEWT_FLAG_RETURNEXIT�D�D当在组件上按回车时程序退出
  • NEWT_FLAG_HIDDEN�D�D输入不回显,大多数应用在输入密码的情况
  • NEWT_ENTRY_SCROLL�D�D允许滚动输入
  • NEWT_FLAG_WRAP�D�D换行时整个单词换行
  • NEWT_FLAG_BORDER�D�D加边框
  • NEWT_FLAG_MULTIPLE�D�D允许多选

若要使用多个标志,可对多个标志进行与操作('|')。

根窗口(root window)

终端所显示的背景,只有不被任何窗口遮盖的部分称为根窗口。一般地,应用不需使用到根窗口,而把文字写到属于自己的窗口上。所有组件都不应放在根窗口上。根窗口只用于显示一些辅助信息,例如程序的作者姓名、版本等。NEWT提供两种在根窗口显示文字的方式,它们是唯一能越出组件自己当前窗口写文字的NEWT函数。

void newtDrawRootText(int left, int top, const char *
            text);

该函数用于在根窗口指定位置写出text字苻串,left和top为字苻串text的开始处,left是屏幕x坐标,top是屏幕y坐标。

Left和top允许为负数。屏幕坐标原点在显示器的左上角,x坐标从原点出发至左向右增大,y坐标从原点出发至上向下增大。点(10,5)表示以左上角为原点x=10,y=5,而left,top为负,表与为正数方向相对。点(-10,5)表以右上角为原点x=10,因此点(10,5)与点(-10,5)在屏幕左右两边相对,同理点(10,5)与点(10,-5)在屏幕上下两边相对。

在文本方式下,通常屏幕的最后一行用于显示帮助信息,如每个快捷键所对应的功能等。这一提示行称为帮助行(help line)。正如前面所述,NEWT是基于堆栈,压栈Push操作显示帮助行,出栈Pop操作删除帮助行。基于栈的操作后面还回遇到。

void newtPushHelpLine(const char * text);
            void newtPopHelpLine(void);

newtPushHelpLine()用于显示帮助行,text为所要显示的字苻串指针,若为NULL则显示缺省的帮助行。NewtPopHelpLine()则删除帮助行。

非正常退出 

在缺省情况下,NEWT程序不能非正常退出,尽管大多数Unix程序可以通过按Ctrl-z强迫退出,但在NEWT不支持此功能。因NEWT初始化时屏蔽所有终端信号。

typedef void (*newtSuspendCallback)(void);
            void newtSetSuspendCallback(newtSuspendCallback cb);

但可通过调用newtSetSuspendCallback()实现Ctrl-z强迫退出的功能,cb是相应的回调函数,它不带参数,只做清理工作,如newtFinished()等。早期Red Hat Linux的安装程序当运行到硬盘分区时,若你使用Fdisk则屏幕回到命令行状态运行Fdisk进行分区,退出Fdisk时又回到当前窗口。要实现这种功能,在回调函数中加入下面两个函数:
void newtSuspend(void);
            void newtResume(void);

newtSuspend()告诉NEWT程序回到终端初始化前的状态,做需要做的工作。如需要回到NEWT界面,调用newtResume()恢复。

窗口

生成窗口有两种主要方式:
int newtCenteredWindow(int width, int height, const char * title);
            int newtOpenWindow(int left, int top, int width, int height, const char * title);

由名字可知,newtCenteredWindow()在屏幕中心生成窗口,width为窗口宽度,height为窗口高度,title为窗口标题字串指针,标题文字为红色。由newtOpenWindow()生成的窗口位置由left,top确定,其余参数同上。

所有窗口的删除都是用同一种方式,由于NEWT是基于堆栈来操作,只有在栈顶的窗口才能被删除,位于栈顶的窗口即当前你能看到的不被任何其他窗口遮盖的窗口。

void newtPopWindow(void);

这函数删除屏幕最顶层的窗口,并重画被该窗口遮盖的部分。

Form

正如前述那样,Form是一个容器组件,同一时间只能生成一个Form,所有组件都必须放在Form上,然后运行它。生成一个Form用以下函数:
newtComponent newtForm(newtComponent vertBar, const char * help, int flags);

vertBar是垂直滚动条,help是提示信息,通常这两个参数都不会用到,用NULL即可,flags就是前述的标志。该函数返回标志所生成的Form的变量。

把组件放在Form上用以下函数:
void newtFormAddComponent(newtComponent form, newtComponent co);
            void newtFormAddComponents(newtComponent form, ...);

newtFormAddComponent()只放一个组件在Form上,而newtFormAddComponents()则可放多个组件,最后用NULL结束。

然后就运行它:
newtComponent newtRunForm(newtComponent form);

其中Form参数是newtForm()返回的变量。

删除一个Form:
void newtFormDestroy(newtComponent form);

当一个Form被删除时,其上的组件一同被删除,并释放内存资源。

按钮

几乎所有的Form都包含最小一个按钮。按钮分两类:完全按钮(full button)和紧缩按钮(compact button)。完全按钮富有立体感,紧缩按钮则单调些。

newtComponent newtButton(int left, int top, const char * text);
            newtComponent newtCompactButton(int left, int top, const char * text);

newtButton()生成完全按钮,letf,top指定该按钮位置,text是指向按钮文字的指针,该函数返回按钮的newtComponent变量。NewtCompactButton()生成紧缩按钮,参数及返回值同上。

标签

标签是NEWT程序最简单的组件,用于显示给定的文本但不允许用户输入。

newtComponent newtLabel(int left, int top, const char * text);
            void newtLabelSetText(newtComponent co, const char * text);

newtLabel()生成标签组件,并返回它的newtComponent变量,参数left,top指定标签组件位置,text为给定的文本。NewtLabelSetText()用于动态改变标签组件的文字,co是要改变的标签组件,test是要改变的字串指针。

输入盒(Entry Box)

输入盒可让用户输入字符串到Form中然后由应用接收。

newtComponent newtEntry(int left, int top, const char * initialValue, int width,char ** resultPtr, int flags);
            void newtEntrySet(newtComponent co, const char * value, int cursorAtEnd);
            char * newtEntryGetValue(newtComponent co);

newtEntry()生成输入盒组件,其中initialValue为初始化字符串指针,若不需则用NULL,width为宽度,resultPtr为指向当前输入的字符,flags为标志。Flags设为NEWT_ENTRY_SCROLL,当输入的字串长度等于输入盒的宽度时输入盒将往后滚动,否则不能再输入;Flags设为NEWT_FLAG_HIDDEN 输入不回显,主要应用于输入密码方面。NewtEntrySet()用于动态地改变输入盒的内容,value为字符串指针,cursorAtEnd实质是一个逻辑变量,由于C语言没有逻辑类型变量,仅用int代替,若为0则表TRUE,指定光标跟随,非0光标不跟随输入。NewtEntryGetValue()返回输入的字串。

检查盒(Checkbox)

检查盒可对其代表的内容通过按空格键切换预定的各种状态。

newtComponent newtCheckbox(int left, int top, const char * text, char defValue,const char * seq, char * result);
            char newtCheckboxGetValue(newtComponent co);

newtCheckbox()生成一个检查盒,text标明它所代表的内容,defValue为缺省值也即初始值,seq为切换的顺序,result指向当前状态。如defValue='@',seq="@*X",则初始时为[@],当按空格键==》[*]再按空格键==》[X],如此循环。若result为NULL则需 NewtCheckboxGetValue()获取当前状态。

单选按钮(Radio Button)

单选按钮的外观与检查盒非常相似。不同的是单选按钮是由若干个组成一个集合,当一个单选按钮被选中时,其他单选按钮则被清除。若集合中只有一个单选按钮,它总会被选中,因而就失去了选择的意义。

newtComponent newtRadiobutton(int left, int top, const char * text, int isDefault, newtComponent prevButton);
            newtComponent newtRadioGetCurrent(newtComponent setMember);

newtRadiobutton()建立单选按钮集合,text为代表单选按钮的字符串指针,isDefault是逻辑开关,为1表逻辑TRUE,初始状态为选中;为0表FALSE,初始状态为不选中。若当前单选按钮是集合中的第一个,prevButton为NULL让newtRadiobutton()自动建立一个集合;若不是第一个,prevButton为前一个由newtRadiobutton()生成的单选按钮。

范围(Scale)

范围组件通常用于制作水平进度条。

newtComponent newtScale(int left, int top, int width, long long fullValue);
            void newtScaleSet(newtComponent co, unsigned long long amount);

newtScale()生成水平进度条,width为宽度,fullValue为进度条的最大值。NewtScaleSet()用于设置进度条的值。

文本盒(Textbox)

文本盒能让终端显示一个文本块。

newtComponent newtTextbox(int left, int top, int width, int height, int flags);
            void newtTextboxSetText(newtComponent co, const char * text);

newtTextbox()建立一个文本盒,其中flags可设为NEWT_FLAG_WRAP、NEWT_FLAG_SCROLL和它们的与操作。文本盒建立后,由newtTextbox()填充文本。

滚动条(Scrollbar)

newtComponent newtVerticalScrollbar(int left, int top, int height,int normalColorset, int thumbColorset);

newtVerticalScrollbar()生成滚动条,normalColorset为滚动条颜色,thumbColorset为滚动块颜色。

列表盒(Listboxe)

列表和是NEWT中最重要的组件,允许多选或单选

newtComponent newtListbox(int left, int top, int height, int flags);
            int newtListboxAppendEntry(newtComponent co, const char * text, const void * data);
            void * newtListboxGetCurrent(newtComponent co);
            void newtListboxSetWidth(newtComponent co, int width);
            void newtListboxSetCurrent(newtComponent co, int num);
            void newtListboxSetCurrentByKey(newtComponent co, void * key);

newtListbox()生产列表盒,flags可设为NEWT_FLAG_SCROLL、NEWT_FLAG_RETURNEXIT、NEWT_FLAG_BORDER、 NEWT_FLAG_MULTIPLE和它们的与操作。NewtListboxAppendEntry()用于在当前列表盒最后追加一个列表项,每一个个列表项由key唯一标志,key可为任意类型,只要能和其他列表项区别开来就可以了。data为key数据。操作列表盒的函数还有:

void newtListboxSetEntry(newtComponent co, void * key, const char * text);
            int newtListboxInsertEntry(newtComponent co, const char * text, const void * data, void * key);
            int newtListboxDeleteEntry(newtComponent co, void * key);
            void newtListboxClear(newtComponent co);





回页首


例子:

#include <newt.h>
            #include <stdio.h>
            void rootwin_show()
            {
            newtCls();
            /*请观察left,top为正数,为负数地情形*/
            newtDrawRootText(0, 0, "左上角");
            newtDrawRootText(-6, 0, "右上角");
            newtDrawRootText(0, -3, "左下角");
            newtDrawRootText(-6, -3, "右下角");
            /*注意helpline缺省时的内容*/
            newtPushHelpLine(NULL);
            newtRefresh();
            sleep(10);
            newtPushHelpLine("我的帮助行");
            newtRefresh();
            sleep(3);
            newtPopHelpLine();
            newtRefresh();
            sleep(1);
            }
            void label_button()
            {
            newtComponent form, label, entry, button,cb;
            char * entryValue;
            newtCls();
            newtCenteredWindow(50,10,"输入与标签演示");
            /*left,top是相对于中心窗口而言*/
            label = newtLabel(10, 1, "请输入:");
            entry = newtEntry(19, 1, NULL, 20, &entryValue,
            NEWT_FLAG_SCROLL);
            newtEntrySet(entry,"\0",0);
            button = newtButton(10, 5, "完全按钮");
            cb=newtCompactButton(25,5,"紧缩按钮");
            form = newtForm(NULL,NULL, 0);
            newtFormAddComponents(form, label, entry, button,cb, NULL);
            newtRunForm(form);
            if(*entryValue!='\0')
            {
            newtDrawRootText(0,0,"你输入了:");
            newtDrawRootText(12,0,entryValue);
            }
            else
            newtDrawRootText(0,0,"无输入!");
            newtRefresh();
            newtFormDestroy(form);
            sleep(5);
            }
            void check_radio()
            {
            newtComponent form, checkbox, rb[3], button,lable1,lable2;
            char cbValue,cv[2];
            int i;
            newtCls();
            newtOpenWindow(10, 8, 40, 11, "检查盒与单选盒演示");
            lable1 = newtLabel(2, 1, "检查盒:");
            checkbox = newtCheckbox(10, 1, "A checkbox", ' ', " *X", &cbValue);
            lable2 = newtLabel(2, 4, "单选盒:");
            rb[0] = newtRadiobutton(10, 3, "Choice 1", 1, NULL);
            rb[1] = newtRadiobutton(10, 4, "Choice 2", 0, rb[0]);
            rb[2] = newtRadiobutton(10, 5, "Choice 3", 0, rb[1]);
            button = newtButton(15, 7, "退出");
            form = newtForm(NULL, NULL, 0);
            newtFormAddComponent(form, checkbox);
            newtFormAddComponent(form, lable1);
            newtFormAddComponent(form, lable2);
            for (i = 0; i < 3; i++)
            newtFormAddComponent(form, rb[i]);
            newtFormAddComponent(form, button);
            newtPushHelpLine("<空格健>选择");
            newtRefresh();
            newtRunForm(form);
            for (i = 0; i < 3; i++)
            if (newtRadioGetCurrent(rb[0]) == rb[i])
            {       newtDrawRootText(0, 0, "单选盒:");
            newtDrawRootText(9, 0, "第");
            if(i==0)newtDrawRootText(11, 0,"1");
            if(i==1)newtDrawRootText(11, 0,"2");
            if(i==2)newtDrawRootText(11, 0,"3");
            newtDrawRootText(12, 0, "个");
            }
            newtDrawRootText(0, 3, "检查盒状态:");
            cv[0]=cbValue;cv[1]='\0';
            newtDrawRootText(13, 3, cv);
            newtRefresh();
            newtFormDestroy(form);
            sleep(5);
            }
            void test()
            {
            char message[] = "This is a pretty long message. It will be displayed "
            "in a newt textbox, and illustrates how to construct "
            "a textbox from arbitrary text which may not have "
            "very good line breaks.\n\n"
            "Notice how literal \\n characters are respected, and "
            "may be used to force line breaks and blank lines.";
            newtComponent form, text, button;
            newtCls();
            text = newtTextboxReflowed(1, 1, message, 30, 5, 5, 0);
            button = newtButton(12, newtTextboxGetNumLines(text) + 2, "退出");
            newtOpenWindow(10, 5, 37,
            newtTextboxGetNumLines(text) + 7, "文本盒");
            form = newtForm(NULL, NULL, 0);
            newtFormAddComponents(form, text, button, NULL);
            newtRunForm(form);
            newtFormDestroy(form);
            }
            main()
            {
            newtComponent ls,fm;
            int p = 1, q = 2, r = 3, s = 4, t = 5, *u;
            newtInit();
            do {
            newtCls();
            newtRefresh();
            newtDrawRootText(0,0,"这是我的一个NEWT演示程序");
            newtCenteredWindow(50,10,"请选择");
            ls = newtListbox(18,3,5,NEWT_FLAG_RETURNEXIT);
            newtListboxAppendEntry(ls,"根窗口演示",&p);
            newtListboxAppendEntry(ls,"输入盒与按钮",&q);
            newtListboxAppendEntry(ls,"检查盒与单选盒",&r);
            newtListboxAppendEntry(ls,"文本盒",&s);
            newtListboxAppendEntry(ls,"退出 ",&t);
            newtPushHelpLine("                Move using the arrow keys and press ENTER to select");
            fm = newtForm(NULL,NULL,0);
            newtFormAddComponents(fm,ls,NULL);
            newtRunForm(fm);
            u = newtListboxGetCurrent(ls);
            newtPopWindow();
            newtFormDestroy(fm);
            switch(*u) {
            case 1:
            rootwin_show();
            break;
            case 2:
            label_button();
            break;
            case 3:
            check_radio();
            break;
            case 4:
            test();
            break;
            case 5:
            newtFinished();
            exit(0);
            }
            } while(1);
            }
            

运行结果如下图:



 
posted on 2007-07-20 14:02 jinfeng_wang 阅读(615) 评论(0)  编辑  收藏 所属分类: ZZLinux

只有注册用户登录后才能发表评论。


网站导航: