【问题标题】:Horizontally-Drawn RowColumn Class for Motif Library (C)?用于 Motif 库(C)的水平绘制的 RowColumn 类?
【发布时间】:2020-04-17 21:53:01
【问题描述】:

我正在使用 Motif 库来完成我的工作。如果有人不熟悉这个库,你可以在https://packages.ubuntu.com/xenial/amd64/libmotif-dev/filelist 找到文件列表,以及在Motif 1.2 X11 on using RowColumn widget inside a ScrolledWindow 找到另一个问题。

我的问题是 xmRowColumnWidgetClass 是垂直绘制的,这意味着它逐列绘制(从左上角开始移动到左下角,然后向右移动到下一列,等等)

做这样的事情:

Widget parentWidget, rowColumn;

XtAppContext app;

parentWidget = XtVaAppInitialize(&app, "rowColumn", NULL, 0,
&argc, argv, NULL, NULL);

然后像这样:

rowColumn = XtVaCreateManagedWidget("rowcolumn",
            xmRowColumnWidgetClass,
            parentWidget,
            XmNnumColumns, 3,
            XmNpacking, XmPACK_COLUMN,
            XmNspacing, 6,
            NULL);

(void) XtVaCreateManagedWidget("button 1",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 2",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 3",
xmPushButtonWidgetClass, rowColumn, NULL);
        
(void) XtVaCreateManagedWidget("button 4",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 5",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 6",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 7",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 8",
xmPushButtonWidgetClass, rowColumn, NULL);

(void) XtVaCreateManagedWidget("button 9",
xmPushButtonWidgetClass, rowColumn, NULL);

所以上面的代码会像这样创建小部件:

button 1    button 4    button 7

button 2    button 5    button 8

button 3    button 6    button 9

我的问题是我希望某些并排而不是上下。

假设作为一种解决方法,我指定了这样的顺序:按钮 1、按钮 4、按钮 7、按钮 2、按钮 5、按钮 8、按钮 3、按钮 6、按钮 9。看起来像这样:

button 1    button 2    button 3

button 4    button 5    button 6

button 7    button 8    button 9

但是,如果我想删除一个按钮或添加一个新按钮,这会搞砸一切。假设我从上面的示例中删除了“按钮 4”,因此顺序如下:按钮 1、按钮 7、按钮 2、按钮 5、按钮 8、按钮 3、按钮 6、按钮 9。看起来像这样:

button 1    button 5    button 6

button 7    button 8    button 9

button 2    button 3

如您所见,现在几乎所有应该并排并排的东西现在都没有了。

添加新按钮时也会出现此问题:假设我们要在末尾添加按钮 10:按钮 1、按钮 4、按钮 7、按钮 2、按钮 5、按钮 8、按钮 3、按钮 6 ,按钮 9,按钮 10。如下所示:

button 1    button 5    button 9

button 4    button 8    button 10

button 7    button 3

button 2    button 6

到目前为止,这看起来最糟糕,因为添加一个新按钮会将行的法线增加到 4 而不是 3,这会改变整个布局。


致任何熟悉这个库的人:

如何创建水平(逐行)而不是垂直绘制的 xmRowColumnWidgetClass 实例? (逐列)

或者,我如何扩展这个库并可能创建一个 xmHorRowColumnWidgetClass 来满足我的需求?


该库的另一组示例:
https://github.com/spartrekus/Motif-C-Examples
https://github.com/spartrekus/Motif-C-Examples/blob/master/rowcol.c

【问题讨论】:

  • 您找到解决方案了吗?我和你的情况一样:我需要一个水平排列的 RowColumn 并限制列数。奇怪的是,RowColumn 小部件无法做到这一点(并且 XmForm 不可比:您需要手动提供约束,而 RowColumn 会自动调整自身大小以适应子级所需的严格大小,而无需任何手动约束)。
  • 我找到了 RowColumn 的替代小部件,这对我的目的来说很好。我会将其发布为您其他问题的答案。

标签: c++ c linux drawing


【解决方案1】:

使用XmForm 类,并玩弄附在孩子身上的受限资源。您可以在子级中生成XmATTACH_POSITION,并在表单中设置一个网格,使其(网格)随着父级调整大小而拉伸和压缩。例如,您可以将子项的四个边框附加到覆盖父 (XmForm) 小部件的 4x3 单元假想网格,并将子项附加到父项中的固定位置,因此如果删除其中一个,则孔不会被填充由邻居小部件。请参阅XmForm 的文档,恕我直言,您应该使用该小部件。

keypad.c

下面有一个简单的小键盘示例,使用XmForm 来说明如何初始化资源。它显示了要触摸的最少硬连线资源。

/* main.c -- main program to create a keypad with an XmForm
                         widget.
 * Author: Luis Colorado <luiscoloradourcola@gmail.com>
 * Date: Tue Apr 21 16:15:28 EEST 2020
 * Copyright: (C) 2020 Luis Colorado.  All rights reserved.
 * License: BSD.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/PushBG.h>

#define F(_fmt) __FILE__":%d:%s: " _fmt, __LINE__, __func__

/* XmForm has a coordinate set based on a common denominator
 * that it applies to x and y coordinates, in order to subdivide
 * the grid (that has the same subdivisions along the x axis, as
 * it has along the y axis, so in order to make a 4x3 grid we
 * calculate the MCM(3, 4) = 12 to use as the denominator to
 * divide the x and y sides of it.  This makes the coordinates 
 * to go as the drawing marks.
 *      0   4   8  12
 *      +---+---+---+  0
 *      | 1 | 2 | 3 |
 *      +---+---+---+  3
 *      | 4 | 5 | 6 |
 *      *---+---+---+  6
 *      | 7 | 8 | 9 |
 *      +---+---+---+  9
 *      | * | 0 | # |
 *      +---+---+---+ 12
 */

