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

时间:2021-01-30 09:29:33

标签: c multithreading x11 toolkit 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, NULL, 0, &argc, argv, NULL, NULL, 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", al, ac);
        XtManageChild(busForm);

        /* CREATE TEXT WIDGET */
        ac = 0;
        XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], 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", al, 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, textWidgetLength, 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, 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, NULL, 0, &argc, argv, NULL, NULL, 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", al, ac);
        XtManageChild(busForm);

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

        /* CREATE TEXT WIDGET */
        ac = 0;
        XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
        XtSetArg(al[ac], XmNtopWidget, registerButton); ac++;
        XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
        XtSetArg(al[ac], 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", al, 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, textWidgetLength, NULL);
        XmTextShowPosition(textWidget, textWidgetLength);
        pthread_mutex_unlock(&textWidgetMutex);
}

Motif Test 2

1 个答案:

答案 0 :(得分:0)

我刚刚发现:

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

强制小部件重绘。

相关问题