glcanvas on a wxpanel? Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
almonj
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Dec 09, 2016 5:41 pm

glcanvas on a wxpanel?

Post by almonj »

Is it possible to add a glcanvas to a wxpanel? I have a working canvas program where the canvas is attached to a wxframe:

Image


When I try to add a sizer with a wxpanel to the frame I end up getting a small cube in the corner.

Image


How do I go about getting a canvas in a window where I can also add buttons and text boxes along side of it? I'm probably making some obvious mistake but I have no idea what the proper way to do this is, and I could not find any examples of this.

Frame class

Code: Select all

M_frame::M_frame(const wxString& title)
       : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(1024, 768))
{

    canvas = NULL;

    wxGLAttributes attribs;
    attribs.PlatformDefaults().Defaults().EndList();
    bool accepted = wxGLCanvas::IsDisplaySupported(attribs);
    if (accepted)
    {
        std::cout << "normal display attribs are supported" << std::endl;
    }
    else
    {
        std::cout << "normal display attribs failed, trying other settings" << std::endl;
        attribs.Reset();
        attribs.PlatformDefaults().RGBA().DoubleBuffer().Depth(16).EndList();
        accepted = wxGLCanvas::IsDisplaySupported(attribs);
        if (!accepted)
        {
            std::cout << "display attribs cannot be set" << std::endl;
        }
    }

    if (accepted)
    {
        canvas = new M_canvas(this, attribs);
        std::cout << "canvas created \n" << std::endl;
    }
    SetMinSize(wxSize(640,480));

    //////////////////////////////////////////////////////////////////////////////////////////
    //////////sizer panel test, when I add this the canvas turns into a small cube//////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////
    
    wxBoxSizer *bsizer;
    bsizer = new wxBoxSizer(wxVERTICAL);

    m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
    bsizer->Add(m_panel, 1, wxEXPAND | wxALL, 5);

    this->SetSizer(bsizer);
    this->Layout();
    this->Centre(wxBOTH);

    //////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////

    wxMenu    *menufile    = new wxMenu;
    wxMenuBar *menubar     = new wxMenuBar;

    menubar->Append(menufile, "&File");

    menufile->Append(wxID_EXIT, "&Exit", "Quit the program");
    menufile->AppendSeparator();

    menufile->Append(wxID_HIGHEST + 10, "&Log window", "open Log window");
    menufile->AppendSeparator();

    SetMenuBar(menubar);

    m_log = new wxLogWindow(NULL, "log window", false, false);
    wxLog::SetActiveTarget(m_log);
    wxLogMessage("Log created");

};
Canvas class

Code: Select all

#include "glew-2.1.0/include/GL/glew.h"

#include "M_canvas.h"

#include "M_frame.h"


M_canvas::M_canvas(M_frame* parent, const wxGLAttributes& attribs)
         : wxGLCanvas(parent, attribs, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, "canvas", wxNullPalette)
{

    m_parent = parent;
    wxGLContextAttrs ctxAttribs;

    ctxAttribs.PlatformDefaults().CoreProfile().OGLVersion(3,3).EndList();

    m_context = new wxGLContext(this, NULL, &ctxAttribs);

    M_canvas::gl_init();

    gl = new GL_set();

};


M_canvas::~M_canvas()
{

    if(m_context)
    {
        SetCurrent(*m_context);
    }

    if(m_context)
    {
        delete m_context;
        m_context = NULL;
    }

}

M_canvas::gl_init()
{

    std::cout << "calling gl_init() " << std::endl;

    if (!m_context)
    {
        return false;
    }

    // Context needs to be set before openGL pointers are retrieved (glew)
    SetCurrent(*m_context);

    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        // Problem: glewInit failed, something is seriously wrong.
        printf("Error: %s\n", glewGetErrorString(err));
        return false;
    }
    printf("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

}

void M_canvas::paint(wxPaintEvent& WXUNUSED(event))
{

    wxPaintDC dc(this);

    SetCurrent(*m_context);

    gl->render();

    SwapBuffers();

}

BEGIN_EVENT_TABLE(M_canvas, wxGLCanvas)
    EVT_PAINT(M_canvas::paint)
