我传统上使用wxWidgets绘制到OpenGL画布的方法是从当前OpenGL画布触发30赫兹定时的refresh(),然后生成一个“ wxEVT_PAINT”,我可以将其扩展到帧的其余部分。我还绑定到wxEVT_PAINT并调用refresh()来捕获任何调整帧大小的内容。

在我的不使用wxWidgets AUI的程序中,此方法完美无缺。

但是,如果我尝试使用AUI,则每次尝试绑定到wxEVT_PAINT时,我的绘画事件都不会触发。有时绑定到paint事件甚至会停止触发计时器等其他事件。

AUI处理事件是否有某种特殊方式,或者我在这里缺少的wxEVT_PAINT?在AUI托管框架内绘制到OpenGL窗口的最佳方法是什么?任何人都可以提供提示或示例,因为关于此主题的关于AUI的文档似乎不存在。

编辑:为清楚起见,我在下面添加了我的源代码,以供任何希望帮助查找问题的人使用。我删除了OpenGL部分,因为我实际上只是想让wxEVT_PAINT在调整窗口大小时触发帧中的绑定处理程序。

GeneratedFrame.h

#ifndef __GENERATEDFRAME_H__
#define __GENERATEDFRAME_H__

#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/panel.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/menu.h>
#include <wx/frame.h>
#include <wx/aui/aui.h>


class MainFrame : public wxFrame
{
    private:

    protected:
        wxPanel* m_panelMainView;
        wxMenuBar* m_menubar2;

    public:

        MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("SimpleAui"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 646,516 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
        wxAuiManager m_mgr;

        ~MainFrame();

};

#endif //__GENERATEDFRAME_H__


GeneratedFrame.cpp

#include "GeneratedFrame.h"

MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
{
    this->SetSizeHints( wxDefaultSize, wxDefaultSize );
    m_mgr.SetManagedWindow(this);
    m_mgr.SetFlags(wxAUI_MGR_LIVE_RESIZE);

    m_panelMainView = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
    m_panelMainView->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_ACTIVECAPTION ) );
    m_panelMainView->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INFOBK ) );

    m_mgr.AddPane( m_panelMainView, wxAuiPaneInfo() .Name( wxT("MainView") ).Center() .Caption( wxT("Main View") ).MinimizeButton( true ).PinButton( true ).Dock().Resizable().FloatingSize( wxDefaultSize ).Floatable( false ) );

    m_menubar2 = new wxMenuBar( 0 );
    this->SetMenuBar( m_menubar2 );


    m_mgr.Update();
    this->Centre( wxBOTH );
}

MainFrame::~MainFrame()
{
    m_mgr.UnInit();

}


AppFrame.h

#ifndef __AppFrame_h__
#define __AppFrame_h__

#include "GeneratedFrame.h"
#include "SimpleAuiApp.h"

class AppFrame : public MainFrame
{
public:
    // Constructor/Descructor
    AppFrame( wxWindow* parent, ApplicationData* pAppData );
    ~AppFrame( );

    // display update (called from main App on an update event)
    void UpdateDisplay( );

private:
    // pointer to the main data structure
    ApplicationData* m_pAppData;

    void OnPaint( wxPaintEvent& event );
};

#endif //__AppFrame_h__


AppFrame.cpp

#include "AppFrame.h"
#include "SimpleAuiApp.h"

#include <iostream>

// Constructor for the frame
AppFrame::AppFrame( wxWindow* parent, ApplicationData* pAppData )
    : MainFrame( parent )
{
    // Pull in the app data pointer
    m_pAppData = pAppData;

    // Set the size of the inner drawing area of the frame
    SetClientSize( 500, 500 );

    // Show the frame
    Show();

    // Layout the frame
    Layout();

    // Bind to the wxEVT_PAINT event
    Bind( wxEVT_PAINT, &AppFrame::OnPaint, this );
}

// Destructor for the frame
AppFrame::~AppFrame( )
{
    // stop the update timer for the application, otherwise a timer update
    // event can be generated while data is being deleted
    if( m_pAppData->m_pTimer )
    {
        m_pAppData->m_pTimer->Stop( );
    }
}

void AppFrame::OnPaint( wxPaintEvent& event )
{
    std::cout << "Running AppFrame::OnPaint\n";
    UpdateDisplay( );
}

// perform frame update for the display
void AppFrame::UpdateDisplay( )
{
    std::cout << "Running AppFrame::UpdateDisplay\n";
}


