Need help writing a custom event Topic is solved

Are you writing your own components and need help with how to set them up or have questions about the components you are deriving from ? Ask them here.
DavidHart
Site Admin
Site Admin
Posts: 3887
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Post by DavidHart » Thu May 14, 2009 5:06 pm

I can post the back trace it it might be helpful
It's worth a try. Best to use a pastebin, and paste the relevant lines of source code too.
It seemed to be crashing very very early in the run.
Hmm. Do you create any static objects/functions? And what happens if you comment out the Connect() statement? Does it still crash?
I was asking if it is OK to post to an object which can not by itself handle the event.
No harm, but obviously not much good either.
The object I had in mind has NO event handler at all! Maybe it needs some sort of a handler for the event.Skip() to be used?
PushEventHandler adds a handler. You can then call Skip() inside that handler.
Have a good look at http://docs.wxwidgets.org/stable/wx_eve ... processing and http://docs.wxwidgets.org/stable/wx_eve ... lehandlers

spamiam
I live to help wx-kind
I live to help wx-kind
Posts: 180
Joined: Wed Apr 22, 2009 1:40 am

Post by spamiam » Thu May 14, 2009 7:49 pm

DavidHart wrote:
I can post the back trace it it might be helpful
It's worth a try. Best to use a pastebin, and paste the relevant lines of source code too.
I will find out how to use a pastebin and then post the trace and code.
It seemed to be crashing very very early in the run.
Hmm. Do you create any static objects/functions? And what happens if you comment out the Connect() statement? Does it still crash?
No, everything works fine if I comment out the mainframe->Connect(...) statement. If I use the other type "Connect(wxID_ANY....) then it does not crash, and the one GraphicsWindow object to which the event was posted gets the event and is able to process it. The other instances do not get the event, despite all of them having the line event.Skip().
I was asking if it is OK to post to an object which can not by itself handle the event.
No harm, but obviously not much good either.
Not much good, but the idea was to get an event created SOMEWHERE so that I can later dynamically attach to it.
I will!

-Tony

spamiam
I live to help wx-kind
I live to help wx-kind
Posts: 180
Joined: Wed Apr 22, 2009 1:40 am

Post by spamiam » Sat May 16, 2009 12:32 pm

I have done some more work with trying to trace down the source of the crash. It would appear to be a problem with the mainframe pointer. When I do the same connect to a different object, such as a scrollbar object, then the same command does not crash. See below:

Code: Select all

//
//File: GraphicsWindow.cpp
//

//GLOBAL OBJECTS WHICH CREATE EVENTS USED HERE
extern Analyzer *mainframe;
extern wxScrollBar* dataScroll;




//*********************************************************************
// class constructor

GraphicsWindow::GraphicsWindow(wxScrollBar* NAdataScroll, wxWindow* parent, 
                               wxWindowID id, const wxPoint& pos, const wxSize& size, 
                               long style, const wxString& name)
                              : wxScrolledWindow(parent, id, pos, size, style, name)
                        
{
     
//This Connection works.

    dataScroll->Connect(wxEVT_SCROLL_CHANGED, 
                    wxScrollEventHandler(GraphicsWindow::OnScroll), 
                    NULL, this);
 
//This connection does not cause a crash!                 
    dataScroll->Connect(DataReadyEvent,
                    CaptureEventHandler(GraphicsWindow::OnNewData),
                    NULL, this);
                    
//This connection with only the source pointer changed causes an instant crash!
    mainframe->Connect(DataReadyEvent,
                    CaptureEventHandler(GraphicsWindow::OnNewData),
                    NULL, this);

{....}
}

So It appears to be a problem with the mainframe pointer. Here is how both the dataScroll and mainframe pointers are defined and instantiated:

Code: Select all

//
//File:  AnalyzerMain.cpp
//

#include "AnalyzerMain.h"
#include "captureevent.h" //<-this contains the macro for  DataReadyEvent


//GLOBAL VARIABLES FOR EVENT PASSING
wxScrollBar     *dataScroll;
const wxEventType DataReadyEvent = wxNewEventType();


//*****************************************************
Analyzer::Analyzer(wxWindow *parent, wxWindowID id, const wxString &title,
                   const wxPoint &position, const wxSize& size, long style)
                 : wxFrame(parent, id, title, position, size, style)
{
     initVars();
     CreateGUIControls();
}




//*****************************************************
void Analyzer::CreateGUIControls()
{
     {...}

     dataScroll = new wxScrollBar(page1, wxID_ANY, wxPoint(0,0), wxSize(-1,-1),
                                  wxSB_HORIZONTAL, wxDefaultValidator,
                                  wxT("DATASCROLL"));
     dataScroll->Enable(true);
     dataScroll->SetRange(1<<16);
     dataScroll->SetThumbSize(1<<15);
     dataScroll->SetThumbPosition(1<<14);
     dataScroll->SetPageSize(dataScroll->GetPageSize()>>3);

     {....}
}
And here is where the mainframe object is declared and instantiated:

