My files look something like so:
main.cpp
...
bool SyncApp::OnInit(){
SetTopWindow(new syncWindow(_("(S)FTP Automatic Sync")));
GetTopWindow()->Show(true);
return true;
}
...
syncwindow.h
#include <wx/wx.h>
class syncWindow : public wxFrame {
public:
syncWindow(wxString title) : wxFrame(NULL, -1, title) { initialize(); }
private:
void initialize();
wxTextCtrl * serverEntry;
};
syncwindow.cpp
void syncWindow::initialize(){
serverEntry = new wxTextCtrl(this, wxID_ANY);
this->AddChild(serverEntry);
}
For whatever reason whenever I close the window I get a segfault. If I don't add the serverEntry as a child to the window I don't get a segfault. I don't see why this is doing such a thing. I'm on CentOS 6, g++ 4.7 and wxGTK 2.8. Does anyone have any idea or a hint as to why this is happening?
Since you specified the parent window when constructing your child, the link is already present and calling this->AddChild(serverEntry); will cause double free or similar error when you close the window. http://docs.wxwidgets.org/2.8/wx_wxwindow.html#wxwindowaddchild
wxWindow::AddChild
Adds a child window. This is called automatically by window creation
functions so should not be required by the application programmer.
Notice that this function is mostly internal to wxWidgets and
shouldn't be called by the user code.
Related
I'm going to preface this question by saying that I am not entirely new to wxWidgets, though I would not consider myself all that experience either.
I'm having a problem which I have narrowed down through testing to be with the wxWidgets wxBoxSizer classes. From what I can tell, I don't think I'm doing anything wrong, and they work while the application is running; however, when the application closes and everything terminates, it seems that about a third of the time it will double-free something and seg fault. I'm writing and building on a linux system, and there doesn't seem to be any problems with anything but these sizers.
I did have many more windows within the HomeFrame class before I stripped it to search for bugs, but the code below still causes the double-free:
I've also looked around StackOverflow and other code forums to see if anyone was having a similar issue, but I couldn't find anything. I'm thinking that it may have something to do with the way I'm storing the sizer pointers in the class as members?
HomeFrame.h:
#pragma once
#include <wx/frame.h>
#include <wx/sizer.h>
namespace qzrgui
{
class HomeFrame: public wxFrame
{
public:
HomeFrame();
~HomeFrame();
private:
// Sizers
wxBoxSizer* _topSizer;
wxBoxSizer* _leftSizer;
wxBoxSizer* _rightSizer;
// Functions
void _setup();
void _createWindows();
};
}
HomeFrame.cpp:
#include "HomeFrame.h"
namespace qzrgui
{
HomeFrame::HomeFrame() :
wxFrame(nullptr, wxID_ANY, "Quizzer")
{
_setup();
}
HomeFrame::~HomeFrame()
{
}
void HomeFrame::_createWindows()
{
// Create sizers.
_topSizer = new wxBoxSizer(wxOrientation::wxHORIZONTAL);
_leftSizer = new wxBoxSizer(wxOrientation::wxVERTICAL);
_rightSizer = new wxBoxSizer(wxOrientation::wxVERTICAL);
}
void HomeFrame::_setup()
{
_createWindows();
}
}
Quizzer.h (wxApp base class):
#pragma once
#include <wx/app.h>
namespace qzrgui
{
class Quizzer : public wxApp
{
public:
virtual bool OnInit();
};
};
Quizzer.cpp:
#include "Quizzer.h"
wxIMPLEMENT_APP(qzrgui::Quizzer);
#include "frames/HomeFrame.h"
namespace qzrgui
{
bool Quizzer::OnInit()
{
wxFrame* frame = new HomeFrame();
frame->Show(true);
return true;
}
}
There is nothing in the code shown here which could result in a crash. You do definitely have (three) memory leak(s) in your code, as you create 3 sizers not associated with any window or another sizer and never delete them, but, while wrong, this can't result in a crash.
There is also not enough information to diagnose what you're seeing. As always with a crash, please build your code with debug information and run it under debugger to see what exactly happens. If you're under a Unix-like system (or even under MSW with the latest MSVS 2019 version), you should also compile with address sanitizer enabled to find the real problem before the crash happens.
everybody.
I am working on a gtkmm app and need some help getting a "Close" button to work. As suggested by the gtkmm documentation, I derived a class for the main window object, created some members, and left the main() function mostly for reading the glade UI file, instantiating the form and starting the main loop.
There are 3 files, named conveniently for explanation: Declarations.h, Declarations.cpp, Program.cpp
In "Declarations.h" I have the class inherited from the Gtk Window:
#include <gtkmm.h>
class MainWindowClass : public Gtk::ApplicationWindow
{
protected:
Gtk::Button *button_close;
// other buttons here
protected:
void on_button_close_clicked();
// other callback functions here
public:
MainWindowClass(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade); // Constructor
// Destructor, other public members
};
In "Declarations.cpp" I have the implementations:
#include "Declarations.h"
using namespace Gtk;
// Implementing the constructor
MainWindowClass::MainWindowClass(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) :
Gtk::Window(cobject), builder(refGlade)
{
builder->get_widget("button_close", button_close);
// Getting other widgets from the glade file
button_close->signal_clicked().connect(sigc::mem_fun(*this, &MainWindowClass::on_button_close_clicked));
// Connecting other callback functions here
}
// Implementing the callback for the "Close" button, ** PROBLEM IS HERE **
void MainWindowClass::on_button_close_clicked()
{
//gtk_main_quit(); Apparently GTK+/C only, compiler doesn't complain but causes a segfault when clicking the button
//Gtk::Application::quit(); Won't compile
}
The Program.cpp reads the UI from a file and starts the main program loop:
#include <gtkmm.h>
#include "Declarations.h"
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "Damn this close button");
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("Program_UI.glade");
MainWindowClass our_main_window;
return app->run(our_main_window);
}
I am omitting some non-relevant code (of other objects and callbacks) because they work, it is the close procedure that is causing me trouble, though closing the app with "X" works.
I have also thought about trying to call a quit() or destroy() function (if they exist) of "app", but then the callback function doesn't know "app" exists.
What do you guys suggest?
Thanks a lot.
** Edit: fixed this using FormMain::hide(), which is inherited from GtkWindow.
I thought the static procedure Gtk::Main::hide() would do it, but the compiler says that hide() is not a member of Gtk::Main...
Well, moving forward one step at a time.
Used FormMain::hide() (inherited from GtkWindow). The static procedure Gtk::Main::hide() was not being recognized by the compiler.
For my work, I developped an algorithm that computes stuff (which I'm not allowed to talk about just yet). It is a time consumming algorithm. Due to my sincere hatred of command line hard to configure algorithms, I am developping a GUI tool that should help me configure the algorithm and launch it. Here it is for the background.
Where I'm stuggling is here: I have a bunch of parameters to set, which is fine, and then I hit a generate button. What it does (or what I want it to do) is launch a custom popup wxDialog with a wxTextField containing the log info generated by the algorithm. The custom wxDialog only has construtor that sets the widgets in the right position.
Here is how I coded it so far:
void TnF_LoadingFrame::OnGenerate(wxCommandEvent &)
{
std::cout << "Generating!" << std::endl;
LogDialog dialog (m_pController,this,-1,_("Generation"));
{
wxStreamToTextRedirector redirect(dialog.m_textRedirection);
m_pController->Generate();
}
if(dialog.ShowModal() == wxID_OK)
std::cout << "Saving to do" << std::endl;
else
std::cout << "Cancelled" << std::endl;
}
As expected, the dialog shows itself only when the algorithm has finished computing. What I would like is for the window to show itself and for the algorithm to run in the background and its logs to be shown in realtime in the textfield. I was thinking in the line of threads, but I am not sure I understand how it works. I was also thinking in the line of an update function that would automatically be called every frame or so in order to let the dialog shows itself and then launch the algorithm in the update function and finally allows the user to exit the dialog.
I hope I am clear. Does anyone has any suggestions, pointers, ...? Help would be much appreciated ! Thanks in advance.
----EDIT----
So I have tried to implement the wxThread stuff with the LogDialog, and there is a problem. It seems that I have done something wrong with the events that are sent from the thread to the log dialog.
What I wanted was to create a thread when the LogDialog is created. Also, the ok button of the logdialog is disabled while the . This thread launches the algorithm so it runs in the background. When the algorithm is finished, it sends an event to the LogDialog. This event is captured by the log dialog, and the callback function enables the ok button, and deletes the thread.
However, it seems that the LogDialog never captures the event, and while the algorithm is running, finishes and an event is sent somewhere, the callback function is never called... Maybe it something I've done wrong. I included the code below. Thanks again for your help.
Here is what I've wrote: the OnGenerate function is as follows:
void TnF_LoadingFrame::OnGenerate(wxCommandEvent &)
{
std::cout << "Generating!" << std::endl;
LogDialog dialog (m_pController,this,-1,_("Generation"));
if(dialog.ShowModal() == wxID_OK)
std::cout << "Saving to do" << std::endl;
else
std::cout << "Cancelled" << std::endl;
}
It creates a dialog that launches a thread. The thread files are as follows:
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include "controller.h"
#include <tr1/memory>
using std::tr1::shared_ptr;
class Controller;
class MyThread : public wxThread
{
public:
MyThread(shared_ptr<Controller> pController, wxEvtHandler* parent)
: wxThread(wxTHREAD_DETACHED)
{
m_pController = pController;
m_parent = parent;
}
~MyThread(){}
protected:
virtual ExitCode Entry();
shared_ptr<Controller> m_pController;
wxEvtHandler* m_parent;
};
#endif // MYTHREAD_H
MyThread.cpp
#include "MyThread.h"
DEFINE_EVENT_TYPE(GENERATION_FINISHED_EVENT)
wxThread::ExitCode MyThread::Entry()
{
m_pController->Generate();
wxCommandEvent evt(GENERATION_FINISHED_EVENT, wxID_ANY);
m_parent->ProcessThreadEvent( evt );
//m_parent->ProcessPendingEvents();
return 0;
}
The log dialog files are as follows:
LogDialog.h
#ifndef LOGDIALOG_H
#define LOGDIALOG_H
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include "controller.h"
DECLARE_EVENT_TYPE(GENERATION_FINISHED_EVENT, wxID_ANY)
#include "MyThread.h"
class MyThread;
class LogDialog : public wxDialog
{
public:
LogDialog(shared_ptr<Controller> pController, wxWindow *parent, wxWindowID id, const wxString & title,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE );
~LogDialog(){}
wxTextCtrl *m_textRedirection;
private:
void OnGenerationFinished(wxCommandEvent &evt);
shared_ptr<Controller> m_pController;
wxButton *m_buttonOk;
wxStreamToTextRedirector *m_redirect;
MyThread *m_thread;
DECLARE_EVENT_TABLE()
};
#endif
LogDialog.cpp
#include "LogDialog.h"
// how to define the custom event
DEFINE_EVENT_TYPE(GENERATION_FINISHED_EVENT)
LogDialog::LogDialog(shared_ptr<Controller> pController, wxWindow *parent, wxWindowID id, const wxString & title,
const wxPoint & pos,
const wxSize & size,
long style)
: wxDialog(parent, id, title, pos, size, style)
{
m_pController = pController;
//some stuff
m_thread = new MyThread(m_pController,this);
m_thread->Create();
m_thread->Run();
}
void LogDialog::OnGenerationFinished(wxCommandEvent &evt)
{
m_buttonOk->Enable(true);
m_thread->Delete();
}
BEGIN_EVENT_TABLE(LogDialog, wxDialog)
EVT_COMMAND(wxID_ANY, GENERATION_FINISHED_EVENT, LogDialog::OnGenerationFinished)
END_EVENT_TABLE()
there are basically 2 options:
Single threaded Application: Do everything in the main (wx) thread, just implement your algorithm in a loop triggered by an eventhandler, since you want the gui to be responsive and even show output you have to pass processing time back to wx, this can be done by calling yield (or better safeyield), you can do this somewhere in the loop implementing your algorithm
Multithreaded Application: create a separated thread for your algorithm and use events to communicate with the main thread (and the gui) - take a look at the wx-wiki page
So I have managed to make it work... I looked at the sample thread code provided with the library. First of all, I started using wxMACROs instead of MACROs. Don't if that helped... but hey, who am I to judge. Next instead of having a:
DECLARE_EVENT_TYPE(NAME,TYPE)
call in LogDialog.h, and MyThread.h, I use an enum in LogDialog.h:
enum{
wxEVT_COMMAND_MYTHREAD_COMPLETED = wxID_HIGHEST+1
};
This seems to be equivalent to declaring the event, and reduces the macro calls everywhere, so less messy.
Then I declare the event table at the beginning of LogDialog.cpp:
wxBEGIN_EVENT_TABLE(LogDialog, wxDialog)
EVT_THREAD(wxEVT_COMMAND_MYTHREAD_COMPLETED, LogDialog::OnGenerationFinished)
wxEND_EVENT_TABLE()
Again, don't know if that helped. But the using an EVT_THREAD is probablly better. Finally, and I think it is what did the trick, I create and launch the event as follows:
wxThreadEvent evt(wxEVT_THREAD,wxEVT_COMMAND_MYTHREAD_COMPLETED);
wxQueueEvent(m_parent,evt.Clone());
This does the trick.
Also the other problem was to get the standard output back and show it in a text control but it seems that
wxStreamToTextRedirector(m_textRedirection);
is not thread safe... This is a story for another time.
Thanks to #Baxit for his insights.
I would like to fill an application window created with wxWidgets with a wxWebView. After reviewing the wxWebView sample, there the author created a wxFrame which then contained a wxBoxSizer and a wxWebView was added directly to that. However I would like my application to use a wxSingleChoiceDialog, so as far as I can tell, that means I need to include something like a wxPanel to use as the dialog's parent (the first argument to the constructor is the 'parent' of type wxWindow). So in my application I put a wxPanel in the wxFrame and then set the wxBoxSizer of the wxPanel to include the wxWebView. Unfortunately now the wxWebView no longer fits the full application window and I'm not sure why. Here is a simplified example of the application I'm trying to create.
main.h
#ifndef MAIN_H
#define MAIN_H
#include <wx/wx.h>
class MyApp : public wxApp
{
public:
virtual bool OnInit();
};
DECLARE_APP(MyApp)
#endif
main.cpp
#include "main.h"
#include "mainframe.h"
IMPLEMENT_APP(MyApp)
bool MyApp::OnInit()
{
MainFrame *mainFrame = new MainFrame(wxT("Content Creator"));
mainFrame->Show(true);
return true;
}
mainframe.h
#ifndef MAINFRAME_H
#define MAINFRAME_H
#include <wx/wx.h>
#include <wx/webview.h>
class MainFrame : public wxFrame
{
public:
wxPanel *panel;
wxBoxSizer *topsizer;
wxMenuBar *menubar;
wxMenu *file;
wxWebView *webView;
wxString editorURL;
MainFrame(const wxString& title);
void initMenu();
void initEditor();
};
#endif
mainframe.cpp
#include "mainframe.h"
MainFrame::MainFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(800,600))
{
panel = new wxPanel(this, -1);
topsizer = new wxBoxSizer(wxVERTICAL);
panel->SetSizer(topsizer);
initMenu();
initEditor();
}
void MainFrame::initMenu()
{
menubar = new wxMenuBar;
file = new wxMenu;
//file->Append(wxID_EXIT, wxT("Quit"));
menubar->Append(file, wxT("File"));
SetMenuBar(menubar);
}
void MainFrame::initEditor()
{
editorURL = "file:///C:/Users/kenwood/Desktop/MarkCreator2/ckeditor/samples/editor.html";
webView = wxWebView::New(panel, wxID_ANY, editorURL);
topsizer->Add(webView, 1, wxEXPAND | wxALL, 0);
}
Here is a screenshot of the application this creates: Screenshot
Does anyone know how I might be able to make this wxWebView fill the application window (or at least why it isn't fitting the window because I'm clearly missing something here)? I realize I can create a wxWebView an specify a a size that would be equal to the window size, but then when the user resizes the screen webview is no longer the same size as the application window.
Thanks.
EDIT:
Also, I'm using wxWidgets version 2.9.4
EDIT 2:
It appears that calling initEditor() before initMenu() produces the desired result (but not the other way around). Would anyone know what the reason for this is? I would really like to call initMenu() first if that is possible.
You need to add the webView to the panels sizer. Your question actually doesn't have anything to do with wxWebView but just concerns the layout and I strongly recommend (re)reading the corresponding section of the manual.
For anyone having similar problems, one of the main problems with my code is that I was creating the 'panel' before creating the menubar. By calling initMenu() as the first function call in the constructor I was able to get the webview to display in the full application window --advice provided by the illustrious 'doublemax' of wxWidgets forums. Thanks for everyone's help.
i have written the following application using MFC in visual c++ that includes two resources (a menu and a dialogbox) (created using the resource editor)...the program works absolutely fine except that it displays only one resource ie. it displays only the menu but it does not display the dialogbox...
what to do??
this is the code...
#include<afxwin.h>
#include"stdafx.h"
#include"resource.h"
class mydialog:public CDialog
{
private:
int id;
public:
mydialog(int n):CDialog(n)
{
id=n;
}
int OnInitDialog()
{
CDialog::OnInitDialog();
if(id==IDD_DIALOG1)
CenterWindow(GetDesktopWindow());
else
CenterWindow();
return TRUE;
}
void OnOK()
{
CDialog::OnOK() ;
MessageBox(TEXT("You have Pressed the OK Button"),TEXT("OnOK handler"));
}
};
class myframe:public CFrameWnd
{
public:
myframe()
{
Create(0,TEXT("Simple Dialog Box"),WS_OVERLAPPEDWINDOW,rectDefault,0,MAKEINTRESOURCE(IDR_MENU1));
}
void about()
{
mydialog d(IDD_DIALOG1);
d.DoModal();
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(myframe,CFrameWnd)
ON_COMMAND(101,about)
END_MESSAGE_MAP()
class myapp:public CWinApp
{
public:
int InitInstance()
{
myframe *p;
p=new myframe;
p->ShowWindow(3);
m_pMainWnd=p;
return 1;
}
};
myapp a;
Hey, without compiling the code and running it I can see a problem here:
myframe()
{
Create(0,TEXT("Simple Dialog Box"),WS_OVERLAPPEDWINDOW,rectDefault,0,MAKEINTRESOURCE(IDR_MENU1));
}
Where you are creating a window using IDR_MENU1 resource which is a menu. This means that the main window of your app is the menu.
Also, the whole code does not look MFC-ish at all. I would suggest creating an MFC app from Visual Studio template - it will set up the main window properly for you.
The dialog will only be displayed when the command with id 101 is executed. Presumably this would be a menu item which is associated with the main window. If your menu is defined as:
IDR_MENU1 MENU
BEGIN
POPUP "HELP"
BEGIN
MENUITEM "About", ID_HELP_ABOUT
END
END
And ID_HELP_ABOUT is defined with the value 101, then your about function will get called when you select that menu item, showing the dialog.
I'm not sure exactly what you are trying to achieve here, and would echo the other suggestions here by saying to start out with the MFC wizard generated code and take it from there.