I have a (maybe) simple question. I'd like to resize my program window after the user clicked on "maximize" since I want to fit the data to the window, without leaving "grey patches" (hope it does make sense lol, since I'm from Italy I'm not sure it does) . The problem is if I try to show a simple message, it doesn't show up. This is the piece of code I think you need to look at of my class (cpp file)
void EBCFrame::OnMaximize(wxMaximizeEvent& event)
{
// _window->Fit();
wxMessageBox(_T("maximize test"));
}
// Event table for EBCFrame
BEGIN_EVENT_TABLE(EBCFrame, wxFrame)
...
EVT_MAXIMIZE(EBCFrame::OnMaximize)
END_EVENT_TABLE()
And here's the header file
class EBCFrame : public wxFrame
{
public:
// Constructor
EBCFrame(const wxString& title);
// Event handlers
.....
void OnMaximize(wxMaximizeEvent& event);
private:
// This class handles events
DECLARE_EVENT_TABLE()
wxScrolledWindow* _window;
....
};
I apologize if it's not enough and you need the full code; in that case, I'll provide as soon as I read this question again. Thank you for your support!
Judging from your earlier question's code: wxWidgets: can't inherit from wxListCtrl;
You seem to be using a wxScrolledWindow for a wxListCtrl which is not needed (the wxListCtrl already manages the scrolling of its content) If that is the case, remove the wxScolledWindow from your code.
If that wxListCtrl (EBCList) is the only client window in your frame (EBCFrame), wxWidgets will size it automatically.
If you have added more widgets to your frame in the meantime, you may want to look into the sizer classes to compose your layout (e.g wxBoxSizer).
Related
I am using wxWidgets 3.1.3 and Boost 1.73.
Working on a custom preferences dialog for a modular application, here is the relevant parts of the header:
class PreferencesWindow : public wxDialog {
public:
PreferencesWindow(...); // Constructor
protected:
wxButton* DialogButtonsApply;
wxButton* DialogButtonsCancel;
wxButton* DialogButtonsOK;
wxTreebook* TreeBook;
private:
enum {
// Enumerated Window Ids
};
// Event Handlers
virtual void OnTreeSelection(wxTreeEvent& event);
virtual void OnApplyButton(wxCommandEvent& event);
virtual void OnCancelButton(wxCommandEvent& event);
virtual void OnOkayButton(wxCommandEvent& event);
DECLARE_EVENT_TABLE();
pt::ptree newPrefs;
public:
const pt::ptree &getNewPrefs() const;
void setNewPrefs(const pt::ptree &newPrefs);
};
The pt::ptree objects are typedefs of boost::property_trees. There is a global ptree in MyApp accessible throughout the entire application. During construction, the dialog dynamically loads each module's preferences page. Each page is a derived wxPanel. The newPrefs contain the modified preferences. I need the panels to be able to access and update newPrefs so that when the user exits the dialog, the dialog can be responsible for updating the main preferences data — and consequently, the preferences file/registry on disk.
How do I do this?
Update #1
To clarify:
During construction of PreferencesWindow, each of the controls are created and placed in their sizers. Panel, derived from wxPanel is then created and added to the dialog in TreeBook->AddPage(panelName, "Panel Caption");
Normally, the dialog will be called as a ShowModal from the main application window. However, right now, while I am creating the foundation for the PreferencesWindow, the main window is currently bypassed. The MyApp::OnInit() creates, and shows, the dialog, directly.
I will be making the Preferences dialog responsible for writing the options to disk, not just the main preferences variable.
I'm not sure what exactly is the problem, i.e. what precisely doesn't work for you, but you may find TransferDataFromWindow() useful: this method is called when the dialog is accepted and you typically override it to copy the data from the UI into your internal data structures.
Note that you should not define any handlers for the standard wxID_OK and wxID_APPLY buttons, as the default behaviour should be just fine (and, as an aside, if you do define these handlers, it doesn't make much sense to make them virtual).
I have been attempting to write a GTKMM gui application in C++. In my earlier projects in Java I started by making so-called 'Screen' objects which would each contain the layout of, and objects in, different screens. So I tried that in C++ as well, I derived these different Screen objects from the Gtk::Box so that I could easily append them to a Gtk::Notebook.
However I found out that this approach results in circular dependencies, and after a lot of browsing I couldn't find people with other approaches. I currently have a screen to display data retrieved from a database, and wanted to add filters to that.
I managed to allow the swapping of screens by giving each screen a pointer to the Gtk::Notebook they are in, but I hit a roadblock when I couldn't figure out how to make two screens interact with each other (eg. filter the data in another screen).
The general problem appears like this:
Gui.h:
class Gui {
protected:
// Child object pointers.
Gtk::Notebook *m_screens;
DbConnector *m_db;
// Screen object pointers.
MainScreen *m_mainScreen;
FilterScreen *m_filterScreen;
public:
// Constructors & destructor.
Gui();
virtual ~Gui();
};
Gui.cpp:
Gui::Gui() {
// Create application.
auto app = Gtk::Application::create();
// Db connector
m_db = new DbConnector();
// Create & configure window.
Gtk::Window m_window;
// Window configs.....
// Create notebook & screen objects.
m_screens = new Gtk::Notebook();
m_screens->set_show_tabs(false);
m_mainScreen = new MainScreen(*m_screens);
m_filterScreen = new FilterScreen(*m_screens);
// Add notebook to window.
m_window.add(*m_screens);
//Insert pages.
m_screens->append_page(*m_mainScreen);
m_screens->append_page(*m_filterScreen);
// Show all children & run app.
m_window.show_all_children();
app->run(m_window);
}
MainScreen.h:
class MainScreen : public Gtk::Box {
protected:
// Parent notebook pointer.
Gtk::Notebook* parent;
// Child widgets.
Gtk::Button m_toFilterScreenButton = Gtk::Button("To Filter Screen");
// Constructors & desctructor.
MainScreen(Gtk::Notebook& par);
virtual ~MainScreen();
// Methods.
void addFilter(std::string filterText);
void toFilterScreen();
};
MainScreen.cpp:
MainScreen::MainScreen(Gtk::Notebook& par) : parent(&par) {
// Build screen.
// Packing contents.....
// Configure widgets.
// Things like widget border width.....
// Signal handlers.
m_toFilterScreenButton.signal_clicked().connect(sigc::mem_fun(*this, &MainScreen::toFilterScreen));
}
void MainScreen::addFilter(std::string filterText) {
// Add filter
}
void MainScreen::toFilterScreen() {
notebook->set_current_screen(pagenum_of_filterscreen);
}
The problem I ran into now is when the FilterScreen is up, a filter is selected, and that filter should be applied to the MainScreen. The FilterScreen can't reach the MainScreen via the Gui object because that would require the screens to include Gui.h, which would result in a circular dependency. Trying to retrieve the MainScreen from the Gtk::Notebook returns a Widget&, which will tell you a Gtk::Widget has no function called addFilter(std::string filterText);.
Is anybody aware of a pattern I could use that would allow this type of behavior? So far the only option I can think of is one giant class that sets the screens using functions instead of premade objects, which would be far from optimal...
With the advice given by Sam Varshavchik in the comments I made a tiny example app that can handle multiple screens and switch easily. For those interested: source can be found here: ExampleApp
This is my first question here, so I'm trying to not sound stupid!
EXPLANATION:
I have a main window in Qt that has a button to create (sub-?) windows within the main window. This can be done as many times as the user wants, and each sub-window displays the same set of properties/items. I figured writing a class to hold all these properties would be a smart way to go about it (this would inherit the main window class), as each instance of the child window would automatically get the properties. I am using a slot to create each instance.
QUESTION:
Besides the desired properties, what do I add to the child window class to let Qt know that if I create an object of that type it should open a window?
For example, say I have implemented all the child window properties in a header file that looks something like this:
#include <QObject>
#include <QDialog> //Not sure about this
class ChildWindow : public ParentWindow
{
Q_OBJECT
public:
ChildWindow(QObject* parent);
~ChildWindow();
//Remaining properties like QSpinBox, Radio buttons etc
}
how then would I implement my slot? Like this?
void Parent::Slot()
{
ChildWindow* window;
window = new ChildWindow(this);
window->show()
}
My problem is that I don't see any code that indicates that window is a separate window. I can see that it is of type ChildWindow, but does just including QDialog give it the show() functionality?
EDIT:
I realise the first suggestion would be try and see if this works, but in the unlikely scenario that it works I wouldn't have learnt anything and I still wouldn't know why it worked, and if it didn't I would be back here asking this same question. I hope you guys understand.
EDIT 2:
error C2039: 'show' : is not a member of 'ChildWindow'
So I am guessing including QDialog did not do the trick
EDIT 3:
If I add this to the ChildWindow constructor
QDialog* child;
child = new QDialog;
child->show()
Do I have to do the same in the slot definition as well?
I am writing a small QT gui application where there is a QLineEdit in my mainwindow.ui and I want to display the entered text in a separate dialog and or window when a button is pressed.
Now, I have stored the input in a variable, and I am also able to show this string on a label within this same mainwindow,
void MainWindow::on_GoButton_clicked()
{
QString mytext = ui->lineEdit_1->text();
ui->label_1->setText(mytext);
}
Now, I want to open a popup dialog (can be a window also), for example SecDialog;
SecDialog secdialog;
secdialog.setModal(true);
secdialog.exec();
and display the text of mainwindow->mytext string variable in a label of the SecDialog. How can I do that ??? I know it is a basic level question, but I think it will help clear lot of my doubts reagrding moving values of variables in between forms and classes.
Situation
So this is your situation:
From your code, the dialog is a modal dialog:
SecDialog secdialog;
//secdialog.setModal(true); // It's not needed since you already called exec(), and the
// dialog will be automatically set to be modal just like what
// document says in Chernobyl's answer
secdialog.exec();
Solution
To make the dialog display the text from the Window,
the concept is to pass the information(text) from the Window
to the dialog, and use a setter function from the dialog to display it.
Like Floris Velleman's answer, he passed the mytext string (by reference) to a customized dialog constructor and called the setter theStringInThisClass(myString) at once.
The implementation detail of this function is complemented by Chernobyl's answer (use the name setLabelText instead):
void SecDialog::setLabelText(QString str)
{
ui->label->setText(str); // this "ui" is the UI namespace of the dialog itself.
// If you create the dialog by designer, it's from dialog.ui
// Do not confuse with the ui from mainwindow.ui
}
Chernobyl suggested another way which calls the setter in the slot function and it bypasses the need of defining another constructor, but basically the concept is the same:
void MainWindow::on_GoButton_clicked()
{
QString mytext = ui->lineEdit_1->text();
ui->label_1->setText(mytext);
SecDialog secdialog;
secdialog.setLabelText(myText); // display the text in dialog
secdialog.exec();
}
Comment
I try to illustrate the concept as clear as possible, because from my previous experience on your question, you just "copy & paste" codes from answers and took them as your final solution, which is not right. So I hope this summary could help you understand the concept and then you may write your own code.
This task can be easy done with getter/setter method or with signal and slot, but setter is more suitable here. In SecDialog header:
public:
void setLabelText(QString str);
//in cpp
void SecDialog::setLabelText(QString str)
{
ui->label->setText(str);//it is label dialog
}
Usage:
secDialog.setLabelText(myText);
Also line where you set modal to true is not necessary because
This property holds whether show() should pop up the dialog as modal
or modeless. By default, this property is false and show() pops up the
dialog as modeless. Setting his property to true is equivalent to
setting QWidget::windowModality to Qt::ApplicationModal. exec()
ignores the value of this property and always pops up the dialog as
modal.
Assuming SecDialog is a custom class with an interface file as well you might want to pass it as a constructor argument or pass it by using another function.
So in the SecDialog constructor you could have something like:
SecDialog::SecDialog(QWidget* parent, const QString& myString)
: QDialog(parent),
theStringInThisClass(myString)
{}
And then you could call it like:
SecDialog secdialog(this, mytext);
I'm trying to sort a wxGrid. Now, the documentation tells me it doesn't support sorting, but that it does generate an event. This documentation tells me the event is called wxEVT_GRID_COL_SORT. Fair enough!
Now, the problem is that I simply don't know how to get the event to work. I have an event table for my frame, which looks something like this:
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_BUTTON(XRCID("toevoegknop"), MainWindow::openAddWindow)
// A few other events that work
END_EVENT_TABLE()
The events listed there already work perfectly fine. In my MainWindow class I declared a function:
void sortColumn(wxGridEvent& event);
Now, I want to add said wxEVT_GRID_COL_SORT event. From my point of view the documentation isn't really super clear on what I should do, so I just tried adding the event by adding the following line to the event table.
wxEVT_GRID_COL_SORT(MainWindow::sortColumn)
Brings up a syntax error, thus it isn't right. I noticed the other events just started with EVT, so I tried to remove the wx, but I'm still out of luck.
Searching the internet far and wide brought me to a pastebin post which handles the event by adding the following line to the constructor of the frame (in my case MainWindow)
Grid->Connect(wxEVT_GRID_COL_SORT,(wxObjectEventFunction)&Frame::OnGridColSort);
Which I adapted like this (the almost entire constructor for MainWindow)
MainWindow::MainWindow(const wxString& title, const wxPoint& pos, const wxSize& size, Collection* library, MovieDB* database)
: wxFrame(), library_(library), database_(database) {
wxXmlResource::Get()->LoadFrame(this, NULL, _T("hoofdvenster"));
SetSize(size);
grid_ = (wxGrid *)FindWindowById(XRCID("filmtabel"));
// Irrelevant code removed, setting up the grid labels etc.
grid_->Connect(wxEVT_GRID_COL_SORT,(wxObjectEventFunction)&MainWindow::sortColumn);
}
Which throws up an error:
‘wxEVT_GRID_COL_SORT’ was not declared in this scope
So now I don't know what else I can try. Please do keep in mind that I only started messing about with wxWidgets a few days ago, so things that are trivial to any wxWidgets user might not be for me.
Thanks in advance!
It appears that you're using wx 2.8.12 which does not implement wxEVT_GRID_COL_SORT. It was added in wx 2.9 so you'd have to get the latest development release (2.9.4) to use it.
However, in wx 2.8 you can handle wxEVT_GRID_LABEL_LEFT_CLICK and dispatch the event accordingly to emulate the event.
Either add the event to the event map,
EVT_GRID_CMD_LABEL_LEFT_CLICK(ID_GRID,Frame::OnGridLabelLeftClick)
or connect it in your constructor:
grid->Connect(wxEVT_GRID_LABEL_LEFT_CLICK,
(wxObjectEventFunction)&Frame::OnGridLabelLeftClick);
void Frame::OnGridColSort(wxGridEvent& event) {}
void Frame::OnGridRowSort(wxGridEvent& event) {}
void Frame::OnGridLabelLeftClick(wxGridEvent& event) {
// GetCol and GetRow will return the index of the col/row label clicked
event.Skip(); // the next handler will select col/row/everything, based
// on the label clicked; remove to prevent selection
if( event.GetCol() >= 0 )
OnGridColSort(event);
else if( event.GetRow() >= 0 )
OnGridRowSort(event);
else
; // if both are -1, the upper left corner was clicked (select all)
}
This will behave similarly to EVT_GRID_COL_SORT.