arrays - Solved: Impossible to pass a Motif widget array as client_data in XtAddCallback?
问题描述
Greets all, what I've got is a much simplified snippet of a real program that has to update the label strings in 45 million Motif label widgets. Simplified version: I create two label widgets and set their label strings to "text." I place the two widgets into a standard C array and pass it as client_data to a callback function using XtAddCallback. The callback is invoked by a pushbutton and it's supposed to change the label strings from "text" to "different text," but it only changes the string in the first label widget. I'm assuming that for whatever reason the client_data (an XtPointer) that's supposed to have the two widget array actually only has the first widget. I realize full well that I could access the label widgets from the parent widget that's passed in as the first parameter in XtAddCallback, then use XtNameToWidget to get the labels, but that would entail 45 million calls to XtNameToWidget, which I'd rather avoid. I also realize I could put the all the label widgets into a global array, and then index over the array to change the label strings, but globals are also something I'd rather avoid. Another thing that's weird, if there is no second widget I would have thought that calling XtSetValues on it would crash the program, but it doesn't. So, if anyone's interested in taking a look at this (doubtful), here's the simplified snippet, if you name it arrays.c, it compiles (at least on Linux) with gcc -lXm -lXt -lX11 -o arrays arrays.c - Oh and for reasons that defy logical explanation, I'm being forced to use Motif-2.1.32
/* Impossible to pass a widget array using XtAddCallback? */
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <stdio.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
void pass_array_cb(Widget, XtPointer, XtPointer);
int main(int argc, char * argv[])
{
XtAppContext app_context;
XmString text;
Widget toplevel;
Widget form, button, label_01, label_02;
Arg av[10];
int ac = 0;
toplevel = XtOpenApplication(
&app_context,
"arrays",
NULL,
0,
&argc,
argv,
NULL,
applicationShellWidgetClass,
av,
ac);
form = XtVaCreateManagedWidget("form",
xmFormWidgetClass, toplevel,
XmNheight, 100,
XmNwidth, 200,
NULL);
text = XmStringCreateLocalized((char *) "text");
label_01 = XtVaCreateManagedWidget("label_01",
xmLabelWidgetClass, form,
XmNwidth, 60,
XmNheight, 20,
XmNlabelString, text,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, toplevel,
NULL);
label_02 = XtVaCreateManagedWidget("label_02",
xmLabelWidgetClass, form,
XmNwidth, 60,
XmNheight, 20,
XmNlabelString, text,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, label_01,
NULL);
XmStringFree(text);
Widget label_widgets[2] = { label_01, label_02 };
button = XtVaCreateManagedWidget("button",
xmPushButtonWidgetClass, form,
XmNwidth, 60,
XmNheight, 20,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, label_02,
NULL);
XtAddCallback(button, XmNactivateCallback, pass_array_cb, *label_widgets);
XtRealizeWidget (toplevel);
XtAppMainLoop (app_context);
return 0;
}
void pass_array_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
Widget (*label_widgets)[2] = (Widget (*)[2])client_data;
XmString text = XmStringCreateLocalized((char *)"different text");
int i;
for(i = 0; i < 2; i++)
{
printf("in the callback, widget index is %d\n", i);
XtVaSetValues(*label_widgets[i], XmNlabelString, text, NULL);
}
XmStringFree(text);
}
解决方案
XtAddCallback(button, XmNactivateCallback, pass_array_cb, *label_widgets);
*label_widgets
与label_widgets[0]
您的情况完全相同,与label_01
. 您label_01
作为回调参数传递。它有类型Widget
。
Widget (*label_widgets)[2] = (Widget (*)[2])client_data;
label_widgets
现在是指向 2 元素数组的指针Widget
,这与您作为参数传递的非常不同。Widget
XtVaSetValues(*label_widgets[i], XmNlabelString, text, NULL);
*label_widgets[i]
是一样的label_widgets[i][0]
。由于label_widgets
是一个指针(见上文),它被视为指向数组第一个元素的指针。什么数组?二元素数组或Widget
. 因此,它采用该i
数组的第 th 个元素,它恰好是 的 2 元素数组Widget
,并采用该0
ths 小部件。不用说,任何地方都没有数组Widget
,所以这段代码只是徘徊到 La-La Land。
你要这个:
传递指向 的第一个元素的指针label_widgets
。查找数组到指针衰减以获取更多信息。
XtAddCallback(button, XmNactivateCallback, pass_array_cb, label_widgets);
接收指向数组的第一个元素的指针Widget
。
Widget* label_widgets = (Widget*)client_data;
使用指向其第一个元素的指针对上述数组进行索引(所有数组索引都以这种方式工作)。
XtVaSetValues(label_widgets[i], XmNlabelString, text, NULL);
推荐阅读
- mongodb - 使用 MongoDB API 的 CosmosDB 数据库级吞吐量不再需要分片集合?
- scala - Spark UI 在尝试创建动态数据框时卡住了
- jquery - ajax/jquery 抛出错误时等待 x 秒
- python - 如何在熊猫数据框的单列中的行上应用函数?
- xml - xpath 的 text() 不返回自定义实体
- vim - 如何同时转到vim中所有拆分文件的结尾?
- vagrantfile - 消息:未定义的方法''
- sql - T-SQL 检查文件是否存在
- go - YAML Unmarshal map[string]struct
- c# - 我正在尝试读取我创建的文本文件中的最后一行,并在程序退出之前将最后一行添加到我的文件名中