Search code examples
c++wxwidgetssfml

How to use wxWidgets with SFML?


I am making a series of applications on physics simulations and until now I've done some of them using purely the handy SFML library. Now I want to add some GUI elements to them. I am just a little bit familiar with wxWidgets framework and wxFrames but have no idea how wxDc works, which seems to be at the core of SFML-wxWidgets integration. I will list my queries one by one.

  1. My shot at the old tutorial provided by SFML dev webpage: The final code, after correcting for the trivial errors looks like this:
#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);

This throws a bunch of unresolved externals:

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   

Furthermore, I don't quite understand how in this example wxWidgets is supposed to draw the contents of a sf::RenderWindow. It will be very helpful if someone can rectify this barebone code so that it works. And also hopefully explain how it works.

  1. Is there an alternative to wxWidgets that would work with SFML, or has a handy tool for fast and simple graphical library? The only requirement is that I should be able to compile it on MSVS for x64 framework and statically link to my application. I considered Qt, but I can't get it to either compile on my own, or even if I do, it's only the 32-bit shared library configuration.

  2. How is the code supposed to work? The sf::RenderWindow is created using sf::RenderWindow::create(GetHandle()). Is it supposed to draw everything on its own? Or do I have to copy the bitmap of the SFML window and draw on the wxControl by myself? It will be really helpful if someone could shed some light on how it's supposed to work.


Solution

  • Your error is due to using DECLARE_EVENT_TABLE but not using any wxBEGIN_EVENT_TABLE/wxEND_EVENT_TABLE, i.e. you never define your event table nor connect any event handlers.

    I don't know anything about SFML, so I can't really help you with the rest, but apparently drawing is supposed to be done from your wxEVT_PAINT handler -- once you connect it -- by just calling sf::RenderWindow::Display().