struct but_desc {
        int left_x, top_y;
        int right_x, bot_y;
        char *name;
        char *out;
        void (*cb)(Widget, XtPointer, XtPointer);
};

void callback(Widget w, XtPointer data, XtPointer cd);

static struct but_desc
pos_tab[] = {
    { 4, 9,  8, 12, "b0",        "0", callback, },
        { 0, 0,  4,  3, "b1",        "1", callback, },
        { 4, 0,  8,  3, "b2",        "2", callback, },
        { 8, 0, 12,  3, "b3",        "3", callback, },
        { 0, 3,  4,  6, "b4",        "4", callback, },
        { 4, 3,  8,  6, "b5",        "5", callback, },
        { 8, 3, 12,  6, "b6",        "6", callback, },
        { 0, 6,  4,  9, "b7",        "7", callback, },
        { 4, 6,  8,  9, "b8",        "8", callback, },
        { 8, 6, 12,  9, "b9",        "9", callback, },
        { 8, 9, 12, 12, "bhash",     "#", callback, },
        { 0, 9,  4, 12, "basterisk", "*", callback, },
        { 0, 0,  0,  0, NULL, NULL, },
};

int
main(int argc, char **argv)
{
        XtAppContext app_ctx;
        char *class_name = "XKeypad";

        Widget topLevel = XtVaAppInitialize(
                &app_ctx,
                class_name,
                NULL, 0, /* XrmOptionDescRec array */
                &argc, argv, /* args to main */
                NULL, /* default resources */
                NULL); /* empty list of arguments */

        if (!topLevel) {
                fprintf(stderr,
                F("Couldnt create main widget"));
                exit(EXIT_FAILURE);
        }

        char *form_name = "form";
        Widget form = XtVaCreateManagedWidget(
        form_name,
                xmFormWidgetClass,
                topLevel,
                XmNfractionBase, 12,
                NULL);

        if (!form) {
                fprintf(stderr,
                        F("Couldn't create form '%s'\n"),
                        form_name);
                exit(EXIT_FAILURE);
        }

        struct but_desc *p;
        for (p = pos_tab; p->name; ++p) {
                printf(F("Creando botón '%s'@{(%d,%d),(%d,%d)}\n"),
                        p->name, p->left_x, p->top_y, p->right_x, p->bot_y);
                Widget button =
                        XtVaCreateManagedWidget(
                                        p->name,
                                        xmPushButtonGadgetClass,
                                        form,
                                        XmNleftAttachment, XmATTACH_POSITION,
                                        XmNrightAttachment, XmATTACH_POSITION,
                                        XmNtopAttachment, XmATTACH_POSITION,
                                        XmNbottomAttachment, XmATTACH_POSITION,
                                        XmNleftPosition, p->left_x,
                                        XmNrightPosition, p->right_x,
                                        XmNtopPosition, p->top_y,
                                        XmNbottomPosition, p->bot_y,
                                        NULL, NULL);
                if (!button) {
                        fprintf(stderr,
                                F("Couldnt create button '%s'\n"),
                                p->name);
                        exit(EXIT_FAILURE);
                }
                XtAddCallback(button, XmNactivateCallback, p->cb, p);
        }

        XtRealizeWidget(topLevel);
        XtAppMainLoop(app_ctx);

} /* main */

void callback(Widget w, XtPointer p, XtPointer cd)
{
        struct but_desc *data = p;
        write(1, data->out, strlen(data->out));
}

我在下面的示例代码中添加了this repository。存储库包括一个Makefile 和一个默认资源文件 (XKeypad)。

【讨论】:

  • 你能举个例子,或者伪代码吗?
  • 我有一些。一个向您显示屏幕数字键盘(在 4x3 矩阵上),另一个允许您玩扫雷。但是它们是在git 时代之前写的,我不知道它们在哪里。给我一些时间,我会给你一个例子(电话键盘可以是一个说明性的例子)
  • @overlord,这里有您要求的示例代码。祝你好运。
【解决方案2】:

要使 xmRowColumnWidgetClass 实例水平绘制,请在代码中添加XmNorientation, XmHORIZONTAL

rowColumn = XtVaCreateManagedWidget("rowcolumn",
            xmRowColumnWidgetClass,
            parentWidget,
            XmNnumColumns, 3,
            XmNorientation, XmHORIZONTAL,
            XmNpacking, XmPACK_COLUMN,
            XmNspacing, 6,
            NULL);

这使它逐行而不是逐列绘制。

由于某种原因,XmNnumColumns 现在指的是行数而不是列数,但这是一个单独的问题,因此上面的代码确实回答了我原来的问题。

【讨论】:

    猜你喜欢
    • 2020-08-03
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 2016-01-27
    相关资源
    最近更新 更多