简体   繁体   English

不可能在 XtAddCallback 中将 Motif 小部件数组作为 client_data 传递?

[英]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.大家好,我得到的是一个非常简化的真实程序片段,它必须更新 4500 万个 Motif 标签小部件中的标签字符串。 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.我将这两个小部件放入标准 C 数组中,并将其作为 client_data 传递给使用 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.我假设无论出于何种原因,应该具有两个小部件数组的 client_data(一个 XtPointer)实际上只有第一个小部件。 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.我完全意识到我可以从作为 XtAddCallback 中的第一个参数传入的父小部件访问标签小部件,然后使用 XtNameToWidget 来获取标签,但这需要对 XtNameToWidget 进行 4500 万次调用,我宁愿避免。 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.另一件奇怪的事情是,如果没有第二个小部件,我会认为在其上调用 XtSetValues 会使程序崩溃,但事实并非如此。 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所以,如果有人有兴趣看看这个(可疑),这是简化的片段,如果你将它命名为 arrays.c,它会使用 gcc -lXm -lXt -lX11 -o arrays arrays.c 编译(至少在 Linux 上) - 哦,由于无法解释的原因,我被迫使用 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 is exactly the same as label_widgets[0] which in your case is exactly the same as label_01 . *label_widgetslabel_widgets[0]完全相同,在您的情况下与label_01 You are passing label_01 as your callback argument.您将label_01作为回调参数传递。 It has type Widget .它有Widget类型。

 Widget (*label_widgets)[2] = (Widget (*)[2])client_data;

label_widgets is now a pointer to a 2-element array of Widget , which is very different from Widget you have passed as the argument. label_widgets现在是指向Widget的 2 元素数组的指针,这与您作为参数传递的Widget非常不同。

 XtVaSetValues(*label_widgets[i], XmNlabelString, text, NULL);

*label_widgets[i] is the same as label_widgets[i][0] . *label_widgets[i]label_widgets[i][0]相同。 Since label_widgets is a pointer (see above), it is taken as a pointer to the first element of an array.由于label_widgets是一个指针(见上文),它被视为指向数组第一个元素的指针。 An array of what?什么数组? Of two-element arrays or Widget .二元素数组或Widget So it takes the i th element of that array, which happens to be a 2-element array of Widget , and takes the 0 ths widget of that.因此,它采用该数组的第i个元素,恰好是Widget的 2 元素数组,并采用其中的第0个小部件。 Needles to say, there is no array of arrays of Widget anywhere, so this code just wanders off to the La-La Land.不用说,任何地方都没有Widget数组的数组,所以这段代码只是飘到了 La-La Land。

You want this:你要这个:

Pass a pointer to the first element of label_widgets .将指针传递给label_widgets的第一个元素。 Look up array-to-pointer decay for more info.查找数组到指针衰减以获取更多信息。

XtAddCallback(button, XmNactivateCallback, pass_array_cb, label_widgets);

Receive a pointer to the first element of an array of Widget .接收指向Widget数组的第一个元素的指针。

Widget* label_widgets = (Widget*)client_data;

Index into the aforementioned array using a pointer to its first element (all array indexing works this way).使用指向其第一个元素的指针对上述数组进行索引(所有数组索引都以这种方式工作)。

XtVaSetValues(label_widgets[i], XmNlabelString, text, NULL);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM