Invalid use of 'this' in non-member - c++

I have a problem - discussed a lot previously, but all solutions I saw doesn't work here.
What is wrong in this code?
main.cpp:8:19: error: invalid use of ‘this’ in non-member function
#include <QApplication>
#include <QPainter>
#include <math.h>
class QPainter;
int main(int argc, char *argv[]){
QApplication app(argc,argv);
QPainter painter(this);
painter.setPen(QPen(Qt::black,3));
int n=8;
for (int i=0;i<n;++i){
qreal fAngle=2*3.14*i/n;
qreal x = 50 + cos(fAngle)*40;
qreal y = 50 + sin(fAngle)*40;
painter.drawPoint(QPointF(x,y));
}
return app.exec();
}

In the function "main" you are using the reserved keyword "this" which means "address of the current object". main is a function and not a member of any class or object that would have a "this" variable. I know nothing about qt but 5 seconds with google tells me that "QPainter" wants the address of a QPaintDevice.
http://qt-project.org/doc/qt-5.0/qtgui/qpainter.html#QPainter

If you are talking about QPainter painter(this); you are using the this pointer in main. The this pointer is for member functions of an object. Your main function doesn't have a this pointer to use.

In Qt you need to create a window (inheriting from QWidget) before you can see anything on the screen. You then create a QPainter object inside the paintEvent method of your window and there you will have the proper this to pass to QPainter constructor.
You're highly encouraged to follow some tutorial. Qt is fantastic, but it's huge and it's not a library, but a framework (like most other GUIs).
Your code must be structured in a quite specific way.

You just tried to copy some code without understanding what was going on.
It looks like you saw a code like this :
#include <QtGui>
#include <QWidget>
class MyWidget : public QWidget
{
Q_OBJECT
public:
protected:
void paintEvent(QPaintEvent *event)
{
//create a QPainter and pass a pointer to the device.
//A paint device can be a QWidget, a QPixmap or a QImage
QPainter painter(this); // <- Look at this !!
// ^^^^ Allowed
// ...
}
signals:
public slots:
};
int main( int argc, char **argv )
{
QApplication app( argc, argv );
MyWidget myWidget;
myWidget.show();
return app.exec();
}
Here you can see that in the function paintEvent of the class MyWidget we use the this pointer. We can because we use it in a non-static member of the class. Here this is of type MyWidget*.
Look at the standard :
9.3.2 The this pointer [class.this]
In the body of a non-static member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*.
So you cannot use the this pointer inside the main function, this is no sense.
And other thing, like it is said in the comment inside the code, you just have to pass a pointer to a device to the QPainter constructor. It can be a QWidget, a QPixmap or a QImage.
Maybe you should read this for a beginning : http://www.cplusplus.com/doc/tutorial/classes/

Related

Qt GUI Easiest way to access MainWindow from another class

