【问题标题】:How to use wxWidgets with SFML?如何在 SFML 中使用 wxWidgets?
【发布时间】:2021-04-19 13:33:32
【问题描述】:

我正在制作一系列关于物理模拟的应用程序,到目前为止,我已经完成了其中一些应用程序,纯粹是使用方便的 SFML 库。现在我想为它们添加一些 GUI 元素。我只是对 wxWidgets 框架和 wxFrames 有点熟悉,但不知道 wxDc 是如何工作的,这似乎是 SFML-wxWidgets 集成的核心。我将一一列出我的查询。

  1. 我对@9​​87654321@提供的旧教程的拍摄:纠正一些琐碎错误后的最终代码如下所示:
#include <SFML/Graphics.hpp>
#include <wx/wx.h>

class wxSFMLCanvas : public wxControl, public sf::RenderWindow
{
public:
    wxSFMLCanvas(wxWindow* Parent = NULL, wxWindowID Id = -1, const wxPoint& Position = wxDefaultPosition,
        const wxSize& Size = wxDefaultSize, long Style = 0);
    virtual ~wxSFMLCanvas();

private:
    DECLARE_EVENT_TABLE()
    virtual void OnUpdate();
    void OnIdle(wxIdleEvent&);
    void OnPaint(wxPaintEvent&);
    void OnEraseBackground(wxEraseEvent&);
    void OnSize(wxSizeEvent&);
};

void wxSFMLCanvas::OnUpdate()
{
}

void wxSFMLCanvas::OnIdle(wxIdleEvent&)
{
    // Send a paint message when the control is idle, to ensure maximum framerate
    Refresh();
}

void wxSFMLCanvas::OnPaint(wxPaintEvent&)
{
    // Prepare the control to be repainted
    wxPaintDC Dc(this);
    // Let the derived class do its specific stuff
    OnUpdate();
    // Display on screen
    display();
}

void wxSFMLCanvas::OnEraseBackground(wxEraseEvent&)
{
}

void wxSFMLCanvas::OnSize(wxSizeEvent&)
{
}

wxSFMLCanvas::wxSFMLCanvas(wxWindow* Parent, wxWindowID Id, const wxPoint& Position, const wxSize& Size, long Style) :
    wxControl(Parent, Id, Position, Size, Style) {
    sf::RenderWindow::create(GetHandle());
}

wxSFMLCanvas::~wxSFMLCanvas()
{
}

class MyCanvas : public wxSFMLCanvas
{
    sf::CircleShape circ;
public:
    MyCanvas(wxWindow* Parent, wxWindowID Id, wxPoint& Position, wxSize& Size, long Style = 0) : wxSFMLCanvas(Parent, Id, Position, Size, Style) {
        // specify circle
        circ.setRadius(50.0f);
        circ.setOrigin(50.0f,50.0f);
        circ.setFillColor(sf::Color::Blue);
        circ.setPosition(100.0f, 100.0f);
    }
private:
    virtual void OnUpdate() {
        // Clear the view
        clear(sf::Color(0, 128, 128));

        // Display the circle in the view
        draw(circ);
    }
};

class MyFrame : public wxFrame
{
public:
    MyFrame() : wxFrame(NULL, wxID_ANY, "SFML wxWidgets", wxDefaultPosition, wxSize(800, 600)) {
        wxPoint tmp1 = wxPoint(50, 50);
        wxSize tmp2 = wxSize(700, 500);
        new MyCanvas(this, wxID_ANY, tmp1, tmp2);
    }
};

class MyApplication : public wxApp
{
private:

    virtual bool OnInit()
    {
        // Create the main window
        MyFrame* MainFrame = new MyFrame;
        MainFrame->Show();

        return true;
    }
};

IMPLEMENT_APP(MyApplication);

这会引发一堆未解决的外部问题:

Error   LNK2001 unresolved external symbol "protected: virtual struct wxEventTable const * __cdecl wxSFMLCanvas::GetEventTable(void)const " (?GetEventTable@wxSFMLCanvas@@MEBAPEBUwxEventTable@@XZ) test1   C:\Users\rajat\source\repos\test1\test1.obj 1   
Error   LNK2001 unresolved external symbol "protected: virtual class wxEventHashTable & __cdecl wxSFMLCanvas::GetEventHashTable(void)const " (?GetEventHashTable@wxSFMLCanvas@@MEBAAEAVwxEventHashTable@@XZ)    test1   C:\Users\rajat\source\repos\test1\test1.obj 1   
Error   LNK2019 unresolved external symbol main referenced in function "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ)    test1   C:\Users\rajat\source\repos\test1\MSVCRTD.lib(exe_main.obj) 1   

此外,我不太明白在这个示例中 wxWidgets 应该如何绘制 sf::RenderWindow 的内容。如果有人可以纠正这个准系统代码以使其正常工作,那将非常有帮助。并希望能解释它是如何工作的。

  1. 是否有可以与 SFML 一起使用的 wxWidgets 替代品,或者是否有用于快速和简单图形库的便捷工具?唯一的要求是我应该能够在 MSVS for x64 框架上编译它并静态链接到我的应用程序。我考虑过 Qt,但我不能让它自己编译,或者即使我这样做,它也只是 32 位共享库配置。

  2. 代码应该如何工作? sf::RenderWindow 是使用 sf::RenderWindow::create(GetHandle()) 创建的。它应该自己绘制所有内容吗?还是我必须自己复制SFML窗口的位图并在wxControl上绘制?如果有人能阐明它应该如何工作,那将非常有帮助。

