Render loop with wxWidgets

Started by
4 comments, last by legalize 14 years, 10 months ago
Hello, I want to write an editor with DirectX 10 and wxWidgets. Since wxWidgets hides the WinMain() and the application loop I can't set up the traditional render loop by myself. I found this site ( http://wiki.wxwidgets.org/Making_a_render_loop ) where they propose 2 approaches to implement a render loop: 1) using the idle event or 2) timers. I don't like the timer approach so I tried their code for the idle event. If I run the little sample code I get a windows with a white panel and the string "Testing" is constantly rendered (at different positions) to the panel in method render(), which is called by the OnIdle Event method. But the big problem is: If I move or resize the window, the rendering totally stops! I added a little menu bar to the window and even when I open a menu (for example click on "File", then the rendering freezes! If I close the menu or stop moving/resizing the window the rendering is continued. Does anyone know how I can fix this so that it renders ALL THE TIME? Thanks!
Advertisement
You can listen to other messages (such as erase_background) and all your render function at that time. I've had some issues with it though. Since the GUI is threaded, it'll be calling your function from multiple threads.

I've found it to generally be better to simply halt the rendering while it moved. Saves on several issues.
-- gekko
You can make your own event loop with wxWidgets if you want. There's nothing stopping you from doing that. Look deeper in the wxWidgets documentation, its in there. (I just don't remember where off the top of my head.)

My free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!

"""This demo attempts to override the C++ MainLoop and implement itin Python."""import timeimport wx                  #---------------------------------------------------------------------------class MyFrame(wx.Frame):    def __init__(self, parent, id, title):        wx.Frame.__init__(self, parent, id, title,                         (100, 100), (160, 150))        self.Bind(wx.EVT_SIZE, self.OnSize)        self.Bind(wx.EVT_MOVE, self.OnMove)        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)        self.Bind(wx.EVT_IDLE, self.OnIdle)        self.count = 0        panel = wx.Panel(self)        sizer = wx.FlexGridSizer(cols=2, hgap=5, vgap=5)                self.sizeCtrl = wx.TextCtrl(panel, -1, "", style=wx.TE_READONLY)        sizer.Add(wx.StaticText(panel, -1, "Size:"))        sizer.Add(self.sizeCtrl)        self.posCtrl = wx.TextCtrl(panel, -1, "", style=wx.TE_READONLY)        sizer.Add(wx.StaticText(panel, -1, "Pos:"))        sizer.Add(self.posCtrl)        self.idleCtrl = wx.TextCtrl(panel, -1, "", style=wx.TE_READONLY)        sizer.Add(wx.StaticText(panel, -1, "Idle:"))        sizer.Add(self.idleCtrl)        border = wx.BoxSizer()        border.Add(sizer, 0, wx.ALL, 20)        panel.SetSizer(border)            def OnCloseWindow(self, event):        app.keepGoing = False        self.Destroy()    def OnIdle(self, event):        self.idleCtrl.SetValue(str(self.count))        self.count = self.count + 1    def OnSize(self, event):        size = event.GetSize()        self.sizeCtrl.SetValue("%s, %s" % (size.width, size.height))        event.Skip()    def OnMove(self, event):        pos = event.GetPosition()        self.posCtrl.SetValue("%s, %s" % (pos.x, pos.y))#---------------------------------------------------------------------------class MyApp(wx.App):    def MainLoop(self):        # Create an event loop and make it active.  If you are        # only going to temporarily have a nested event loop then        # you should get a reference to the old one and set it as        # the active event loop when you are done with this one...        evtloop = wx.EventLoop()        old = wx.EventLoop.GetActive()        wx.EventLoop.SetActive(evtloop)        # This outer loop determines when to exit the application,        # for this example we let the main frame reset this flag        # when it closes.        while self.keepGoing:            # At this point in the outer loop you could do            # whatever you implemented your own MainLoop for.  It            # should be quick and non-blocking, otherwise your GUI            # will freeze.              # call_your_code_here()            # This inner loop will process any GUI events            # until there are no more waiting.            while evtloop.Pending():                evtloop.Dispatch()            # Send idle events to idle handlers.  You may want to            # throttle this back a bit somehow so there is not too            # much CPU time spent in the idle handlers.  For this            # example, I'll just snooze a little...            time.sleep(0.10)            self.ProcessIdle()        wx.EventLoop.SetActive(old)    def OnInit(self):        frame = MyFrame(None, -1, "This is a test")        frame.Show(True)        self.SetTopWindow(frame)        self.keepGoing = True        return Trueapp = MyApp(False)app.MainLoop()



This a wxPython sample program from wxPython SDK.
You can look at this, maybe it will help you.

Thanks for your answers!

@ElisaDay: I just ported your code to C++ and it basically works. I have overwritten the MainLoop function:
int MyApp::MainLoop() {    wxEventLoop* eventLoop = new wxEventLoop;   wxEventLoop* oldEventLoop= wxEventLoop::GetActive();    wxEventLoop::SetActive(eventLoop);    MSG msg;    while(running) {         while (PeekMessage( &msg, (HWND)0, 0, 0, PM_REMOVE )) {             if (!eventLoop->PreProcessMessage(&msg)) {                 TranslateMessage(&msg);                 DispatchMessage(&msg);             }         }         g_frame->Render();     }     wxEventLoop::SetActive(oldEventLoop);     return 0;}
But the problem is the same: When I click on the menu the rendering stops (Render() isn't called anymore). Any ideas how I can fix this?
Menus and dialogs start their own event loop. You could fire timer events, which should still be delivered to your app, so that you could continue rendering.

My free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!

This topic is closed to new replies.

Advertisement