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
相关产品推荐
相关产品推荐

