如何设计一个窗口,呈现循环?

问题描述 投票:1回答:1

我想设计一个窗口对象,它的任务是处理GLFW窗口的所有功能(初始化,回调,输入处理...)

其中最重要的事情是渲染循环。最天真的设计,我能想到的是有renderloop法取一个函数指针没有参数,然后调用它的循环方法中,如下所示:

class Window
{
public:
    Window();
    ~Window();

    void WindowLoop(void (*f) (void));
protected:
    GLFWwindow* window;
};


void Window::WindowLoop(void (*f) (void))
{
    while(!glfwWindowShouldClose(window))
    {
        f();
        glfwPollEvents();
    }
}

然而,这施加了很大的局限性。首先,它意味着该函数不能带任何参数。这可能会或可能不会是一个问题。

我做了一些研究,显然可以传递函数指针是利用参数的任意数目,但是这似乎是既困难又防止建议。

另一种选择是一般的函子,然后这些参数可以被定义为类/结构的一部分,避免了必须处理的。

有可能是我不知道的,以及其他潜在的设计。

这将是C ++的渲染循环良好的设计,试图使用和第二,执行速度的第一优先考虑通用性?

c++ window glfw software-design
1个回答
1
投票

我简短的回答将是:

使用原始函数指针的std::function代替。这给你,因为它可以容纳更多的灵活性:

  • 函数指针
  • 方法指针(与对象,当然)
  • 函子
  • 的lambda(有或没有实际上重复所述一个或一个以上其它捕获)。

你仍然被限制在定义呼叫签名,但你可以给这可能是所有你需要你的回调上下文。

所以,这是怎么会看:

#include <functional>

class Window
{
public:
    Window();
    ~Window();

    void WindowLoop(std::function<void()> f);
protected:
    GLFWwindow* window;
};


void Window::WindowLoop(std::function<void()> f)
{
    while(!glfwWindowShouldClose(window))
    {
        f();
        glfwPollEvents();
    }
}

(它看起来比OP的原始样本没有太大的不同。)


三思而后行,我发现它值得一提的小工具集,他们提供什么样的解决方案(如有同样的问题来解决)。

这两个通用的解决方案

  • 信号/信号处理程序(signal slot concept
  • 事件处理程序virtual方法可以覆盖。

信号基本上是没有别的比函数指针(或std::function或东西可比)的容器。该信号被发射(即,所存储的函数指针称为)在某些情况下。因此,其他对象可以得到该情况(在信号注册他们的信号处理)通知。因此,一个信号是不同的函数指针(多个)不暂时提供,但存储在成员变量实际上类似像上面。

另一种方法是调用一个方法virtual在某些情况下。要添加自定义行为时,RESP。基类必须被导出并在追求的virtual方法必须被重写。

在OP的情况下,这可能是这样的:

class Window
{
public:
    Window();
    ~Window();

    void WindowLoop();
protected:
    virtual void step();
protected:
    GLFWwindow* window;
};


void Window::WindowLoop()
{
    while(!glfwWindowShouldClose(window))
    {
        step();
        glfwPollEvents();
    }
}

void Window::step() { /* empty placeholder */ }

要使用在应用程序中,派生类Window的是强制性的:

class GameWindow: public Window {
    protected:
        virtual void step() override;
};

void GameWindow::step()
{
    // Do the game step stuff (e.g. rendering)
    // where this (of type GameWindow) can provide the necessary context.
}

关于Qt,存在用于对例如各种情况和virtual方法的信号事件处理程序中的小部件。有大多的非此即彼/或选择 - 我不记得这两个可用的东西。例如。可以存在用于QPushButton::clicked()注册的信号处理程序,但以自定义的事件处理程序作为mousePressEvent(),一个Qt插件必须被重载以覆盖事件处理方法。 (也有事件过滤器的概念,但恕我直言,这是不完全一样的。)

gtkmm而不是(至少在2.0版本我在过去使用)提供的一切我还记得virtual方法和信号。所以,总有要么得到一个gtkmm的小部件或更改的选择,只是通过注册的信号处理/延长的gtkmm控件的行为。这可能会引入一些额外的性能开销,但它是应用程序非常方便。

© www.soinside.com 2019 - 2024. All rights reserved.