【问题标题】:How do I draw a string to a window with a C program including X11/Xlib.h?如何使用包括 X11/Xlib.h 的 C 程序将字符串绘制到窗口?
【发布时间】:2020-06-04 16:15:59
【问题描述】:

我正在尝试使用 X11/Xlib 创建一个 Hello World 程序,但是当我调用 XDrawString() 时,它不会绘制“Hello world!”在窗口中。我需要改变什么才能做到这一点?

编辑: 我的完整代码如下。当问题描述是“主要是代码”时,StackOverflow 不会让我提交问题,所以我还将在代码下方解释程序打算做什么。

代码:

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    //Open default display
    Display *display = XOpenDisplay(NULL);
    if(display != NULL)
    {
        //Get default screen
        Screen *screen = DefaultScreenOfDisplay(display);
        if(screen != NULL)
        {
            //Initialize window
            Window window = XCreateSimpleWindow(display, RootWindowOfScreen(screen), 0, 0, WidthOfScreen(screen), HeightOfScreen(screen), 0, BlackPixelOfScreen(screen), BlackPixelOfScreen(screen));
            XSelectInput(display, window, KeyPressMask || ExposureMask);
            XStoreName(display, window, "Hello World!");
            XMapRaised(display, window);

            //Initialize graphics context
            GC graphics_context = DefaultGCOfScreen(screen);

            //Event handling loop
            XEvent event;
            while(1)
            {
                XNextEvent(display, &event);
                if(event.type == KeyPress)
                {
                    //KeyPress event
                    if(event.xkey.keycode == XKeysymToKeycode(display, XK_Escape))
                    {
                        XDestroyWindow(display, window);
                        XCloseDisplay(display);
                        exit(EXIT_SUCCESS);
                    }
                }
                else if(event.type == Expose)
                {
                    //Expose event (window is visible)
                    char *msg = "Hello world!";
                    XDrawString(display, window, DefaultGCOfScreen(screen), 0, 0, msg, strlen(msg));
                }
            }
            XDestroyWindow(display, window);
        }
        XCloseDisplay(display);
    }
    exit(EXIT_FAILURE);
}

此代码旨在

  • 打开默认显示;

  • 获取此显示器的默认屏幕

  • 在默认显示上创建一个简单窗口作为屏幕根窗口的子窗口,x 和 y 归零,宽度和高度分别等于屏幕的默认宽度和高度,0 宽度边框,边框和窗口背景都用屏幕黑色像素的颜色着色

  • 选择曝光事件和按键作为窗口接受的输入

  • 存储名称“Hello World!”在窗口中

  • 映射并升起窗口

  • 获取屏幕的默认图形上下文

  • 在无限循环中处理事件,当用户按下 Escape 键或绘制“Hello world!”时以成功状态退出到窗口曝光窗口

  • 如果打开显示器失败或显示器默认屏幕为NULL,则以失败状态退出

【问题讨论】:

  • 请张贴所有代码,以便我们重现您正在做的事情。你有类似geeks3d.com/20120102/… 的东西吗?
  • @pifor 我最初尝试将我使用的所有代码添加到描述中,但 StackOverflow 阻止我这样做,因为我的问题是“主要是代码”。我可以尝试编辑问题描述以添加我正在使用的所有代码并更彻底地注释它
  • @pifor 我已经提交了所有代码

标签: c x11


【解决方案1】:

你需要打电话给XFlush,你应该关心X11坐标。

查看简单的 GUI 工具包的源代码,例如 FLTK。或许使用ltrace(1)gdb(1) 来了解他们的行为。使用

从源代码编译 FLTK
./configure 'CXX=g++' 'CXXFLAGS=-O2 -g1' --with-abiversion \
           --enable-x11 --enable-shared

然后观察(使用gdbltrace)运行时简单测试示例的行为。

另请参阅 thisthat

【讨论】:

  • 我在调用XNextEvent(display, &amp;event) 后尝试调用XFlush(display),但字符串仍未绘制。此外,如果输入缓冲区为空,显然XNextEvent 显然已经刷新了输出缓冲区。我会尝试跟踪一个 GUI 工具包
【解决方案2】:

为您的应用创建一个新的 GC 会更好。它必须具有相同的深度,并且您必须加载字体。 您可以阅读thisthis,它们都解释了如何绘制文本。

this 其他页面您有示例代码:

black=BlackPixel(display,screen),   /* get color black */
white=WhitePixel(display, screen);  /* get color white */

/* create the Graphics Context */
gc=XCreateGC(display, window, 0,0);        

/* here is another routine to set the foreground and background
   colors _currently_ in use in the window.
*/
XSetBackground(display,gc,white);
XSetForeground(display,gc,black);

XDrawString(display,window,gc,x,y, string, strlen(string));

您应该考虑到 x,y 坐标是字体基线,您必须添加字体的上升或下降。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    相关资源
    最近更新 更多