I am doing a blackjack program and I am keeping track of the cards in the players hand in another class ("hand.h") than the main window class.
In the hand class, for every card that I collect, I am also creating a QLabel that grabs the proper card image for the card and also sets the coordinates for where the card should appear on the main window.
The problem is that I am not able to create the QLabel based on the MainWindows object that is originally created at the main function. Is there any easy way that I am able to get that information fairly easily? Thanks for your help!
I have tried using QGuiApplication::topLevelWindows(), but haven't came to luck with using that. Here is my function that I am using.
#include <QRect>
#include <QApplication>
#include <iostream>
#include <QLabel>
#include "mainwindow.h"
#include <QMainWindow>
#include <QWindowList>
#include <QWidgetList>
#include "ui_mainwindow.h"
void Test() {
QList<QWindow*> Main_Window = QGuiApplication::topLevelWindows();
for (int i = 0; i < Main_Window.size(); ++i) {
if(Main_Window.objectName() == "mainWindow") // name is OK
break;
}
QMainWindow* mainWindow = static_cast<QMainWindow*>(Main_Window);
QLabel* temp;
temp = new QLabel(Main_Window);
temp->setPixmap(QString("Ten of Clubs.png"));
temp->setGeometry(290, 300, 350, 390);
temp->show();
}
Here is the main.cpp file that creates the mainwindow
int main(int argc, char *argv[])
{
srand(time(NULL));
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I found the iterating code online and have been having issues from it.
I am having issues while trying to iterate through the list, but I have no idea how to identify the list and the error says that there is no objectName() function. Also, in the static cast line, there is an error that says that I cannot convert an QList to type QMainWindow. Any help would be greatly appreciated.
No way in general, because some applications may have several (toplevel) QMainWindow-s (and their list could change with time). So for that case you'll better pass the pointer to it (the particular QMainWindow you want to deal with) explicitly....
A possible way might be to have your specific subclass of QApplication (which is a singleton class, see QCoreApplication::instance to get its sole instance) and in your application subclass put, as fields, the explicit windows you want to deal with (maybe you even want to add some new signal or slot to your application class).
However, you could use QGuiApplication::topLevelWindows() or QGuiApplication::allWindows() to get the list of all such windows. Notice that a QWindowList is just a QList<QWindow *>. So see QList for how to traverse or iterate on that list.
Once you have found which QMainWindow you want, adding a QLabel into it is usual practice (but again, signals & slots could be helpful).
BTW, each (displayed) widget has its window, see QWidget::window()
About your code:
Your Main_Window is really poorly named (and the name is so confusing that I cannot use that). It is a list not a window. So code first:
QMainWindow* mainWindow = nullptr;
{
QList<QWindow*> topwinlist = QGuiApplication::topLevelWindows();
int nbtopwin = topwinlist.size();
for (int ix=0; ix<nbtopwin; ix++) {
QWindow*curwin = topwinlist.at(ix);
if (curwin->objectName() == "mainWindow")
mainWindow = dynamic_cast<QMainWindow*>(curwin);
}
}
I did not test the above code and I am not sure it is correct or even can compile. But why don't you just have a global pointer to your main window:
MainWindow*mymainwinp = nullptr;
and initialize it appropriately in your main body:
int main(int argc, char *argv[]) {
srand(time(NULL));
QApplication a(argc, argv);
MainWindow w;
mymainwinp = &w;
w.show();
int r = a.exec();
mymainwinp = nullptr;
return r;
}
then use mymainwinp elsewhere (e.g. in your Test)? If you want more elegant code, define your own subclass of QApplication and have mymainwinp be a field in it.

Why are QWidgets accessed by pointers?

I am new to Qt5 and I am learning QWidgets to develop an application.
I've noticed in many examples, QWidgets are almost always accessed by pointer. For example:
#include <QApplication>
#include <QWidget>
#include <QFrame>
#include <QGridLayout>
class Cursors : public QWidget {
public:
Cursors(QWidget *parent = 0);
};
Cursors::Cursors(QWidget *parent)
: QWidget(parent) {
QFrame *frame1 = new QFrame(this);
frame1->setFrameStyle(QFrame::Box);
frame1->setCursor(Qt::SizeAllCursor);
QFrame *frame2 = new QFrame(this);
frame2->setFrameStyle(QFrame::Box);
frame2->setCursor(Qt::WaitCursor);
QFrame *frame3 = new QFrame(this);
frame3->setFrameStyle(QFrame::Box);
frame3->setCursor(Qt::PointingHandCursor);
QGridLayout *grid = new QGridLayout(this);
grid->addWidget(frame1, 0, 0);
grid->addWidget(frame2, 0, 1);
grid->addWidget(frame3, 0, 2);
setLayout(grid);
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Cursors window;
window.resize(350, 150);
window.setWindowTitle("Cursors");
window.show();
return app.exec();
}
This is taken from the tutorial: http://zetcode.com/gui/qt5/firstprograms/
Yet, on the same page, I see that we can access the QWidget base class by its object itself:
#include <QApplication>
#include <QWidget>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QWidget window;
window.resize(250, 150);
window.setWindowTitle("Simple example");
window.show();
return app.exec();
}
Why is it necessary to access all QWidget derived classes by their pointer? Why isn't it necessary to access QWidget itself by its pointer?
It's all about object's lifetime and shared ownership. If you create an object on stack in function, it will be destroyed when scope ends.
Why isn't it necessary to access QWidget by pointer in your example? Just because when main() 'ends', your program is finished, and widget may be destroyed.
Why is it necessary to access QWidget's children by pointer? Because if you want to ask QWidget to give you access to it's child, it can't give you a value, because it would be just a copy of an object. Moreover, if you pass a large object by value to QWidget, it needs to copy your object.
This is not specific to QWidgets: it is so for every QObjects (Qt fundamental base class, from which everything else is derived).
It is the consequence of a design choice of the Qt framework. Quoting Qt documentation:
QObject has neither a copy constructor nor an assignment operator.
This is by design.
[...]
The main consequence is that you should use
pointers to QObject (or to your QObject subclass) where you might
otherwise be tempted to use your QObject subclass as a value. For
example, without a copy constructor, you can't use a subclass of
QObject as the value to be stored in one of the container classes. You
must store pointers.
Source:
http://doc.qt.io/qt-5.5/qobject.html#no-copy-constructor
The rationale for this choice is explained here:
http://doc.qt.io/qt-5.5/object.html#identity-vs-value
QClasses are larger in size and you don't want to fill up your stack memory by instantiating them in stack memory.
When you instantiate derived class objects it also runs constructor of a base class ( derived class + base class ) memory is required,
On the other hand QWidget only inherits QObject and QPaintDevice as you can see here
So it will be less overhead to create QWidget object on stack memory.
You must be very careful when you are using heap memory, read the answers on memory management
You can study the difference between stack and heap from here

