In Short:
I need to access a QCustomPlot variable in a WidgetClass. But I can't because it's private in that context. How is this accomplished?
What I have done:
I have a class that creates a graph and a widget class that calls the graph class
My QCustomPlot variable is a private variable that is being declared in the graph class, but I need to access this variable in the Widget Class.
I have a generate_graphs slot that gets data and passes the data to the graph class and from there the graph is created. I am saving to a png, so I need to access the graph variable with this data, the variable is passed data in the WidgetClass which then calls the graph class, which generates the graph.
The graph class variable (in the Widget Class) is declared like so: GraphWidget* graph
I try to access the QCustomPlot variable in that slot like this: graph->QCustomPlot->savePNG()
I keep getting an error that says QCustomPlot* GraphWidget::QCustomPlot is private within this context
I then created a function to just return the GraphWidget* graph so I could access that variable in the graph class. Instead so I could access the QCustomPlot variable without it being private in that context. This caused errors because it needs to be passed a GraphWidget* graph which is not declared in the GraphWidget class.
This was an isolated problem, but if anyone else has a similar problem my suggestion is this:
Make sure that your GraphWidget variable (the variable to creates a QCustomPlot) is accessible by the entire class that is trying to use it. I was trying to pass it a bunch of different ways, and none of them were correct.
Also make sure you create a public function in the GraphWidget class in order to access the savePng() function that QCustomPlot uses.
Related
In my QMainWindow scope I have an instance of a class AgilentSweeper which inherits QDockWindow, and initialize and display it with:
sweeper = new AgilentSweeper(this);
addDockWidget(Qt::RightDockWidgetArea,sweeper);
This class has a Qt Creator-made .ui form which has several widgets in it and the constructor looks like:
AgilentSweeper::AgilentSweeper(QWidget *parent) :
QDockWidget(parent),
ui(new Ui::AgilentSweeper)
{
ui->setupUi(this);
}
where Ui::AgilentSweeper *ui is public.
From other functions in the AgilentSweeper scope I can access the AgilentSweeper widgets and do things like double power = ui->powerSpinBox->value(); normally. However, I can't figure out how to access the AgilentSweeper widgets from within the scope of the main Ui. It seems like this should be possible because sweeper is a member I thought I should be able to do something like double power = sweeper->ui->powerSpinBox->value();, but despite messing around with it for a while I can't figure out how to access anything from sweeper's ui. I can think of several work-arounds, but this seemed like it should be possible.
ui Object is defined as private member of AgilentSweeper by default. So normally, you can't access it.
Some solutions:
very bad: declare QMainWindow as friend
bad: Change in AgilentSweeper.h private: by public: for the Ui::AgilentSweeper
one I would prefer:for each method of your UI-widgets you want to expose, create a public method in AgilentSweeper.h
So you can access the spinbox-value by
//in AgilentSweeper.h
double powerSpinBoxValue()
{
return ui->powerSpinBox->value()
}
//call from outside:
double power = sweeper->powerSpinBoxValue();
EDIT Explanation for 2
The object Ui::AgilentSweeper *ui is defined in AgilentSweeper.h usinf forward declaration. So in a file including AgilentSweeper.h alone, no information is given, how to create an instance of the object and which methods it provides.
This information is provided by autogenerated file ui_AgilentSweeper.h. so in order to use the way 2, include also ui_AgilentSweeper.h.
Why is this solution bad? It looks so flexible right?
In the first line exposing members as public is bad. A user could delete the instances: e.g. delete sweeper->ui->powerSpinBox.
Besides, there is no way to log or lock the access to the member objects.
I'm making an Arkanoid clone. This is the program layout I came up with:
source.cpp // few lines
App class // has constants APP_WIDTH and APP_HEIGHT
Ball class // has constant RADIUS
Brick class
Paddle class
Now I want to place the ball at the center of the window at the beginning of the game. Normally I would accomplish it like this:
Ball::Ball (App &app)
{
circle.setPos(app->WINDOW_WIDTH/2-RADIUS/2,app->WINDOW_HEIGHT/2-RADIUS/2)
}
But the ball class doesn't know anything about the App!
Do I need to make APP_WIDTH and APP_HEIGHT global variables?
Or do I need to turn the current app layout upside down, so that Ball class has #include "app.hpp" statement?
EDIT: Or do I need to declare ball, brick and paddle classes inside the app class? But then where I define them? Inside the same app class? Then the header gets too big!
And maybe there are some good tutorials on program layout topic on the internet? I haven't found any...
QUESTION 2:
Why do classes need protected variables if "there is no reason that ball would know anything about app class"
Since the issue seems to be that "Ball doesn't have any access to the private members of app class.", than maybe you want to make a getter.
A getter is a public method that returns the value of a private field.
If you do that, you can access the values of those members like so
circle.setPos(app->GetWidth()....
Your getter might look similar to the following
public int GetWidth()
{
return this.APP_WIDTH;
}
There is no reason for the game objects to know anything about the App they are part of. When it needs any information from App, it should receive them from App directly. This can happen either through setter-methods (recommended when properties can be changed by the App later, like the position of the ball) or in the constructor (recommended for things which don't change, like the positions of blocks).
Ball should have a SetPosition(x,y) which app invokes with the above calculation. Internally, this SetPosition would set the circle like above, so ball knows nothing about app.
I have an MDI application where a dialog is called when the OnFileNew() function (processed by the theApp object) is called. This dialog allows the user to set values to some variables that then need to be passed on to the CChildFrame object that is created when the ->CreateNewChild() function is called.
How do I pass these variables onto the CChildFrame object that is created by the ->CreateNewChild() function?
EDIT:
In response to an answer I got, here are the results for using ->Create() vs ->CreateNewChild().
Link: CMainFrame *pFrame; - pFrame->CreateNewChild()
Link: CChildFrame *childFrame; - childFrame->Create()
How do I get the tabbed windows shown in the first link with the function declarations described in the second link?
You can pass the data via a customized document template. Derive a class from CMultiDocTemplate to add additional data members, then add a pointer to your derived document template class to your CWinApp-derived app class. Initialize your document template in the usual way, except when you finish, save the new document template object to the pointer in your app class.
Now in your CreateNewChild function, instead of calling CWinApp::OnFileNew, you can just get the data from the current frame, then assign to the data member in the document template saved in the app class, before calling OpenDocumentFile(NULL). You can clear the data members when OpenDocumentFile returns.
The document template will in turn create the child frame and pass the doc template in the create context. To get the create context in the child frame, you can either override CChildFrame::OnCreateClient, or read the create structure in OnCreate:
MDICREATESTRUCT * pMDICreateStruct=(MDICREATESTRUCT * )lpCreateStruct->lpCreateParams;
CCreateContext *pCreateContext=(CCreateContext *)pMDICreateStruct->lParam;
Instead of passing the initialization data in the document template, you could also pass data to the new document. You will basically copy the code from CMultiDocTemplate::OpenDocumentFile and add the code to get the initialization data from the active document of the main frame.
Hey guys .. Well ever since I've started programming in Qt, I've been having problems regarding scope visibility of objects I've defined .. Till now I've managed to find ways to get around these things but now its getting annoying ..
For example, I have this class defined called Canvas:
class Canvas : public QWidget//, public MainWindow
{
Q_OBJECT
public:
void refreshFoldersList(QString inputPath);
void browseFolders();
private:
QListWidget *foldersList;
};
#endif // CANVAS_H
Now even though foldersList is private, refreshFoldersList() should be able to 'see' it, right ? But in my case it can't .. ! I first initialize foldersList in the browseFolders() function and then from within browseFolders(), I call refreshFoldersList() ... Any code inside refreshFoldersList() dealing with foldersList immediately throws a segmentation fault ... I've checked the pointer values for foldersList when the scope is in browseFolders() and refreshFoldersList() .. the values don't match .. its like either I'm trying to access something I'm not supposed to, or that I'm trying to access an object which has not been initialized yet ..
Any clues on this ?
A related issue ... I have another class MainWindow (inherited from QMainWindow) .. In this class I have an instance of the class Canvas .. this instance is named canvas .. I initialize canvas in MainWindow's constructor, and set canvas's parent to the MainWindow instance initializing it .. based on this, I used the following code to access a MainWindow function from within the Canvas class:
((MainWindow*)parent())->someFunctionDefinedInMainWindow();
Before, the above code used to work .. but then like 2-3 days ago it stopped working all of a sudden .. Now it got me to inside the MainWindow function I was calling (namely someFunctionDefinedInMainWindow() ), but from there if I tried to access any variable defined in MainWindow, I got a Segmentation Fault, again with pointer values not matching .. The way I solved this is by defining a variable as:
void * papa;
.. inside Canvas, and then when I initialized canvas, I set:
canvas->papa = this; //this being the MainWindow instance initializing canvas
Now I accessed MainWindow's functions like this:
((MainWindow*)papa)->someFunctionDefinedInMainWindow();
.. which works!
But again, I would like to know the nature of these problems .. Am I doing something wrong or what ?
The bug is here (code from your comment to liaK):
QListWidget *foldersList = new QListWidget();
You are creating a local variable instead of initializing the class member. Change the code to:
foldersList = new QListWidget();
And probably there is no need for foldersList to be a pointer at all, so your class declaration could be:
private:
QListWidget foldersList;
throws a segmentation fault
Probably some error in your initialization.. How you are initializing it?? Showing the code will be helpful.
And you are using --> instead of ->
Check out this link
Sure it is not a bug with Qt.
or that I'm trying to access an object
which has not been initialized yet
Perhaps you are trying to access an object that hasn't been initialised yet? How and where do you initialise folderList?
Now even though foldersList is private, refreshFoldersList() should be able to 'see' it, right ? But in my case it can't .. ! I first initialize foldersList in the browseFolders() function and then from within browseFolders(), I call refreshFoldersList() ... Any code inside refreshFoldersList() dealing with foldersList immediately throws a segmentation fault
If there was any problem with members visibility, your code wouldn't even compile. Your segfault must be related to something else.
I'm afraid you'll have to show more code for us to be able to help you efficiently.
Moreover, you're using C casts while Qt requires you to write C++. That can only make things worse.
So instead of:
((MainWindow*)parent())-->someFunctionDefinedInMainWindow();
You should use either dynamic_cast<> or static_cast<>, depending on what you want to achieve.
I'm using the wxGlade designer to generate the GUI for a small application.
It generates a class, inherited from wxFrame, which is the main application window.
In order to facilitate the maintenance, I'd like to avoid writing additional code in this generated class.
But all the widgets created with the wxGlade are actually created in the auto-generated method do_layout() and it is not possible to access them outside the scope of that generated method in the generated class.
Is there a way to get pointer of certain widget outside that generated class - by name, by type, by enumerating the children or something like that?
All classes inherited from wxWindow (wxFrame being one of them) have a function "GetChildren", which returns a list of child windows that you can then enumerate over. If you are looking for a specific field by name then use the "FindWindow" function.
Actually I found the answer myself:
wxWindowList & children = myframe->GetChildren();
for ( wxWindowList::Node *node = children.GetFirst(); node; node = node->GetNext() )
{
wxWindow *current = (wxWindow *)node->GetData();
// .. do something with current
}
May I recommend you try wxFormBuilder. I also used wxGlade before, but it presents too much constraints on how you use it. For example, with wxFormBuilder you can select 'visibility' (public,protected,private) for each control on the form. It can also generate virtual functions for event handlers, so you just derive your class from wxFormBuilder generated class and implement those functions.