【问题讨论】:

  • 是否有替代 wxWidgets 的方法可以与 SFML 一起使用 Qt 应该可以很好地解决这个问题。
  • 对此的另一条评论。请记住,c++ 库的二进制文件通常只与 msvc 或 mingw 兼容,您通常不能将 mingw c++ 二进制文件用于 msvc 或反之亦然。确保您拥有适用于您正在使用的任何编译器的正确二进制文件。此外,Visual Studio 2015 至 2019 版本相互兼容,但与任何其他版本的 msvc 不兼容。
  • @drescherjm 我用错误更新了问题。如果我可以在静态链接模式下为 x64 架构编译它,我可以使用 Qt,但我根本做不到。我在 x64 静态链接配置​​的 MSVS 上编译了 SFML 和 wxWidgets,并且我正在使用相应的预处理器指令进行静态链接。它们各自工作正常。
  • 我在工作中使用 64 位 Qt 已有 13 年,但从未将其用作静态库。相反,我生成了一个 NSIS 安装程序,它具有所有必需的 dll,还包括安装 msvc 可再发行组件的能力。
  • @RajatMondal,请在 MSVC 中打开 minimal 示例解决方案并查看其属性。然后在你的项目中做同样的事情。然后它应该可以干净地编译。确保在示例中选择合适的目标来查看 -= 即静态与动态。

标签: c++ wxwidgets sfml


【解决方案1】:

您的错误是由于使用了DECLARE_EVENT_TABLE 而没有使用任何wxBEGIN_EVENT_TABLE/wxEND_EVENT_TABLE,即您从未定义您的事件表或连接任何事件处理程序。

我对 SFML 一无所知,因此我无法真正帮助您完成其余的工作,但显然应该从您的 wxEVT_PAINT 处理程序中完成绘图——一旦你连接它——只需调用 @ 987654324@.

【讨论】:

  • 再次,抱歉,我对 SFML 一无所知,但对我来说,Display() 应该可以工作。在不使用 wx 的情况下,它是否适用于仅 SFML 的示例?
  • 我让它工作了。我只是被这么多的类和未使用的成员函数弄糊涂了,所以我开始删除所有不需要的东西,最后一切都在一起了。我发布了一个显示圆圈的准系统代码。我的第二个假设是正确的。SFML 可以自己显示所有内容,我不必自己绘制wxControl。不过谢谢你的回答!
【解决方案2】:

我终于让他们一起工作了。这是一个在按钮单击时显示一个圆圈的最小代码:

#include <SFML/Graphics.hpp>
#include <wx/wx.h>

class wxSFMLCanvas : public wxControl, public sf::RenderWindow
{
public:
    wxSFMLCanvas(wxWindow* Parent = NULL, wxWindowID Id = -1, const wxPoint& Position = wxDefaultPosition,
        const wxSize& Size = wxDefaultSize, long Style = 0);
    virtual ~wxSFMLCanvas();
};

wxSFMLCanvas::wxSFMLCanvas(wxWindow* Parent, wxWindowID Id, const wxPoint& Position, const wxSize& Size, long Style) :
    wxControl(Parent, Id, Position, Size, Style) {
    sf::RenderWindow::create(GetHandle());
}

wxSFMLCanvas::~wxSFMLCanvas() {
}

class cMain : public wxFrame
{
    wxButton* m_btn1 = nullptr;
    wxSFMLCanvas* mycanv = nullptr;
    wxDECLARE_EVENT_TABLE();
public:
    cMain();
    void onBtnClicked(wxCommandEvent &evt);
};


wxBEGIN_EVENT_TABLE(cMain,wxFrame)
    EVT_BUTTON(10001, onBtnClicked)
wxEND_EVENT_TABLE()


cMain::cMain() : wxFrame(nullptr, wxID_ANY, "Window", wxPoint(30, 30), wxSize(800, 600)) {
    mycanv = new wxSFMLCanvas(this, wxID_ANY, wxPoint(50, 50), wxSize(700, 500));
    m_btn1 = new wxButton(this, 10001, "button1", wxPoint(10, 10), wxSize(100, 50));
}

void cMain::onBtnClicked(wxCommandEvent& evt) {
    sf::CircleShape circ(50.0f);
    circ.setOrigin(50.0f, 50.0f);
    circ.setFillColor(sf::Color::Blue);
    circ.setPosition(350, 250);
    mycanv->draw(circ);
    mycanv->display();
}

class myApp : public wxApp
{
    cMain* m_Frame1 = nullptr;
public:
    myApp();
    virtual bool OnInit();
};
wxIMPLEMENT_APP(myApp);

myApp::myApp() {

}

bool myApp::OnInit() {
    // Create the main window
    m_Frame1 = new cMain;
    m_Frame1->Show();
    return true;
}

此代码的可执行文件(所有静态链接)约为 10MB(调试模式)~4MB(发布模式)。我把这段代码留在这里,以防其他人觉得这很有用。

【讨论】:

    猜你喜欢
    • 2022-09-13
    • 2021-12-06
    • 2011-07-17
    • 1970-01-01
    • 2014-10-27
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多