Code: Select all

//
//File:  AnalyzerApp.cpp
//

#include "AnalyzerApp.h"




//Create some GLOBAL variables which are event sources:
Analyzer *mainframe;



IMPLEMENT_APP(AnalyzerApp)

bool AnalyzerApp::OnInit()
{
    mainframe = new Analyzer(NULL);
    SetTopWindow(mainframe);
    mainframe->Show();
    return true;
}
As far as I can tell, the mainframe pointer should be a good one, and not pointing wildly when it is used in the GraphicsWindow code. It is not NULL when I check it in the GraphicsWindow when I print it out onto the graphics screen.

Any ideas about why the mainframe pointer whould cause a crash while the dataScroll does not?

-Tony

User avatar
doublemax
Moderator
Moderator
Posts: 14075
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Sat May 16, 2009 1:30 pm

Any ideas about why the mainframe pointer whould cause a crash while the dataScroll does not?
quite obvious, the global variable "mainframe" is not initalized at that point in time.

Global variables are usually bad and in this particular case certainly not necessary.

If you don't want to change anything now, put a "mainframe=this;" at the first line into your Analyzer ctor.

Any you really should learn how to use a debugger, errors like this are easily detected in a debugger while looking at the code you can spend hours without seeing the mistake.
Use the source, Luke!

spamiam
I live to help wx-kind
I live to help wx-kind
Posts: 180
Joined: Wed Apr 22, 2009 1:40 am

Post by spamiam » Sat May 16, 2009 5:45 pm

doublemax wrote:quite obvious, the global variable "mainframe" is not initalized at that point in time.
Well, You are correct, I did not initialize mainframe. I did not do this because I thought that the very first thing that happened when executing my applications code was to assign the mainframe variable (see the indicated statement)

Code: Select all

//This is the main application file.  It gets run as the very first thing

//Create some GLOBAL variables which are event sources:
Analyzer *mainframe;

IMPLEMENT_APP(AnalyzerApp)

bool AnalyzerApp::OnInit()
{
   mainframe = new Analyzer(NULL); //<-THIS IS THE ASSIGNNEMT, AND IT SEEMS TO BE DONE 
//                                 //BEFORE ANYTHING ELSE IN THE APPLICATION CODE

{....}
}
doublemax wrote:Global variables are usually bad and in this particular case certainly not necessary.
I agree, They are distasteful and no end of trouble. But Even more distasteful is having to pass the mainframe pointer when creating a child of a child of a child....

Is there another way to determine the mainframe pointer other than using a global or explicitly passing it to children?
doublemax wrote:If you don't want to change anything now, put a "mainframe=this;" at the first line into your Analyzer ctor.

I will try it. But I thought that mainframe would have been assigned that value by then
doublemax wrote:Any you really should learn how to use a debugger, errors like this are easily detected in a debugger while looking at the code you can spend hours without seeing the mistake.
You mean the the backtrace? Yes, it seems quite cryptic. I have looked at the backtrace, but I can not tell where it is trying to say that the crash occurred.

-Tony

EDIT:

P.S. I made the change you suggested to initialize mainframe to "this" in the Analyzer class in AnalyzerMain.coo. I then changed the variable name when instantiating the class in Anallyzer.App.cpp.

AND IT WORKED! All of it! Even the ability to catch the event even when it is posted to some other class. And ALL the instances of the GraphicsWindow class see the event. This achieves my goal! THANK YOU.

I still don't know why the statement
"mainframe = new Analyzer(...);"

is not equivalent to the statement
"mainframe = this;" when written inside the Analyzer class. I thought that the two pointers were equivalent.

-T

DavidHart
Site Admin
Site Admin
Posts: 3887
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Post by DavidHart » Sat May 16, 2009 6:51 pm

You haven't shown where you create your GraphicsWindow instance, but I'd guess it's from either initVars() or CreateGUIControls().

These are called inside your Analyzer ctor, and the statement mainframe = new Analyzer(NULL) doesn't set mainframe until it returns.

spamiam
I live to help wx-kind
I live to help wx-kind
Posts: 180
Joined: Wed Apr 22, 2009 1:40 am

Post by spamiam » Sat May 16, 2009 11:41 pm

DavidHart wrote:You haven't shown where you create your GraphicsWindow instance, but I'd guess it's from either initVars() or CreateGUIControls().

These are called inside your Analyzer ctor, and the statement mainframe = new Analyzer(NULL) doesn't set mainframe until it returns.
Yes, the GraphicsWindow(s) get created inside CreateGUI().
doesn't set mainframe until it returns.
AHHHHHHHHHHHHHHHHHH!, Of course. That explains it. Actually I did not know which came first, and not that you point it out, it makes sense that the assignment would be after the creation.

Thanks so much!

-Tony

Post Reply