c++ - 如何避免cairo绘图xlib表面闪烁?

标签 c++ cairo xlib

我正在使用 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;
}

调整窗口大小时,有时会得到如下结果:
The result window

似乎尚未完成绘制红色背景的操作。

有人可以告诉我为什么会这样以及如何避免吗?

如果有人想在下进行编译,则可以使用Linux :g++ \pkg-config --cflags --libs x11 cairo\ src.cpp

谢谢!

最佳答案

该问题是由于您在白色背景上用填充红色区域来制作红色背景而造成的,这不是最有效的方法。

您应该使用定义为红色而不是白色的背景色来创建窗口!

因此,要做到这一点,请在XCreateSimpleWindow()背景参数(最后一个)中,将0xFF0000放入它,它是24位色彩空间中红色的十六进制值,但是如果使用其他格式,则可能需要更改它颜色空间。该行如下所示:

XCreateSimpleWindow(display, root_win, 0, 0, 800, 600, 0,
            BlackPixel(display, default_scr), WhitePixel(display, default_scr));

关于c++ - 如何避免cairo绘图xlib表面闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34382772/

相关文章:

C++套接字编程死循环

r - linux下无法安装Cairo包

xlib - 在 ubuntu/linux 中使用 Xlib 或 xinput 控制多个指针

c - Xlib:使用 PIxmap 和 XDrawPoint 显示网络摄像头太慢了……我该如何改进?

c++ - 父类上的方法没有被覆盖

C++ 将值解析为 vector 的更好方法

c++ - VS2008 C++好像不能继承const重载方法

python - 如何使用 igraph 在 python 中绘制 3d 图?

python - python中gtk.DrawingArea的透明背景

c - X11:如何使应用程序位于顶部