Event capture during for loop 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
parad0x13
Experienced Solver
Experienced Solver
Posts: 79
Joined: Tue Jan 06, 2009 3:09 am

Event capture during for loop

Post by parad0x13 »

I have a loop that looks kinda like this:

Code: Select all

for(int y=0;y<Screen.y;y++)
{
	for(int x=0;x<Screen.x;x++)
	{
		PutToScreen(array[y*x + x]);
		SwapBuffer();
	}
}
Of coarse the actual PutToScreen algorithm is much more complex, fractal plotter, it is much much slower...

THEREFOR! I want stop the plotting process if their is a keyboard event... Perhapse something like this:

Code: Select all

for(int y=0;y<Screen.y;y++)
{
	for(int x=0;x<Screen.x;x++)
	{
		PutToScreen(array[y*x + x]);
		SwapBuffer();
		if(CharEvent() == true)
			break;
	}
}
Does anyone know how to inline check for events with wxwidgets?
User avatar
Disch
Experienced Solver
Experienced Solver
Posts: 99
Joined: Wed Oct 17, 2007 2:01 am

Post by Disch »

The only thing I can think of would be to call ::wxSafeYield to allow the app to process pending events. Maybe something like:

Code: Select all

void MyClass::SomeFunc()
{
  buttonPressed = false;

  for(int y=0;y<Screen.y;y++)
  {
    for(int x=0;x<Screen.x;x++)
    {
      PutToScreen(array[y*x + x]);
      SwapBuffer();
      ::wxSafeYield();
      if(buttonPressed)
        return;
    }
  }
}

void MyClass::OnChar(wxKeyEvent& event)
{
  buttonPressed = true;
}
However in my experiences I've found that's it's better to work around the event pump system rather than disrupt it. I'd try to avoid having to Yield unless you really have to.

Possible alternative solutions would be:

1) Put the large processing loop in a seperate thread.

2) Use Idle events to take steps in the drawing rather than putting it in a large loop.

An example of #2 might be:

Code: Select all

void MyClass::OnIdle(wxIdleEvent& event)
{
  event.Skip();
  bool more = true;

  PutToScreen(array[y*x + x]);
  SwapBuffer();
  ++x;
  if(x >= Screen.x)
  {
    x = 0;
    ++y;
    if(y >= Screen.y)
    {
      y = 0;
      more = false;
    }
  }

  event.RequestMore(more);
}
Also... did you mean y*x? or y*Screen.x?
parad0x13
Experienced Solver
Experienced Solver
Posts: 79
Joined: Tue Jan 06, 2009 3:09 am

Post by parad0x13 »

I meant x*y, because Array[x*y + x] turns the single dimensional array into a psuedo two dimensional one... Unless you know a better way of doing it lol, I certainly don't without initially creating a 2D array

Thank you for your ideas! I don't like the idea of putting it in an idle loop, because I want the plotting function to happen on keypress or event, etc... And I DO like the thread idea, however my extensive knowledge of threading is... well not very extensive to say the least...

Why would you NOT recommend the yield function?
It seems like a great idea! But you seem more knowledgable about it than I so, please tell me why you dislike it

Thanks : )

* Actually...
Doing a little research and testing 'yields' (pun intended) why yield() isn't such a good idea for my cause...

I wonder if there are any other ways how to check for events during a loop... hmmmmmmmmmmm
User avatar
Disch
Experienced Solver
Experienced Solver
Posts: 99
Joined: Wed Oct 17, 2007 2:01 am

Post by Disch »

parad0x13 wrote:I meant x*y, because Array[x*y + x] turns the single dimensional array into a psuedo two dimensional one
Not really, because x is a counter, not a constant value. The typical way to do this kind of indexing is (y*width)+x. (y*x)+x will give you very wacky results. Think about it for a bit... if you try to get the entry at coords 0,5 you get (5*0)+0 = 0. Not what you want, I'm sure.
Why would you NOT recommend the yield function?
Just personal preference I guess. There's nothing wrong with it. If you like the idea and it fits well, then go for it.

Just be cautious because it's possible for some potentially unwanted events to be triggered when you yield, resulting in some code being executed that you don't want to be executed.

For example if you yield from 'SomeFunc' (as in my previous example), you wouldn't want an event to enter SomeFunc during the yield or you'll get in a potentially endless event-yield-event-yeild loop which can deadlock the program or crash it in a stack overflow.

I guess it's potential situations like this which shy me away from Yield. But the same thing can happen with threads, too, if you're not careful. So like I say -- go with whatever works.
TrV
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 630
Joined: Wed Jul 04, 2007 1:12 pm

Post by TrV »

I do recommand thread solution too. It's surely more elegant.
Even if you don't know how exactly to implement.
It's in fact very simple : just a class, which derived from wxThread, with a virtual method to implement (Entry()), which is equivalent do the "main" of the thread.
Create an object of this class, run the thread and that's it.
You won't regret it, because threads are very often used for every kind of purposes.

For information, look at http://wiki.wxwidgets.org/Inter-Thread_ ... munication at the first example. You got everything.
parad0x13
Experienced Solver
Experienced Solver
Posts: 79
Joined: Tue Jan 06, 2009 3:09 am

Post by parad0x13 »

GAH! Your exactly right with the array thing lol, If I were to LOOK at my code then I would have realized:

Code: Select all

ComplexList[y*Screen.x+x].x = x;
Now it just makes me look stupid...

Anyways, I'm either going to have to find a better way to check for events, or more probably I'm going to have to rework my code flow to fix the issue, which I fear doing...

But again, thank you for your help : )
Post Reply