PDA

View Full Version : How to pass a pointer to a "QMainWindow" subclass in a function ?



AtlasS
22nd December 2012, 13:15
Hello

I want to access a function inside a custom QMainWindow (subclass that inherits QMainWindow), I called the class "BMW" (basic main window).

public :
void AccessFunction(BMW*);

when I try to pass the pointer to the BMW object, I get an error (BMW has not been declared).
note that the class which (accessFunction(BMW) ) method is in, is a foreign class, but an object of the class is inside BMW as an instance.

Strange enough, this method works with other classes ; thus it can communicate easily & trigger foreign functions smoothly.

Any help ? :/

amleto
22nd December 2012, 15:26
As a precursor I will just say that you have poor design and you shouldn't need to write code like that!!

To deal with your actual problem that has nothing to do with qt (and so this is the wrong forum for your question...) :

In your foreign class cpp file you need to #include "bmw.h" or whatever header contains your BMW class.
In your foreign class hpp file you need to forward declare the class

e.g.


class BMW;

class foreignclass
{
public:
void use_bmw(bmw* ptr);
};

AtlasS
22nd December 2012, 17:38
As a precursor I will just say that you have poor design and you shouldn't need to write code like that!!

To deal with your actual problem that has nothing to do with qt (and so this is the wrong forum for your question...) :

In your foreign class cpp file you need to #include "bmw.h" or whatever header contains your BMW class.
In your foreign class hpp file you need to forward declare the class

e.g.


class BMW;

class foreignclass
{
public:
void use_bmw(bmw* ptr);
};



Thank you very much for your comment, It was helpful.
Excuse me for rejecting your judgement on my design, but I simply forgot to declare the class BMW in my foreign class, but that's still not the problem.

The class won't take BMW* as a parameter. Here are the points in the code where the problem is


InterfaceHndler.h >>Foreign class

#ifndef INTERFACEHNDLER_H
#define INTERFACEHNDLER_H

#include <bmw.h>
#include <KnightsComponent.h>
#include <scene.h>
#include <scenemainmenue.h>
#include <QGraphicsView>

class InterfaceHndler
{
class BMW;
public:
InterfaceHndler();

QGraphicsView *boardHndler;
Scene *chessBoard;

SceneMainMenue *MW;
QImage *Logo;
QGraphicsView *display;
QGraphicsScene *displayScene;
KnightsComponent *button_ng;



void buildMm(BMW*);
void buildGame();
};

#endif // INTERFACEHNDLER_H


BMW.h file


#ifndef BMW_H
#define BMW_H
#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <interfacehndler.h>


class BMW : public QMainWindow
{
//Member variables

public:
InterfaceHndler Ih;



public: BMW();




};

#endif // BMW_H



I followed this methodology of design to allow my mouse event inside my (SceneMainMenue *MW) variable to respond to custom button clicking, and build other scenes in my main window class. I don't think that my design is poor, it's only a matter of making the BMW ptr works as a parameter....

I didn't modify the code, I just encapsulated the components into the interfaceHandler class. All I need is to know how to pass my BMW ptr as a parameter into the interface handler class, so I can manage button clicking..

the problem is not my design. The problem isn't Qt. The problem is simply that QGraphicsScene's mouse event is local.. I'm just trying to escape that locality by simple object communication.

It worked with simpler classes, but failed with QMainWindow subclasses (Any subclass from QMainWindow).

Added after 4 minutes:

I edited the following :

1-Functions are no longer reside in BMW ; they are defined in the interface handler.
2-The interfaceHndler class can manage the adding & deleting of elements from/ to the main window by receiving a pointer to to that window as a parameter in its native functions

Added after 5 minutes:

BTW, I don't want a simple solution like (adding a main QGraphicsScene) to the main window first, and implementing the mouse event in it, because all I want is simply allowing different objects in different classes to communicate by adding pointers the the destination class through a function.

I just want to know why I can't pass a QMainWindow as a pointer..

lol, sorry for talking too much, but I'm a student, and I need to learn..