SimpleAuiApp.h

#ifndef __SimpleAuiApp_h__
#define __SimpleAuiApp_h__

#include <wx/wx.h>

#define DEFAULT_UPDATE_RATE (10)    // in Hz (set to 0 for OnIdle)

// Forward declarations
class AppFrame;

struct ApplicationData
{
    // constructor
    ApplicationData( )
    {
        m_pFrame = NULL;
        m_pTimer = NULL;
        m_nDisplayUpdateRate = DEFAULT_UPDATE_RATE;
    }

    // timer object for frame based updates
    wxTimer* m_pTimer;

    // rate of display update (in HZ) (0=update on idle)
    int m_nDisplayUpdateRate;

    // pointer to the main frame instance
    AppFrame* m_pFrame;
};

// Main application class
// (derived from the wxWidget App class)
class SimpleAuiApp : public wxApp
{
public:

    SimpleAuiApp( );
    virtual ~SimpleAuiApp( );

    // the main application data structure
    ApplicationData m_AppData;

private:

    // called by wxApp when starting up, program setup should be done here
    bool OnInit( );

    // called by wxApp when shutting down, program cleanup should be done here
    int  OnExit( );

    // When running with "fixed" framerate, called for each timer event (frame)
    void OnTimer( wxTimerEvent& event );
};

DECLARE_APP( SimpleAuiApp )

#endif //__SimpleAuiApp_h__


SimpleAuiApp.cpp

#include <wx/wx.h>

#include "SimpleAuiApp.h"
#include "AppFrame.h"

#include <iostream>

IMPLEMENT_APP( SimpleAuiApp )

SimpleAuiApp::SimpleAuiApp( )
{
}

SimpleAuiApp::~SimpleAuiApp( )
{
}

bool SimpleAuiApp::OnInit( )
{
    // Open a console window for errors and standard output
    AllocConsole( );
    freopen( "CONOUT$", "wb", stdout );
    freopen( "CONOUT$", "wb", stderr );

    std::cout << "Initialization started...\n";

    // Create the main application frame
    m_AppData.m_pFrame = new AppFrame( (wxWindow*) NULL, &m_AppData );

    // Bring the frame to the front
    SetTopWindow( m_AppData.m_pFrame );

    // See if a fixed frame rate is specified
    if ( m_AppData.m_nDisplayUpdateRate > 0 )
    {
        // Start a timer to update the display at a fixed frame rate.
        // Note that rate is increased by 10% to make up for wxWidget's inaccurate timers.
        m_AppData.m_pTimer = new wxTimer( this );
        float fMilliSeconds = 1000.0 / ( m_AppData.m_nDisplayUpdateRate * 1.1f );
        m_AppData.m_pTimer->Start( fMilliSeconds );
        Bind( wxEVT_TIMER, &SimpleAuiApp::OnTimer, this );
    }
    else
    {
        // capture the "on idle" event when not running at a fixed frame rate
        Bind( wxEVT_IDLE, &SimpleAuiApp::OnIdle, this );
    }

    std::cout << "Initialization completed...\n";

    return true;
}

// -------------------------------------------------------------
// Framerate - functions bound to framerate related events.
// Either OnTimer() or OnIdle() should be called here for each
// frame, but never both.  They are two different refresh
// methods.
// -------------------------------------------------------------

// Called by widget app code on timer event
void SimpleAuiApp::OnTimer( wxTimerEvent& event )
{
    std::cout << "Called SimpleAuiApp::OnTimer \n";
    // update the frame's display
    m_AppData.m_pFrame->UpdateDisplay( );
}

// -------------------------------------------------------------
// OnExit - Called by widget app code on shutdown
// -------------------------------------------------------------
int SimpleAuiApp::OnExit( )
{
    // stop (and delete) the update timer if needed
    if ( m_AppData.m_pTimer )
    {
        m_AppData.m_pTimer->Stop( );
        delete m_AppData.m_pTimer;
        m_AppData.m_pTimer = NULL;
    }

    // close the console window if needed
    FreeConsole( );

    // exit successful
    return 0;
}

最佳答案

问题最终是,您附加到主Frame的AUI管理器在传播时会消耗wxEVT_PAINT事件,并且永远不会到达Frame的类。但是,相框的孩子确实会收到事件。

我不仅使用Frame类中的Bind(),还调用m_panelgl-> Bind,其中m_panelgl是保存OpenGL画布的子容器。

10-08 17:58