END_EVENT_TABLE()
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: glcanvas on a wxpanel?

Post by doublemax »

The wxPanel should be the only child of the wxFrame.
Then you add a wxSizer to the panel and put the wxGLCanvas (and probably other controls) into the sizer.
The wxGLCanvas and these controls must have the wxPanel as parent.
As the wxGLCanvas has no natural "best size" you need to set the sizer flags (wxEXPAND) and proportion parameter so that it consumes all available space.
Use the source, Luke!
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: glcanvas on a wxpanel?

Post by ONEEYEMAN »

Hi,
For the samples please check wxWidgets/samples/opengl folder.

Thank you.
almonj
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Dec 09, 2016 5:41 pm

Re: glcanvas on a wxpanel?

Post by almonj »

I could not get it to work on a panel, but I tried it with just a box sizer and it worked with added buttons. So I guess the panel wasn't really necessary?
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: glcanvas on a wxpanel?

Post by ONEEYEMAN »

Hi,
Did you look at the samples?

Thank you.
almonj
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Dec 09, 2016 5:41 pm

Re: glcanvas on a wxpanel?

Post by almonj »

ONEEYEMAN wrote:Hi,
Did you look at the samples?

Thank you.

There are no samples that feature a glcanvas being used with a wxpanel.
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: glcanvas on a wxpanel?

Post by doublemax »

If it doesn't work with a wxPanel, either the sizer structure or a parent-child relationship is wrong somewhere. But we'd need to see the code to say more.
Use the source, Luke!
almonj
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Dec 09, 2016 5:41 pm

Re: glcanvas on a wxpanel?

Post by almonj »

I have a frame class that only has a wxpanel and a sizer, the canvas class takes a wxpanel as parent.

Image

This is what is looks like. If I change the canvas to take a wxFrame instead it works. What am I doing wrong?

I attached some files.

Thanks for any help, cheers

Frame_t.h

Code: Select all

#ifndef FRAME_T_H
#define FRAME_T_H

#include <wx/frame.h>
#include <wx/panel.h>
//#include <wx/glcanvas.h>

class Frame_t : public wxFrame
{
    public:
        Frame_t(const wxString& title);
        virtual ~Frame_t();

    protected:

    private:
       // wxPanel* m_panel;

        DECLARE_EVENT_TABLE();


};

#endif // FRAME_T_H
Frame_T.cc

Code: Select all

#include "Frame_t.h"

#include <wx/panel.h>
#include <wx/sizer.h>

#include <iostream>

#include "M_canvas.h"

Frame_t::Frame_t(const wxString& title)
       : wxFrame(NULL, wxID_ANY, title, wxPoint(742,300), wxSize(640, 480))
{

    wxPanel*  m_panel = new wxPanel(this, wxID_ANY);

    m_panel->SetBackgroundColour(wxColour(* wxGREEN));

    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

    this->SetSizer(sizer);
    this->Layout();
    this->Centre(wxBOTH);




    wxGLAttributes attribs;
    attribs.PlatformDefaults().Defaults().EndList();
    bool accepted = wxGLCanvas::IsDisplaySupported(attribs);
    if (accepted)
    {
        std::cout << "normal display attribs are supported" << std::endl;
    }
    else
    {
        std::cout << "normal display attribs failed, trying other settings" << std::endl;
        attribs.Reset();
        attribs.PlatformDefaults().RGBA().DoubleBuffer().Depth(16).EndList();
        accepted = wxGLCanvas::IsDisplaySupported(attribs);
        if (!accepted)
        {
            std::cout << "display attribs cannot be set" << std::endl;
        }
    }


    if (accepted)
    {
        M_canvas* canvas = new M_canvas(m_panel, attribs);
        std::cout << "canvas created \n" << std::endl;
    }
    SetMinSize(wxSize(640,480));

    sizer->Add(m_panel, 1, wxEXPAND | wxALL, 10);
}

Frame_t::~Frame_t()
{
    //dtor
}


BEGIN_EVENT_TABLE(Frame_t, wxFrame)

END_EVENT_TABLE()

M_canvas.h

Code: Select all

#include "glew-2.1.0/include/GL/glew.h"

