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.
Related
I'm sorry if this question is duplicate but i am really struggling with finding any answer.
Please take in mind that i am novice in c++ programmming.
My problem is this. I have an GUI made in QtCreator. There are two listeners binding keyReleaseEvent, one on main class (SuperFalcon) , one on QTextEdit ( which is separate and modified class ). I have QFrame which i would like to toggle hide/show on "Ctrl + f" key event. Since that QFrame (object name is findWidget) widget belongs to SuperFalcon->ui, there's no problem, everything works fine, problem starts when i try to make "Ctrl + f" in QTextEdit because it's separate event listener. Basically i tried this.
main class name is "SuperFalcon" so:
in superfalcon.h i've made an public static pointer like this:
public:
static QFrame *fWidget;
then in superfalcon.cpp, i firstly execute
ui->findWidget->hide(); and then
fWidget = ui->findWidget; hoping to get pointer on widget.
Next in my QTextEdit class in keyReleaseEvent function i've tried to get that pointer like SuperFalcon::fWidget->show() but i get undefined reference on it.
So , to make things simpler, i don't know how , if possible, to get reference of QFrame widget which is part of one class (SuperFalcon), from another class (QTextEdit class) in order to execute some commands on QFrame.
If it's not clear enough i can provide some code.
You must have a definition of any static member variable.
This definition has to be in a source file because of the one definition rule.
Simply add the line:
QFrame* SuperFalcon::fWidget;
to "superfalcon.cpp".
You have to initialize your static variable, in superfalcon.cpp:
QFrame* SuperFalcon::fWigdet = nullptr;
Consider the following code:
class.h
public:
QString dataDirectory;
class.cpp
dataDirectory = QApplication::applicationDirPath();
dataDirectory.append("/../data");
child.h
class Child : public QDialog
child.cpp
QString dataFile = parent()->dataDirectory; // Fails
dataFile.append("myfile.txt");
Of course I tried to cast it with an qobject_cast, like so:
ParentClass *myParent = qobject_cast<class *>(parent());
QString dataFile = myParent->dataDirectory; // Fails (I even get a segfault);
No success. I also tried to change the constructor of the child, but I get a few dozen error messages of what is not defined. Although I used forward declaration and avoided to include the header files.
All I want is to have one place where I define the directory path and access it in my whole application. In another language I know better that would be really, really simple, but in C++ I can't get it to work :/
The problem is a really basic one and I'm kinda embarrassed not to find a solution, but my Parent and Child are both QWidgets and I can't find any way to access the parents variable in the child.
Use a private data member and a public and static getter function, returning const QString & made from the data member.
"My" solution (thanks to dom0)
QString parent::dir()
{
return QGuiApplication::applicationDirPath().append("/../data/");
}
I recently met a strange problem of my little program and it would be great if you help me to get the reason of this behavior.
My task is quiet simple - I want to use Qt Graphics Framework to show some objects and I want Box2D to calculate bodies position. So my class hierarchy looks like the following:
I have 1 base abstract class B2DObject. It contains some Box2D staff + some common parameters for its successors (names, some flags, etc.). It also has couple of pure virtual functions that will be reimplemented in successor classes.
Then I implement some classes that represent basic shapes: circles, rectangles, polygons, etc. I am doing it in the following way:
class ExtendedPolygon : public B2DObject, public QGraphicsPolygonItem { ... };
class ExtendedCircle : public B2DObject, public QGraphicsEllipseItem { ... };
etc.
(for those who are not familiar with Qt, QGraphics***Item is inherited from QGraphicsItem).
Also I inherited QGraphicsScene and reimplemented its mousePressEvent. In this function I request an object placed at some point on the screen using QGraphicsScene::itemAt function (which returns QGraphicsItem*), convert it to B2DObject* and try to get some internal field from this object:
void TestScene::mousePressEvent (QGraphicsSceneMouseEvent *event)
{
QGraphicsItem* item = itemAt (event->scenePos ());
if (item)
{
B2DObject* obj = reinterpret_cast < B2DObject* > (item);
QString objName = obj->Name(); // just for example,
// getting other internal fields has
// the same effect (described below)
// use retrieved field somehow (e.g. print in the screen)
}
// give the event to the ancestor
}
Unfortunately, dynamic_cast will not work here because these classes are completely unrelated.
Then I create necessary objects and add it to my scene:
ExtendedPolygon* polygon = new ExtendedPolygon (parameters);
polygon->setName (QString ("Object 1"));
...
TestScene scene;
scene.addItem (polygon);
(for those who are not familiar with Qt, here is the prototype of the last function:
void QGraphicsScene::addItem(QGraphicsItem *item);
I guess it just stores all items in internal index storage and calls QGraphicsItem::paint (...) when item needs to be repainted. I suppose QGraphicsScene doesn't make any significant changes to this item).
So my problems start when I run the program and click on an item on the screen. TestScene::mousePressEvent is called (see a piece of code above).
Mouse click position is retrieved, item is found. Casting works fine: in the debugger window (I'm using Qt Creator) I see that obj points to ExtendedPolygon (address is the same as when I add the item to the scene and in the debugger window I can see all the fields). But when I get some field, I receive garbage in any case (and it does not matter, what I'm trying to get - a QString or a pointer to some other structure).
So first of all, I would like to get any advice about my multiple inheritance. In 95% of cases I try to avoid it, but here it is very effective in the programming point of view. So I would appreciate it if you provide me with your point of view about the architecture of the classes hierarchy - does it even suppose to work as I expect it?
If on this level everything is quite fine, then it would be great if someone gets any idea why doesn't it work.
I have some ideas about workaround, but I really would like to solve this problem (just in order not to repeat the same error anymore).
Looks like I've found the root cause of my problem. It was just lack of knowledge regarding how multiple inheritance really works on data layer.
Let's assume that we have 2 basic classes, A and B. Each of them provides some internal data fields and some interfaces.
Then we create a derived class AABB, inheriting both A and B:
class AABB : public A, public B {...}
AABB could add some additional data fields and reimplement some of the interfaces, but it is not necessary.
Let's create and object of class AABB:
AABB* obj = new AABB ();
For example, obj points at address 0x8416e0. At this address starts data from ancestor class A. Data from ancestor class B starts with some offset (it should bw equal to sizeof (A)), for example, at 0x841700.
If we have some function f (B* b), and if we pass a pointer at AABB object to that function (like this: f (obj), obj is created above), actually not obj start address is passed, but rather a pointer at a start of B data section of AABB object.
Thus this misunderstanding of multiple inheritance inner works has led me to the problem I've got.
I guess Qobjects and multiple inheritance has been already treated. As an example: QObject Multiple Inheritance
Im using C++ and SDL to program a game, and even though I get no errors whenever I try to run it - I get a segmentation fault. I ran the gdb debugger and this is what it gave me when I used the backtrack function : "#0 main () at main.cpp:10" , where the 10th line is the statement right after the try block opens. Can someone tell me what is going on here, Ive never encountered such an error before.
Maybe you are creating the SDL_Surfaces for bgSurface and fgSurface before calling SDL_Init...
That's why I have the call to SDL_Init in a class constructor, by itself (and SDL_Quit in the constructor). That way you can just make Manager a private subclass of that one:
class Manager : private SDLInitializer
{ /* */ }
And in the constructor:
Manager::Manager() :
SDLInitializer(SDL_INIT_VIDEO),
/* */
And since base classes are initialized before member variables, all goes well!
I got 2 classes:
- MainWindow (Was the default class)
- ExtraClass (That i created myself)
Inside the class MainWindow i've made a public function called "logger". This function looks like this:
// Takes in a QString and appends it to a QTextEdit.
void MainWindow::logger(QString Log_MSG)
{
ui->Logg->append(Log_MSG);
}
This logger functions works out as expected inside its own Class MainWindow but when i try to pass in a MSG into logger from the class ExtraClass, it suddenly doesn't work.
My approach to accessing logger from MainWindow to ExtraClass:
MainWindow Con;
Con.logger("The Message the will get appended to ui->logg");
So the question, what have i missed? I don't get any errors and the text "Log_MSG" that should be appended to the QTextEdit Log don't execute.
Sorry for the style, i just don't understand how to get it to look good.
EDIT:
I've already tried to access other functions from "MainWindow class"
and that works but when i try to pass a string this particuallry function "logger"
from another class nothing happens.
For an instance:
MainWindow MainWindow;
int ANumber = MainWindow.GiveMeAValue(); // This works
But when i'm doing this:
MainWindow MainWindow;
MainWindow.logger("Log MSG"); // This dosen't work
My guess is that the problem lies in the appendment of
a QString passed in into the main class that was automatically created by Qt (have stuff like ui->abc) from another class. But in my current
level of understandment of Qt i don't really know where to
troubleshoot beocuse i don't even get an error.
Your code to access the logger is wrong (it shouldn't even compile).
First, everytime you call the function where this code resides, you create a new local MainWindow object (Con). And then you try to call the method on the class and not on an object. If it is a static method (which I doubt, due to the use of ui), you would have to write MainWindow::logger(). If it is not a static method, then you need to call it on a specific MainWindow instance. But instead of creating a local MainWindow everytime, you should provide the correct application's MainWindow instance to your ExtraClass object.
If all this sounds alien to you, you should first look a bit deeper into fundamental C++ programming before delving into Qt.