Must construct a QApplication before a QWidget

Everywhere only just "before QPaintDevice" questions and nowhere is my error. So, here we go.
I need an extern QWidget to be able to get access to it from outside (because I don't know any other ways to do it). Basically, I need this: Create 2 QWidgets from 1 window, go to first window and from there hide main window and show second window created by main window (although main window is not main(), it is QWidget too).
I added
extern QWidget *widget = new QWidget
everywhere and everyhow in possible ways, and I still got this message. I suppose, it means that I need to create my QApplication (in main.cpp) and only then declare any QWidgets. But then HOW can I access those QWidgets from another QWidgets?
Code is here:
https://github.com/ewancoder/game/tree/QWidget_before_QApp_problem
P.S. The final goal is to be able show and hide both gamewindow.cpp and world.cpp from battle.cpp (just regular class)
And btw, adding Q_OBJECT and #include both don't work.
Anyway, if I cannot use functions from one window to another, than what's the point? I can have one window in another, and then another in that one, and then one in that another... but I can't do anything from the last to the previous. After years on Delphi that seems strange to me.
Don't use extern or otherwise static variables which lead to creation of the widget before the QApplication is created in main. The QApplication must exist before the constructor of the QWidget is executed.
Instead of sharing the variable via extern, either make the other windows members of the main window, and then make the windows known to each other by passing around pointers, or keep them private in MainWindow and request the actions from the subwindows e.g. via signal/slots. As a generic rule, don't use global variables but class members.
In the following FirstWindow (which is supposed hide main window and secondWindow) gets the main window and the second window passed via pointers and then just calls show/hide on them directly.
int main(int argc, char **argv) {
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
In main window, have two members for the two other windows, say FirstWindow and SecondWindow:
class MainWindow : public QMainWindow {
...
private:
FirstWindow *m_firstWindow;
SecondWindow *m_secondWindow;
};
MainWindow::MainWindow(QWidget *parent) {
m_firstWindow = new FirstWindow; //not pass this as parent as you want to hide the main window while the others are visible)
m_secondWindow = new SecondWindow;
m_firstWindow->setMainWindow(this);
m_firstWindow->setSecond(m_secondWindow);
m_firstWindow->show(); //Show first window immediately, leave second window hidden
}
MainWindow::~MainWindow() {
//Manual deletion is necessary as no parent is passed. Alternatively, use QScopedPointer
delete m_firstWindow;
delete m_secondWindow;
}
FirstWindow, inline for brevity:
class FirstWindow : public QWidget {
Q_OBJECT
public:
explicit FirstWindow(QWidget *parent = 0) : QWidget(parent) {}
void setMainWindow(MainWindow *mainWindow) { m_mainWindow = mainWindow); }
void setSecondWindow(SecondWindow *secondWindow) { m_secondWindow = secondWindow; }
private Q_SLOTS:
void somethingHappened() { //e.g. some button was clicked
m_mainWindow->hide();
m_secondWindow->show();
}
private:
MainWindow* m_mainWindow;
SecondWindow* m_secondWindow;
};
Maybe not helping the former author, but others facing the problem.
I simply got this error by mistaking a debug-library with a release one. So check your linker settings, if you are sure the implementation is done right (first instancing application and then using widgets).

Qt: maximized frame

I have a beginner question. I'm trying to create a maximized QFrame with the following code but I'm receiving an error which says:
error C3867: 'QWidget::showMaximized': function call missing argument list; use '&QWidget::showMaximized' to create a pointer to member
Code:
class FrameWindow{
private:
QDesktopWidget *desktop;
QFrame frame_window;
QRect frame_rect;
public:
FrameWindow(QApplication& app){
desktop = app.desktop();
desktop->showMaximized;
frame_window.setWindowTitle("QT Trainning");
frame_window.show();
}
I'm totally beginner in C++, so what I'm missing please?
functions/methods generally need argument list, even an empty one -> object->method() Try using brackets.
You eventually want:
w->setWindowState(w->windowState() | Qt::WindowFullScreen);
Edit:
or as your solution:
w->setWindowState(w->windowState() | Qt::WindowMaximized);
In addition to what others have already noticed, it's completely counterproductive to pass either the current application or to hold a pointer to the desktop. The application pointer is always available via the global qApp macro. To get the desktop, simply use
qApp->desktop()
There is absolutely no reason to "cache" this value. Get it whenever you need it, that's all.
It'd be also more idiomatic to derive from the widget type, instead of holding it as a member. The code could be simplified as below. It is a complete, self-contained example.
#include <QFrame>
#include <QApplication>
class FrameWindow : public QFrame {
public:
FrameWindow(QWidget * parent = 0, Qt::WindowFlags * flags = 0) :
QFrame(parent, flags)
{
setWindowTitle("Qt Training");
setWindowState(windowState() | Qt::WindowMaximized);
}
};
int main(int argc, char ** argv) {
QApplication app(argc, argv);
FrameWindow fw; // constructor is called here
fw.show();
return app.exec();
// FrameWindow::~FrameWindow() destructor is called first before exiting
// QApplication::~QApplication() destructor is called next
}

Don't understand why I can't call setCentralWidget in QMainWindow subclass

//clposter.h
class CLPoster : public QMainWindow
{
Q_OBJECT
public:
CLPoster();
private slots:
QWidget createCentralWidget();
void createActions();
void createMenu();
void createStatusBar();
void loadSavedPosts();
};
//clposter.cpp
CLPoster::CLPoster()
{
setWindowTitle("Craigslist Poster");
QWidget mainWidget = createCentralWidget();
setCentralWidget(mainWidget);
// createActions();
// createMenu();
// createStatusBar();
// loadSavedPosts();
// checkForActionsNeeded(); //May want to break up into more functions
}
The error I'm getting is this:
/usr/include/qt4/QtGui/qwidget.h:: In constructor ‘CLPoster::CLPoster()’:
/usr/include/qt4/QtGui/qwidget.h:787: error: ‘QWidget::QWidget(const QWidget&)’ is private
/home/brett/projects/CLPoster/CLPoster-build-desktop/../CLPoster/clposter.cpp:9: error: within this context
/home/brett/projects/CLPoster/CLPoster-build-desktop/../CLPoster/clposter.cpp:10: error: no matching function for call to ‘CLPoster::setCentralWidget(QWidget&)’
/usr/include/qt4/QtGui/qmainwindow.h:141: candidates are: void QMainWindow::setCentralWidget(QWidget*)
I'm having trouble interpreting the error message. It says there is no matching function call, but it should be inheriting it from QMainWindow. It could just be a lack of understanding C++ more so than QT, first time I've used it, but dunno. Thanks for the help.
All QWidget items must be allocated in the free-store (new) since they all have to have "parents". In Qt a parent will delete its children (with delete). This is why any function returning, accepting, whatever a widget is going to do so on a pointer to a widget, not the widget itself; you need to do the same.
The setCentralWidget function expects that you are sending a pointer to a QWidget (QWidget*), whereas you are trying to send the actual object (or a reference to the object, QWidget&, as implied by the compiler error) in your code. If you create your central widget as a pointer (change the member function to QWidget* createCentralWidget()) and pass the pointer to the setCentralWidget function you should be good to go.
e.g.
QWidget* CLPoster::createCentralWidget()
{
QWidget* w = new QWidget;
// Do stuff..
return w;
}
Then in your constructor, you can just call setCentralWidget(createCentralWidget()). The QMainWindow destructor will ensure that your central widget is deleted.
Don't you need to allocate the Widget on the heap and pass a pointer to setCentralWidget()