#ifndef M_CANVAS_H
#define M_CANVAS_H

#include "glew-2.1.0/include/GL/glew.h"

#include <wx/glcanvas.h>
#include <wx/dcclient.h>
#include <wx/panel.h>
#include <wx/sizer.h>

#include "GL_set.h"


class M_frame;


class M_canvas : public wxGLCanvas
{
public:
    M_canvas(wxPanel* parent, const wxGLAttributes& attribs);
    ~M_canvas();

    gl_init();

    void paint(wxPaintEvent& event);

private:

    wxGLContext* m_context;

    GL_set* gl;

    DECLARE_EVENT_TABLE();

};




#endif // M_CANVAS_H
M_canvas.cc

Code: Select all

#include "glew-2.1.0/include/GL/glew.h"

#include "M_canvas.h"

#include "Frame_t.h"


M_canvas::M_canvas(wxPanel* parent, const wxGLAttributes& attribs)
         : wxGLCanvas(parent, attribs, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, "canvas", wxNullPalette)
{

    //m_parent = parent;

    wxGLContextAttrs ctxAttribs;

    ctxAttribs.PlatformDefaults().CoreProfile().OGLVersion(3,3).EndList();

    m_context = new wxGLContext(this, NULL, &ctxAttribs);

    M_canvas::gl_init();

    gl = new GL_set();

};


M_canvas::~M_canvas()
{

    if(m_context)
    {
        SetCurrent(*m_context);
    }

    if(m_context)
    {
        delete m_context;
        m_context = NULL;
    }

}

M_canvas::gl_init()
{

    std::cout << "calling gl_init() " << std::endl;

    if (!m_context)
    {
        return false;
    }

    // Context needs to be set before openGL pointers are retrieved (glew)
    SetCurrent(*m_context);

    glewExperimental = GL_TRUE;
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        // Problem: glewInit failed, something is seriously wrong.
        printf("Error: %s\n", glewGetErrorString(err));
        return false;
    }
    printf("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

}

void M_canvas::paint(wxPaintEvent& WXUNUSED(event))
{

    wxPaintDC dc(this);

    SetCurrent(*m_context);

    gl->render();

    SwapBuffers();

    //Refresh(false);   // generates a paint event, false means do not erase background

}

BEGIN_EVENT_TABLE(M_canvas, wxGLCanvas)
    EVT_PAINT(M_canvas::paint)
END_EVENT_TABLE()

Attachments
M_canvas.cpp
(1.62 KiB) Downloaded 83 times
Frame_t.h
(362 Bytes) Downloaded 77 times
Frame_t.cpp
(1.46 KiB) Downloaded 81 times
User avatar
doublemax
Moderator
Moderator
Posts: 19159
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: glcanvas on a wxpanel?

Post by doublemax »

The problem is that the wxGLCanvas is not in a sizer, so there is nobody that tells it to fill the available space.

OTHT, putting the wxPanel in a sizer is not necessary as it will automatically fill the whole client area of the frame if it is the only child.

So in more or less pseudo-code it should look like this.

Code: Select all

wxPanel *panel = new wxPanel(this, ....);
wxGLCanvas *gl_canvas = new wxGLCanvas(panel...);
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(gl_canvas, 1, wxEXPAND ); // tell wxGLCanvas to grow in both directions
panel->SetSizer( sizer );
Use the source, Luke!
almonj
Earned a small fee
Earned a small fee
Posts: 16
Joined: Fri Dec 09, 2016 5:41 pm

Re: glcanvas on a wxpanel?

Post by almonj »

doublemax wrote:The problem is that the wxGLCanvas is not in a sizer, so there is nobody that tells it to fill the available space.

OTHT, putting the wxPanel in a sizer is not necessary as it will automatically fill the whole client area of the frame if it is the only child.

So in more or less pseudo-code it should look like this.

Code: Select all

wxPanel *panel = new wxPanel(this, ....);
wxGLCanvas *gl_canvas = new wxGLCanvas(panel...);
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(gl_canvas, 1, wxEXPAND ); // tell wxGLCanvas to grow in both directions
panel->SetSizer( sizer );


This solved the problem, I got it to work. Thanks!
Post Reply