📄 ch34.htm
字号:
XtRealizeWidget(top);
XtAppMainLoop(app);
return(0);
}
void bye(Widget w, XtPointer clientdata, XtPointer calldata)
{
exit(0);
}
</FONT></PRE>
<P>Refer to Figure 34.6, shown previously, for the output of this listing with the
<TT>#define DO_RADIO</TT> line commented out. By defining the <TT>DO_RADIO</TT> label,
you can make this into a Radio Button application. That is, only one of the buttons
can be selected at one time. Refer to Figure 34.5, shown previously, for the radio
behavior of these buttons.
<H3 ALIGN="CENTER"><A NAME="Heading27<FONT COLOR="#000077">Convenience Functions</FONT></H3>
<P>Usually the time to set resources for a Widget is at the Widget's creation. This
is done either with the <TT>XtVaCreateManagedWidget</TT> call or with the <TT>XmCreate</TT>YYY
call, where YYY is the name of the Widget you are creating.</P>
<P>This test uses the variable argument call to create and manage Widgets. I do it
simply because it's easier for me to see what resources I am setting and to create
them all in one function call. You might have a personal preference to do it in two
steps. Either way is fine. Keep in mind, though, that if you do use the <TT>XmCreate</TT>YYY
call, you have to set the resource settings in a list of resource sets. Listing 34.4
is an example of creating a Label Widget. This is a function that creates a Label
Widget on a Widget given the string <TT>x</TT>.
<H3 ALIGN="CENTER"><A NAME="Heading28<FONT COLOR="#000077">Listing <A NAME="Heading2934.4.
Sample convenience function for creating a label on a form.</FONT></H3>
<PRE><FONT COLOR="#0066FF">/**
*** This is a sample convenience function to create a label
*** Widget on a parent. The string must be a compound string.
**/
Widget makeLabel( Widget onThis, XmString x)
{
Widget lbl;
Cardinal n;
Arg arg[5];
n = 0;
XtSetArg(arg[n], XmNalignment, XmALIGNMENT_BEGIN); n++;
XtSetArg(arg[n], XmNlabelString, x); n++;
lbl = XmCreateLabel("A Label", onThis, arg, n);
XtManageChild(lbl);
return(lbl);
}
</FONT></PRE>
<P>Or you could use the variable argument lists in creating this label, as shown
in Listing 34.5.
<H3 ALIGN="CENTER"><A NAME="Heading30<FONT COLOR="#000077">Listing <A NAME="Heading3134.5.
Creating a label.</FONT></H3>
<PRE><FONT COLOR="#0066FF">/**
*** Another way of making a label on a parent.
**/
Widget makeLabel( Widget onThis, XmString x)
{
Widget lbl;
lbl = XmCreateManagedWidget("A Label",
xmLabelWidgetClass, onThis,
XmNalignment, XmALIGNMENT_BEGIN,
XmNlabelString, x,
NULL);
return(lbl);
}
</FONT></PRE>
<P>In either case, it's your judgment call as to which one to use. The variable list
method of creating is a bit easier to read and maintain. But what about setting values
after a Widget has been created? This would be done via a call to <TT>XtSetValue</TT>
with a list and count of resource settings. For example, to change the alignment
and text of a label, you would use <TT>XtSetValues</TT>:</P>
<PRE><FONT COLOR="#0066FF">n = 0;
XtSetArg(arg[n], XmNalignment, XmALIGNMENT_BEGIN); n++;
XtSetArg(arg[n], XmNlabelString, x); n++;
XtSetValues(lbl,arg,n);
</FONT></PRE>
<P>Similarly, to get the values for a Widget, you would use <TT>XtGetValues</TT>:</P>
<PRE><FONT COLOR="#0066FF">Cardinal n; /* usually an integer or short... use Cardinal to be safe */
int align;
XmString x;
...
n = 0;
XtSetArg(arg[n], XmNalignment, &align); n++;
XtSetArg(arg[n], XmNlabelString, &x); n++;
XtGetValues(lbl,arg,n);
</FONT></PRE>
<P>In the case of other Widgets, let's use the Text Widget. This setting scheme is
hard to read, quite clumsy, and prone to typos. For example, when you get a string
for a Text Widget, should you use <TT>x</TT> or address of <TT>x</TT>?</P>
<P>For this reason, Motif provides convenience functions. For example, in the ToggleButton
Widget class, rather than using the combination of <TT>XtSetValue</TT> and <TT>XtSetArg</TT>
calls to get the state, you would use one call, <TT>XmToggleButtonGetState(Widget
w)</TT>, to get the state. These functions are valuable code savers when writing
complex applications. In fact, you should write similar convenience functions whenever
you can't find one that suits your needs.
<H3 ALIGN="CENTER"><A NAME="Heading32<FONT COLOR="#000077">The List Widget</FONT></H3>
<P>This displays a list of items from which the user selects. The list is created
from a list of compound strings. Users can select either one or many items from this
list. The resources for this Widget include the following: <TT>XmNitemCount</TT>:
Determines the number of items in the list.</P>
<P><TT>XmNitems</TT>: An array of compound strings. Each entry corresponds to an
item in the list. Note that a List Widget makes a copy for all items in its list
when using <TT>XtSetValues</TT>; however, it returns a pointer to its internal structure
when returning values to a <TT>XtGetValues</TT> call. Therefore, do not free this
pointer from <TT>XtGetValues</TT>.</P>
<P><TT>XmNselectedItemCount</TT>: The number of items currently selected.</P>
<P><TT>XmNselectedItems</TT>: The list of selected items.</P>
<P><TT>XmNvisibleItemCount</TT>: The number of items to display at one time.<BR>
<BR>
<TT>XmNselectionPolicy</TT>: Used to set single or multiple selection capability.
If set to <TT>XmSINGLE_SELECT</TT>, the user will be able to only select one item.
Each selection will invoke the <TT>XmNsingleSelectionCallback</TT>. Selecting one
item will deselect a previously selected item. If set to <TT>XmEXTENDED_SELECT</TT>,
the user will be able to select a block of contiguous items in a list. Selecting
a new item or more will deselect another previously selected item and will invoke
the <TT>XmNmultipleSelection</TT> callback. If set to <TT>XmMULTIPLE_SELECT</TT>,
the user will be able to select multiple items in any order. Selecting one item will
not deselect another previously selected item but will invoke the <TT>XmNmultipleSelection</TT>
callback. If set to <TT>XmBROWSE_SELECT</TT>, the user can move the pointer (with
the button pressed) across all the selections, but only one item will be selected.
Unlike the <TT>XmSINGLE_SELECT</TT> setting, the user does not have to press and
release the button on an item to select it. The <TT>XmbrowseSelectionCallback</TT>
will be invoked when the button is finally released on the last item browsed.<BR>
<BR>
It is easier to create the List Widget with a call to <TT>XmCreateScrolledList()</TT>
because this will automatically create a scrolled window for you. However, this method
may prove to be slow when compared to <TT>XtSetValues()</TT> calls. If you feel that
speed is important, consider using <TT>XtSetValues()</TT>. You should create the
list for the first time by using <TT>XtSetValues</TT>.</P>
<P>The following convenience functions will make working with List Widgets easier:
<TT>XmListAddItem(Widget w, XmString x, int pos)</TT></P>
<P>This will add the compound string <TT>x</TT> to the List Widget <TT>w</TT> at
the one relative position <TT>pos</TT>. If <TT>pos</TT> is 0, the item is added to
the back of the list. This function is very slow, so do not use it to create a <TT>newlist</TT>,
because it rearranges the entire list before returning.</P>
<P><TT>XmListAddItems(Widget w, XmString *x, int count, int pos);</TT></P>
<P>This will add the array of compound strings <TT>x</TT> of size <TT>count</TT>
to the List Widget <TT>w</TT> from the position <TT>pos</TT>. If <TT>pos</TT> is
0, the item is added to the back of the list. This function is slow, too, so do not
use it to create a <TT>newlist</TT>.</P>
<P><TT>XmDeleteAllItems(Widget w)</TT></P>
<P>This will delete all the items in a list. It's better to write a convenience function
to do</P>
<P><TT>n = 0; XtSetArg(arg[n], XmNitems, NULL); n++; XtSetArg(arg[n], XmNitemCount,
0); n++; XtSetValues(mylist,arg,n);</TT></P>
<P><TT>XmDeleteItem(Widget w, XmString x)</TT></P>
<P>Deletes the item <TT>x</TT> from the list. This is a slow function.</P>
<P><TT>XmDeleteItems(Widget w, XmString *x, int count)</TT></P>
<P>Deletes all the count items in <TT>x</TT> from the list. This is an even slower
function. You might be better off installing a new list.</P>
<P><TT>XmListSelectItem(Widget w, XmString x, Boolean Notify)</TT></P>
<P>Programmatically selects <TT>x</TT> in the list. If <TT>Notify</TT> is TRUE, the
appropriate callback function is also invoked.</P>
<P><TT>XmListDeselectItem(Widget w, XmString x)</TT></P>
<P>Programmatically deselects <TT>x</TT> in the list.</P>
<P><TT>XmListPos( Widget w, XmString x)</TT><BR>
<BR>
Returns the position of <TT>x</TT> in the list. Returns 0 if not found.<BR>
<BR>
Let's use the List Widget for a sample application. See Listing 34.6.
<H3 ALIGN="CENTER"><A NAME="Heading33<FONT COLOR="#000077">Listing <A NAME="Heading3434.6.
Using List Widgets.</FONT></H3>
<PRE><FONT COLOR="#0066FF">/*
** This is a typical Motif application for using a list Widget
*/
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/List.h> /*** for the list Widget ***/
#include <Xm/ScrolledW.h> /*** for the scrolled window Widget ***/
/*** Some items for the list ***/
#define NUMITEMS 8
char *groceries[NUMITEMS] = {
"milk",
"eggs",
"bread",
"pasta",
"cd-rom", /** I don't go out often!**/
"bananas",
"yogurt",
"oranges",
};
/* For the list Widget, we need compound strings */
XmString xarray[NUMITEMS];
#define USE_SCROLL
void bye(Widget w, XtPointer clientdata, XtPointer calldata);
int main(int argc, char **argv)
{
Widget top;
XtAppContext app;
Widget aForm;
Widget aList;
Widget aButton;
Arg args[15];
int i;
/**
*** Initialize the toolkit.
**/
top = XtAppInitialize(&app, "KBH", NULL, 0, (Cardinal *)&argc,
argv, NULL, args, 0);
/**
*** Create a Form on this top-level Widget. This is a nice Widget
*** to place other Widgets on top of.
**/
aForm = XtVaCreateManagedWidget("Form1",
xmFormWidgetClass, top,
XmNheight,90,
XmNwidth,200,
NULL);
/**
*** Add a button on the form you just created. Note how this Button
*** Widget is connected to the form that it resides on. Only
*** left, right, and bottom edges are attached to the form. The
*** top edge of the button is not connected to the form.
**/
aButton = XtVaCreateManagedWidget("Push to Exit",
xmPushButtonWidgetClass, aForm,
XmNheight,20,
XmNleftAttachment,XmATTACH_FORM,
XmNrightAttachment,XmATTACH_FORM,
XmNbottomAttachment,XmATTACH_FORM,
NULL);
/**
*** Now create a list of items for this Widget.
**/
for (i=0; i < NUMITEMS; i++)
xarray[i] = XmStringCreateLtoR(groceries[i],
XmSTRING_DEFAULT_CHARSET);
#ifndef USE_SCROLL
/**
*** Then create the list Widget itself. Note this will not
*** put up a scroll bar for you.
**/
aList = XtVaCreateManagedWidget("Push to Exit",
xmListWidgetClass, aForm,
XmNitemCount, NUMITEMS,
XmNitems, xarray,
XmNvisibleItemCount, 4,
XmNscrollBarDisplayPolicy, XmAS_NEEDED,
XmNleftAttachment,XmATTACH_FORM,
XmNrightAttachment,XmATTACH_FORM,
XmNtopAttachment,XmATTACH_FORM,
XmNbottomAttachment,XmATTACH_WIDGET,
XmNbottomWidget,aButton,
NULL);
#else
/**
*** Alternatively, use the scrolled window with the following code:
**/
i = 0;
XtSetArg(args[i], XmNitemCount, NUMITEMS); i++;
XtSetArg(args[i], XmNitems, xarray); i++;
XtSetArg(args[i], XmNvisibleItemCount, 4); i++;
XtSetArg(args[i], XmNscrollBarDisplayPolicy, XmAS_NEEDED); i++;
XtSetArg(ar
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -