微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

尝试将文本附加到 Xm 文本小部件时出现多线程或 Motif 小部件问题

如何解决尝试将文本附加到 Xm 文本小部件时出现多线程或 Motif 小部件问题

我正在尝试使用 TextWidget 作为日志,其中以编程方式添加文本。 通过使用 XmTextInsertXtVaSetValuesXmTextShowPosition,我可以将文本附加到文本小部件,但是我注意到只有当小部件具有焦点或滚动鼠标时才会更新文本指向文本小部件区域的指针。否则,Widget 似乎只更新了大约 5/6 秒,因此您会看到一次出现多行。

我无法确定这是与 Motif 相关的问题还是纯粹的 X11/Xt/Xm 多线程问题,但很明显附加的代码缺少相关内容

例如,此源代码只有 TextWidget,并且更新工作正常,即使焦点在另一个应用程序中,每秒钟您都会看到一个新的 TEST 字添加到 Text Widget:

#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Text.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void displayMessage(char *textLineBuffer);
void createWindow(int argc,char *argv[]);
void *logText(void *arg);

/* X11 RELATED VARIABLES */
XtAppContext    context;

Widget          toplevel;
Widget          busForm;
Widget          textWidget;
pthread_mutex_t textWidgetMutex;
long            textWidgetLength = 0;

int main(int argc,char *argv[]) {

        pthread_t       thread;

        /* INITIALIZE MULTITHREAD X11 ENVIRONMENT */
        XInitThreads();

        /* CREATE X WINDOW */
        createWindow(argc,argv);

        /* GET NEW THREAD TO PROCESS QUEUES */
        /* PARENTS HANDLES X11 */
        pthread_create(&thread,NULL,logText,NULL);

        /* BEGIN X11 APPLICATION */
        XtAppMainLoop(context);

}

void *logText(void *arg) {

        /* READ CLIENT QUEUE MESSAGES */
        while(1) {
                sleep(1);
                displayMessage("TEST\n");
        }

}

void createWindow(int argc,char *argv[]){

        Arg             al[10];
        int             ac;
        xmstringCharSet char_set = xmsTRING_DEFAULT_CHARSET;
        char            pidString[50];

        /* CREATE TOP LEVEL */
        sprintf(pidString,"Bus Client %d",getpid());
        toplevel = XtAppInitialize(&context,pidString,&argc,argv,0);

        /* RESIZE TOP LEVEL */
        ac = 0;
        XtSetArg(al[ac],XmNwidth,300); ac++;
        XtSetArg(al[ac],XmNheight,300); ac++;
        XtSetValues(toplevel,al,ac);

        /* CREATE TOP LEVEL FORM MANAGER */
        ac = 0;
        busForm  = XmCreateForm(toplevel,"busForm",ac);
        XtManageChild(busForm);

        /* CREATE TEXT WIDGET */
        ac = 0;
        XtSetArg(al[ac],XmNtopAttachment,XmATTACH_FORM); ac++;
        XtSetArg(al[ac],XmNleftAttachment,XmNrightAttachment,XmNbottomAttachment,XmNeditMode,XmMULTI_LINE_EDIT); ac++;
        XtSetArg(al[ac],XmNscrollingPolicy,XmVARIABLE); ac++;
        XtSetArg(al[ac],XmNscrollBardisplayPolicy,xmsTATIC); ac++;
        XtSetArg(al[ac],XmNscrollHorizontal,FALSE); ac++;
        XtSetArg(al[ac],XmNeditable,FALSE); ac++;
        textWidget = XmCreateScrolledText(busForm,"textWidget",ac);
        XtManageChild(textWidget);

        /* disPLAY TOP LEVEL */
        XtRealizeWidget(toplevel);
}

void displayMessage(char *textLineBuffer) {
        pthread_mutex_lock(&textWidgetMutex);
        XmTextInsert(textWidget,textWidgetLength,textLineBuffer); 
        textWidgetLength += strlen(textLineBuffer);
        XtVaSetValues(textWidget,XmNcursorPosition,NULL);
        XmTextShowPosition(textWidget,textWidgetLength);
        pthread_mutex_unlock(&textWidgetMutex);
}

输出所示,即使窗口没有焦点,消息也会持续显示

Test2

但是,如果添加按钮,当 Motif 应用程序中的焦点在 Button Widget 中时,文本不会更新,直到鼠标滚过 Text Widget。如果您单击“文本小部件”,则文本会像前面的示例一样在那里不断更新。

这是源代码和相应的例子。

#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/Text.h>
#include <Xm/PushB.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <unistd.h>

void displayMessage(char *textLineBuffer);
void createWindow(int argc,char *argv[]);
void sendButtonCB(Widget w,XtPointer  client_data,XtPointer call_data);
void *logText(void *arg);

/* X11 RELATED VARIABLES */
XtAppContext    context;

Widget          toplevel;
Widget          busForm;
Widget          textWidget;
Widget          registerButton;
Widget          sendButton;
pthread_mutex_t textWidgetMutex;
long            textWidgetLength = 0;

/* BUS CLIENT SYS V QUEUE VARIABLES */
int client_queue_id;
key_t client_queue_key;
int client_message_id;

int main(int argc,ac);
        XtManageChild(busForm);

        /* CREATE SEND BUTTON WIDGET */
        ac = 0;
        XtSetArg(al[ac],XmATTACH_NONE); ac++;
        XtSetArg(al[ac],XmNlabelString,xmstringCreateLtoR("Send",char_set)); ac++;
        sendButton = XmCreatePushButton(busForm,"sendButton",ac);
        XtManageChild(sendButton);
        XtAddCallback(sendButton,XmNactivateCallback,sendButtonCB,NULL); 

        /* CREATE TEXT WIDGET */
        ac = 0;
        XtSetArg(al[ac],XmATTACH_WIDGET); ac++;
        XtSetArg(al[ac],XmNtopWidget,registerButton); ac++;
        XtSetArg(al[ac],textWidgetLength);
        pthread_mutex_unlock(&textWidgetMutex);
}

Motif Test 2

解决方法

我刚刚发现:

void displayMessage(char *textLineBuffer) {
        pthread_mutex_lock(&textWidgetMutex);
        XmTextInsert(textWidget,textWidgetLength,textLineBuffer); 
        textWidgetLength += strlen(textLineBuffer);
        XmUpdateDisplay(textWidget);
        pthread_mutex_unlock(&textWidgetMutex);
}

强制小部件重绘。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。