You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xlib调用XDrawRectangle与XFillRectangle无绘制效果问题排查

问题分析与解决

核心原因

你调用XDrawRectangle()和XFillRectangle()的时机存在问题:在XMapWindow()之后,窗口尚未完成初始化,X服务器会发送Expose事件触发窗口重绘背景,这会直接覆盖你提前绘制的内容。而原程序的完整事件循环能正常工作,正是因为它在处理Expose事件时重新执行了绘制逻辑。

修复步骤

1. 修正窗口事件掩码

在create_win函数中,给XSetWindowAttributes添加event_mask配置,让窗口能够接收Expose事件:

XSetWindowAttributes xwa = 
{
    .background_pixel = WhitePixel(dpy, scr),
    .border_pixel = BlackPixel(dpy, scr),
    .event_mask = ExposureMask, // 添加该行,开启Expose事件接收
};

2. 在事件循环中处理Expose事件

修改主函数的事件循环,当收到Expose事件时执行绘制操作,确保窗口每次需要重绘时都能重新渲染矩形:

XEvent ev;
while (XNextEvent(dpy, &ev)) {
    if (ev.type == Expose) {
        XDrawRectangle(dpy, main_win, gc, 0, 0, 100, 100);
        XFillRectangle(dpy, main_win, gc, 0, 0, 100, 100);
    }
}

3. 修正GC创建的掩码问题

你的create_gc函数中,valuemask包含了GCLineStyle、GCCapStyle、GCJoinStyle,但XGCValues中并未设置这些属性,可能导致GC属性异常。可以去掉这些未配置的掩码:

valuemask = GCForeground | GCBackground | GCFillStyle | GCLineWidth;

完整修复后的代码

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

static Display *dpy;
static int scr;
static Window root;
static Visual *vis;

static Window create_win(int x, int y, int w, int h, int b)
{
    Window win;
    XSetWindowAttributes xwa = 
    {
        .background_pixel = WhitePixel(dpy, scr),
        .border_pixel = BlackPixel(dpy, scr),
        .event_mask = ExposureMask,
    };

    win = XCreateWindow(dpy, root, x, y, w, h, b, DefaultDepth(dpy, scr), InputOutput, vis, CWBackPixel | CWBorderPixel | CWEventMask, &xwa);
    return win;
}

static GC create_gc()
{
    GC gc;
    XGCValues xgcv;
    unsigned long valuemask;

    xgcv.line_width = 4;
    xgcv.fill_style = FillSolid;
    xgcv.foreground = BlackPixel(dpy, scr);
    xgcv.background = WhitePixel(dpy, scr);

    valuemask = GCForeground | GCBackground | GCFillStyle | GCLineWidth;
    gc = XCreateGC(dpy, root, valuemask, &xgcv);

    return gc;
}

int main()
{
    Window main_win;
    GC gc;
    
    dpy = XOpenDisplay(NULL);

    scr = DefaultScreen(dpy);
    root = RootWindow(dpy, scr);
    vis = DefaultVisual(dpy, scr);
    main_win = create_win(0, 0, 200, 200, 5);
    
    gc = create_gc();
    
    XMapWindow(dpy, main_win);
    
    XEvent ev;
    while (XNextEvent(dpy, &ev)) {
        if (ev.type == Expose) {
            XDrawRectangle(dpy, main_win, gc, 0, 0, 100, 100);
            XFillRectangle(dpy, main_win, gc, 0, 0, 100, 100);
        }
    }

    XUnmapWindow(dpy, main_win);
    XDestroyWindow(dpy, main_win);
    XFreeGC(dpy, gc);
    XCloseDisplay(dpy);
    
    return 0;
}

编译运行

依旧使用原编译命令:

gcc -o paint paint.c -lX11

运行后即可看到窗口内正常显示的黑色矩形。

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:13:24