amleto
22nd December 2012, 18:00
I have not stated that 'the problem' is your design, but you have a circular reference which is nearly always poor design.


The class won't take BMW* as a parameter. Here are the points in the code where the problem is.
The class does take BMW*, look


void buildMm(BMW*);
:confused:

Please explain what the problem is.


I just want to know why I can't pass a QMainWindow as a pointer..You can.

AtlasS
22nd December 2012, 18:08
I have not stated that 'the problem' is your design, but it certainly is poor - you have a circular reference.


The class does take BMW*, look


void buildMm(BMW*);
:confused:

Please explain what the problem is.

You can.

The error still appears whenever I call
Ih.buildMm(this); inside BMW.

amleto
22nd December 2012, 18:10
didn't I mention circular reference already? you cannot have this line

#include <bmw.h>

in your interface class header.


And another point - when using <> brackets on includes, you are telling the compiler to look in implementation (compiler implementation) defined paths first - this is not correct! for your own source code files you should use normal quotes e.g. "myfile.cpp"

wysota
23rd December 2012, 10:59
Graphics Scene events are not "local". As every event the event is meant to be delivered to only one object. If the object rejects it, the event gets delivered to an item under the original item (and so on). Furthermore in Graphics View architecture you have a possibility to catch the event in any of three places:
1. the item the event is meant to be delivered to,
2. the scene containing the item,
3. the view the event (e.g. pressing the mouse button) was triggered on.

So if you catch the event in the scene, there is no "locality" here, you can access any item in the scene you want or handle the event globally.

The design you have is poor. It's very C-ish and breaks some OOP principles (like encapsulation). I don't know what you are trying to do but there is a number of design patterns (e.g. the Builder or Factory or maybe even Strategy) that you could use.

E.g. instead of void "buildMw(BMW*)" you could have a "SomeType* buildMw() const" method.

AtlasS
23rd December 2012, 12:00
amleto

Thanks again for your patience : ), I have fixed the mistakes you pointed at in the including of files. I have to admit that the design IS POOR as you have stated, I'm going to start things up from scratch (not the whole code, only the interface part). I need to study the mechanisms of the qt classes more, because obviously I'm confused a little..well, maybe a lot ..

wysota

I'm trying to design a main screen for my chess program. I have already finished the games (full 2 player chess game), defined over 3 classes :

class ChessElement ->QGraphicsItem
class board ->nothing
class Scene ->QGraphicsScene

all the ChessElement instances are added to "Scene *x".

now, having this scene set & ready, I need one main window, starts with a scene added to it (representing the main menu), then I have buttons, which are from a subclass inherits QGraphicsItem (same like chessElement).

All I need now to present the full program is to build the interface -_-", kinda frustrating since I thought it's the easiest part. The whole problem is in the custom buttons, if I used the QPushButton I would've ended this suffering, but it looks ugly :/ I'm not using that :p

I will try to implement what you have wrote in your comment, joining it with what amleto said.

But please, if there is anything I can read (outside the qt documentation) which might solve my problem, post it here. Since the final exams in my academy are up, I don't have a lot of time to read for my personal projects..One of the main reasons while my design is poor + lacks for concentration.

best regards

d_stranz
23rd December 2012, 17:50
Your problem *still* boils down to a C++ problem. The code you posted:



class InterfaceHndler
{
class BMW;
public:
//...


is declaring that there is a class, called "BMW" that is an embedded class defined within the scope of the class InterfaceHndler. This means that the name of that class, as far as C++ is concerned, is InterfaceHndler::BMW. And as far as C++ is concerned, that class is totally different from a class named BMW that might be declared in your bmw.h header file as existing at global scope. Therefore, within InterfaceHndler, the declaration of the embedded class BMW overrides any declaration of a globally scoped class BMW, which means the method you have defined is expecting to receive a pointer to an InterfaceHndler::BMW * instance, not a BMW * instance. You are obviously trying to pass a BMW * instance, which the compiler is telling you is not acceptable.

The solution is easy; move the class BMW forward declaration:



class BMW;

class InterfaceHndler
{
public:
//...