X11窗口上的动画问题 我正努力在一个跨平台的C++应用程序中获得X11重绘事件。

X11窗口上的动画问题 我正努力在一个跨平台的C++应用程序中获得X11重绘事件。,c++,linux,x11,C++,Linux,X11,在Windows上,一切都很好(当我需要重画窗口时,我只发出一些invalidate调用),但在Linux上,我一直有重画口吃(可能是因为我发送了太多重画事件,如下所示) 调整窗口大小时也会发生同样的情况 这是我正在使用的代码 void Window::redraw() { // Called by any control which needs redrawing XEvent event; memset(&event, 0, sizeof(event)); event.t

在Windows上,一切都很好(当我需要重画窗口时,我只发出一些
invalidate
调用),但在Linux上,我一直有重画口吃(可能是因为我发送了太多重画事件,如下所示)

调整窗口大小时也会发生同样的情况

这是我正在使用的代码

void Window::redraw() { // Called by any control which needs redrawing
  XEvent event;
  memset(&event, 0, sizeof(event));
  event.type = Expose;
  event.xexpose.display = display;
  XSendEvent(display, window, False, ExposureMask, &event);
}

void Window::resize(int width, int height) {
  this->Width = width;
  this->Height = height;
}

bool Window::wndProc(XEvent *evt) {
  switch (evt->type) {

      case Expose: {

        if (evt->xexpose.count == 0) { // handle last one only

            if (Width != Bitmap.width() || Height != Bitmap.height())
              Bitmap.resize(Width, Height);

          Renderer.drawOnBitmap(Bitmap);

          this->paint();
        }

        return true;

      } break;

      case ConfigureNotify: {
        this->resize(evt->xconfigure.width, evt->xconfigure.height);

        redraw();
        return true;
      } break;
  }
}

void Window::paint() {

    XImage image;
    sk_bzero(&image, sizeof(image));

//    .. boilerplate to initialize XImage...

    XInitImage(&image);
    XPutImage(display, window, fGc, &image,
              0, 0,
              0, 0,
              Width, Height);
}
我尝试了几种方法来解决这个问题,包括:

  • 在每次重画事件发送之间有200毫秒的延迟(口吃仍在发生..调整大小仍会发出大量事件)
  • 有一个辅助线程每50ms发出一个重画调用(这会立即使X11的缓冲区饱和并使整个过程崩溃)
不幸的是,我有动画控件,每当它们需要重新绘制部分窗口时(我单独处理窗口的绘制区域),它们都会调用
redraw()


如何在确保动画控件保持平滑的同时解决调整大小时出现的口吃和太多重画事件?

首先,尝试使用
XCheckTypedWindowEvent
。如果窗口队列中有多个公开事件,则可能只应处理一个。其次,尝试限制重画速率(如果下一个重画事件比上一个重画事件快20毫秒,则不要重新绘制)。最后但并非最不重要的一点是,切换到其他一些渲染引擎(OpenGL?XPutImage可能会很慢)。配置您的程序!谢谢如果你把它贴出来,我很乐意接受这个答案。对于复杂的UI,使用openGL会更快吗?我认为XPutImage就像是Windows上的一个BitBlt(相当快,它只需要复制东西就可以了)嘿,先检查一下它是否工作。确实如此,我会研究openGL,因为你说它可以更快,但现在它工作得很好。请回答这个问题!那么到底是什么导致性能提高呢?首先,尝试使用
XCheckTypedWindowEvent
。如果窗口队列中有多个公开事件,则可能只应处理一个。其次,尝试限制重画速率(如果下一个重画事件比上一个重画事件快20毫秒,则不要重新绘制)。最后但并非最不重要的一点是,切换到其他一些渲染引擎(OpenGL?XPutImage可能会很慢)。配置您的程序!谢谢如果你把它贴出来,我很乐意接受这个答案。对于复杂的UI,使用openGL会更快吗?我认为XPutImage就像是Windows上的一个BitBlt(相当快,它只需要复制东西就可以了)嘿,先检查一下它是否工作。确实如此,我会研究openGL,因为你说它可以更快,但现在它工作得很好。请回答这个问题!那么到底是什么导致了性能的提高呢?
void Window::redraw() { // Called by any control which needs redrawing
  XEvent event;
  memset(&event, 0, sizeof(event));
  event.type = Expose;
  event.xexpose.display = display;
  XSendEvent(display, window, False, ExposureMask, &event);
}

void Window::resize(int width, int height) {
  this->Width = width;
  this->Height = height;
}

bool Window::wndProc(XEvent *evt) {
  switch (evt->type) {

      case Expose: {

        if (evt->xexpose.count == 0) { // handle last one only

            if (Width != Bitmap.width() || Height != Bitmap.height())
              Bitmap.resize(Width, Height);

          Renderer.drawOnBitmap(Bitmap);

          this->paint();
        }

        return true;

      } break;

      case ConfigureNotify: {
        this->resize(evt->xconfigure.width, evt->xconfigure.height);

        redraw();
        return true;
      } break;
  }
}

void Window::paint() {

    XImage image;
    sk_bzero(&image, sizeof(image));

//    .. boilerplate to initialize XImage...

    XInitImage(&image);
    XPutImage(display, window, fGc, &image,
              0, 0,
              0, 0,
              Width, Height);
}