Where to put constant processing code 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
dmfr
In need of some credit
In need of some credit
Posts: 3
Joined: Sun Mar 18, 2018 6:20 pm

Where to put constant processing code

Post by dmfr »

I have a small program for plotting a fractal. I define classes MyApp and FractalFrame (aside from some wxPanels inside FractalFrame).
After declaring an instance of FractalFrame, I would like to start plotting the fractal. My intention is that, once every 10 iterations or so, the program escapes the iterative cycle, draws the new processed image, and then enter the iterative cycle again.

FractalFrame is supposed to always be computing iterations; that's where the problem might arise: when the user asks the window to close, it will be iterating. I thought of putting this cycle inside the constructor of FractalFrame, but I have a feeling it would not go as well as expected.

Here's the important part of the code:

main.cpp:

Code: Select all

#include <wx/wx.h>
#include "FractalFrame.h"
class MyApp: public wxApp{
    public:
        virtual bool OnInit(){
            FractalFrame* frame = new FractalFrame();
            frame->Show(true);
            return true;
        }
};
wxIMPLEMENT_APP(MyApp);
FractalFrame.h:

Code: Select all

#ifndef FRACTALFRAME_H_INCLUDED
#define FRACTALFRAME_H_INCLUDED
#include <wx/wx.h>
#include "FractalPanel.h"
#include "InfoPanel.h"
class FractalFrame: public wxFrame{
public:
    FractalFrame();
private:
    FractalPanel* fractalPanel;
    InfoPanel*       infoPanel;
    void OnChangeSettings(wxCommandEvent& event);
    wxDECLARE_EVENT_TABLE();
};
#endif // FRACTALFRAME_H_INCLUDED
FractalFrame.cpp:

Code: Select all

#include "FractalFrame.h"

wxPoint WindowInitPos      (250,   50);
wxSize  FractalPanelInitSz (1280, 720);
wxSize  InfoPanelInitSz    (1280,  70);

///Event enumeration
enum{
    ID_ChangeSettings = 1
};
///Functions
FractalFrame::FractalFrame():wxFrame(nullptr, wxID_ANY, "Mandelbrot set plotter", WindowInitPos){
    ///Menu
    wxMenu* menuSettings = new wxMenu;
    menuSettings->Append(ID_ChangeSettings, "&Change Settings");
    wxMenuBar* menuBar = new wxMenuBar;
    menuBar->Append(menuSettings, "&Settings");
    this->SetMenuBar(menuBar);
    ///FractalPanel
    fractalPanel = new FractalPanel(this, FractalPanelInitSz);
    ///InfoPanel
    infoPanel    = new    InfoPanel(this,    InfoPanelInitSz);
    ///Sizer
    wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
    sizer->Add(fractalPanel, 1, wxEXPAND, 0);
    sizer->Add(   infoPanel, 0, wxEXPAND, 0);
    sizer->SetSizeHints(this);
    this->SetSizer(sizer);

}
void FractalFrame::OnChangeSettings(wxCommandEvent& event){
    std::cout << "OnChangeSettings" << std::endl;
}

wxBEGIN_EVENT_TABLE(FractalFrame, wxFrame)
    EVT_MENU(ID_ChangeSettings, FractalFrame::OnChangeSettings)
wxEND_EVENT_TABLE()
The possibilities I have considered are:
1) Put the cycle in FractalFrame's constructor (which doesn't seem like a great idea);
2) Put the cycle after I declare FractalFrame in MyApp::OnInit
3) Put the cycle in a public member function of FractalFrame, and call it after declaring FractalFrame in MyApp::OnInit

Is there a standard procedure for dealing with this kind of situation, or at least a viable way to make it work?
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: Where to put constant processing code

Post by eranon »

Hello, I would go with #3. #2 is supposed to handle the initialization only. About #1, If your frame constructor never returns, your frame is never constructed and you can't show it. Also, remember you never draw directly, but you manage to draw during an event handler handling a paint event (and in case you want to fire a paint event on-demand, you invalidate the concerned area).
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
dmfr
In need of some credit
In need of some credit
Posts: 3
Joined: Sun Mar 18, 2018 6:20 pm

Re: Where to put constant processing code

Post by dmfr »

Thank you very much for your answer.
So, as for #1, it in an absolute no. That was exactly the problem I was thinking of, but I could not pick the right words: the object would not be constructed, and it would not even be possible to call a destructor upon it.
As for firing a paint event on demand, I believe that won't be a problem.
What I meant for #2 was something like:

Code: Select all

virtual bool OnInit(){
	FractalFrame* frame = new FractalFrame();
	frame->Show(true);
	while(true){
		for(int i = 0; i < 10; i++){
			... //calculations
		}
	}
	return true;
}
And for #3 would be like:

Code: Select all

virtual bool OnInit(){
	FractalFrame* frame = new FractalFrame();
	frame->Show(true);
	frame->RunLoop(); //this is where the calculations are. FractalFrame::RunLoop() is declared as public void.
	return true;
}
I believe I did not express myself clearly enough when formulating #2 and #3 in the first post. As for #3, are you referring to the option I have now further detailed, or are you referring to something else? Please explain what you are referring to, and if possible with a simple code example.
I am pretty much a newbie with wxWidgets, so I'm strill trying to learn the basics, sort of.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Where to put constant processing code

Post by doublemax »

The best solution would be to use a worker thread for the calculation. Using threads often sounds complicated and scares beginners off, but it's not really that hard.

http://docs.wxwidgets.org/trunk/classwx ... elper.html
Use the source, Luke!
User avatar
eranon
Can't get richer than this
Can't get richer than this
Posts: 867
Joined: Sun May 13, 2012 11:42 pm
Location: France
Contact:

Re: Where to put constant processing code

Post by eranon »

dmfr wrote:I believe I did not express myself clearly enough when formulating #2 and #3 in the first post. As for #3, are you referring to the option I have now further detailed, or are you referring to something else? Please explain what you are referring to, and if possible with a simple code example.
I am pretty much a newbie with wxWidgets, so I'm strill trying to learn the basics, sort of.
Sorry, no time to write down code just now, but what I meant about #3 was mostly to not block neither the app init nor the frame construction... You can, for example, call it on a one-shot timer after init, when the frame is activated the first time or at any point beyond the initialization (when you're sure the frame exists). Of course, as doublemax said, this method can launch a worker thread to prevent unresponsive UI (it depends on your requirements, if you have to draw a one-time graph or do it all life long) -- you do the calculation in the worker thread, then it sends a message to the main thread when there're a set of data to draw.
[Ind. dev. - wxWidgets 3.0/3.1 under "Win 7 64-bit, TDM64-GCC" + "OS X 10.9, LLVM Clang"]
dmfr
In need of some credit
In need of some credit
Posts: 3
Joined: Sun Mar 18, 2018 6:20 pm

Re: Where to put constant processing code

Post by dmfr »

Thanks a lot doublemax and eranon, a worker thread was exactly the solution I was looking for. I never worked with threads, but seems like the wxThreadHelper that wxWidgets offers is pretty easy to use. I will give it a try.
Post Reply