【发布时间】:2015-12-20 15:51:21
【问题描述】:
我正在用 C++ 中的 cairo 和 xlib 进行一些编程,我的代码如下所示。
我遇到了一些闪烁的问题,但是通过修改我的代码,现在总体上看起来效果很好。
但是,当窗口调整为 小尺寸(我的笔记本电脑上约为 600x450)时,它仍然闪烁。
我该如何解决?
#include <cairo.h>
#include <cairo-xlib.h>
#include <string>
#include <cstdio>
using namespace std;
int main (int argc, char *argv[])
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create (surface);
/* Examples are in 1.0 x
* 1.0 coordinate space */
cairo_scale (cr, 800, 600);
cairo_set_source_rgb (cr, 1.0, 0, 0);
cairo_rectangle (cr, 0, 0, 1.0, 1.0);
cairo_fill(cr);
cairo_destroy(cr);
Display *display = XOpenDisplay(NULL);
int default_scr = DefaultScreen(display);
Visual *visual = DefaultVisual(display, default_scr);
Window root_win = RootWindow(display, default_scr);
Drawable drawable = XCreateSimpleWindow(display, root_win, 0, 0, 800, 600, 0,
BlackPixel(display, default_scr), WhitePixel(display, default_scr));
cairo_surface_t *x11_sf = cairo_xlib_surface_create(display, drawable, visual, 800, 600);
XSelectInput(display, drawable, ExposureMask | StructureNotifyMask);
XMapWindow(display, drawable);
XFlush(display);
XSync(display, default_scr);
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, drawable, &wmDeleteMessage, 1);
int height;
int width;
XEvent event;
bool running = true;
while (running)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
{
cairo_t *x11_cr = cairo_create(x11_sf);
cairo_scale(x11_cr, double(width) / 800, double(height) / 600);
cairo_set_source_surface(x11_cr, surface, 0, 0);
cairo_paint(x11_cr);
cairo_destroy (x11_cr);
}
break;
case ClientMessage:
if (event.xclient.data.l[0] == wmDeleteMessage)
{
running = false;
}
break;
case ConfigureNotify:
width = event.xconfigure.width;
height = event.xconfigure.height;
cairo_xlib_surface_set_size(x11_sf, width, height);
break;
}
}
cairo_surface_destroy (surface);
return 0;
}
我使用cairo_xlib_surface 来绘制一个窗口,它具有整个红色背景色。我试图捕捉XExpose 事件并重绘它。但有时重绘结果会很奇怪。
#include <cairo.h>
#include <cairo-xlib.h>
#include <string>
#include <cstdio>
using namespace std;
int main (int argc, char *argv[])
{
cairo_surface_t *surface;
cairo_t *cr;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create (surface);
/* Examples are in 1.0 x 1.0 coordinate space */
cairo_scale (cr, 800, 600);
/* Drawing code goes here */
cairo_set_source_rgb (cr, 1.0, 0, 0);
cairo_rectangle (cr, 0, 0, 1.0, 1.0);
cairo_fill(cr);
Display *display = XOpenDisplay(NULL);
int default_scr = DefaultScreen(display);
Visual *visual = DefaultVisual(display, default_scr);
Window root_win = RootWindow(display, default_scr);
Drawable drawable = XCreateSimpleWindow(display, root_win, 0, 0, 800, 600, 0,
BlackPixel(display, default_scr), WhitePixel(display, default_scr));
XSelectInput(display, drawable, ExposureMask);
XMapWindow(display, drawable);
XFlush(display);
XSync(display, default_scr);
int height;
int width;
XEvent event;
while (1)
{
XNextEvent(display, &event);
switch (event.type)
{
case Expose:
{
width = event.xexpose.width;
height = event.xexpose.height;
cairo_surface_t *x11_sf = cairo_xlib_surface_create(display, drawable, visual, width, height);
cairo_t *x11_cr = cairo_create(x11_sf);
cairo_scale(x11_cr, double(width) / 800, double(height) / 600);
cairo_set_source_surface(x11_cr, surface, 0, 0);
cairo_paint(x11_cr);
cairo_destroy (x11_cr);
cairo_surface_destroy (x11_sf);
}
break;
}
}
/* Write output and clean up */
cairo_destroy (cr);
cairo_surface_destroy (surface);
return 0;
}
红色背景好像还没画完。
有人能告诉我为什么会发生这种情况以及如何避免吗?
如果有人想在Linux下编译,可以使用:g++ \pkg-config --cflags --libs x11 cairo\src.cpp
谢谢!
【问题讨论】:
-
是否故意将暴露的宽度和高度作为窗口大小提供给 cairo_xlib_surface_create()?你为什么不使用窗口的实际大小呢?在您的情况下,最初是 800x600 并且当您的窗口调整大小时,您必须捕获告诉您它的 ConfigureNotify 并使用 cairo_xlib_surface_set_size()。这个信息真的是你想要的吗?如果不是,我不明白你的问题。
-
感谢您的回复。你的建议确实有效。但是当窗口尺寸较小(低于 600x450)时,重绘过程仍然会出现问题。我修改了我的代码。我错过了其他一点吗? THX
-
我测试了一些案例,发现当我创建的'surface'为100x100时,闪烁消失了。但是,那么表面是 1x1,结果 x11 窗口有一个奇怪的背景。
-
使用 XCreateWindow 代替 XCreateSimpleWindow。我猜你的问题是你通过这个机制为你的窗口使用了白色的背景颜色。 XCreateWindow(display, root_win, 0, 0, 800, 600, 0, 0, CopyFromParent, CopyFromParent, 0, NULL);应该工作。
-
XCreateWindow 有效。谢谢!