Qt: application crashes when using QWidget::show() - c++

I know that this type of problem has been reported before, but the answers weren't helpful to me. This is the code situation:
// main.cpp
#include <QApplication>
#include "game.h"
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
Game game;
game.show();
return app.exec();
}
// game.h
#ifndef GAME_H
#define GAME_H
#include "scene.h"
class Game {
public:
Game();
void show();
private:
GameScene scene;
};
#endif // GAME_H
// scene.h
#ifndef SCENE_H
#define SCENE_H
#include "GraphicsManager.h"
struct GameScene {
static GraphicsManager<MainWindow> window() { return win; }
private:
static GraphicsManager<MainWindow> win;
};
#endif // SCENE_H
// game.cpp
#include "game.h"
Game::Game() {
scene.window().render();
}
void Game::show() {
qDebug() << "crash test before show";
scene.window().view()->show(); // crashes here
qDebug() << "crash test after show";
}
// GraphicsManager.h
#ifndef GRAPHICSMANAGER_H
#define GRAPHICSMANAGER_H
#include <QGraphicsScene>
#include <QGraphicsView> // inherits QWidget
#include <QGraphicsPixmapItem>
#include <QImage>
#include <QBrush>
template <typename T>
struct GraphicsManager {
void render() { static_cast<T*>(this)->render(); }
QGraphicsScene* scene() { return static_cast<T*>(this)->scene(); }
QGraphicsView* view() { return static_cast<T*>(this)->view(); }
};
struct MainWindow :
GraphicsManager<MainWindow> {
void render() {
m_scene = new QGraphicsScene(0, 0, 800, 800);
m_view = new QGraphicsView(m_scene);
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setFixedSize(800, 800);
}
QGraphicsScene* scene() { return m_scene; }
QGraphicsView* view() { return m_view; }
private:
QGraphicsScene* m_scene; // raw pointer is used here, since
QGraphicsView* m_view; // they both inherit QObject,
};
#endif // GRAPHICSMANAGER_H
Now admittedly I am very new to Qt in general, so it's possible that I don't understand some of its mechanics. But as you can see in the minimal code example above, I want to try to use CRTP when it comes to the graphics interface module, and according to my tests, everything works fine until the QWidget::show() method is called in Game::show(). Right after that call the application crashes.
The crash report message does not provide any useful information or hints as to why this happened. Does anyone have an idea of what I have done wrong?
EDIT: This is the compiler message:
11:05:06: Running steps for project test3...
11:05:06: Starting: "C:\CMake\bin\cmake.exe" --build C:/a_Skola/Programmeringsmetodik/space_invaders_testsite/build-test3-Desktop_Qt_6_4_1_MinGW_64_bit-Debug --target all
ninja: no work to do.
11:05:06: The process "C:\CMake\bin\cmake.exe" exited normally.
11:05:06: Elapsed time: 00:00.

Related

Qt crashes when trying to use static QGraphicsScene, QGraphicsView

I am trying to create a singleton game window class that I can use to add other items later on (such as player, enemy, bullet etc). This is the code:
#ifndef GAMEWINDOW_H
#define GAMEWINDOW_H
#include <QGraphicsScene>
#include <QGraphicsView>
class GameWindow {
public:
GameWindow();
static QGraphicsScene* scene();
static QGraphicsView* view();
private:
static QGraphicsScene* m_scene;
static QGraphicsView* m_view;
};
#endif // GAMEWINDOW_H
#include "gamewindow.h"
QGraphicsScene* GameWindow::m_scene = new QGraphicsScene(0, 0, 800, 600);
QGraphicsView* GameWindow::m_view = new QGraphicsView(m_scene);
GameWindow::GameWindow() {
m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_view->setFixedSize(800,600);
m_view->setBackgroundBrush(QBrush(QImage(":/images/space.png")));
m_view->show();
}
QGraphicsScene* GameWindow::scene() { return m_scene; }
QGraphicsView* GameWindow::view() { return m_view; }
// main.cpp
#include <QApplication>
#include "gamewindow.h"
int main(int argc, char* argv[]){
QApplication a(argc, argv);
// launch the game window
GameWindow win;
return a.exec();
}
But for some reason, the application crashes, and the compile output does not give any hints on why. It just says that the process exited normally. How can I solve this, or is this a stupid idea? I'm open to suggestions on alternative solutions.
I didn't know what to try, because my understanding of the underlying problem is very limited.

Qt undefined reference vtable

I made simple game to shot rectangle(class Bullet) from other rectangle(class MyRect). I have error undefined reference to 'vtable for bullet'. I have written that is connected with Q_OBJECT and moc.I can't resolve this problem.
Bullet.h
#ifndef BULLET_H
#define BULLET_H
#ifndef Q_MOC_RUN
#include <QGraphicsRectItem>
#include <QObject>
class Bullet: public QObject,public QGraphicsRectItem{
Q_OBJECT
public:
Bullet();
public slots:
void move();
};
#endif
#endif // BULLET_H
MyRect.h
#ifndef MYRECT_H
#define MYRECT_H
#include <QGraphicsRectItem>
class MyRect: public QGraphicsRectItem{
public:
void keyPressEvent(QKeyEvent* event);
};
#endif // MYRECT_H
Bullet.cpp
#include "Bullet.h"
#include <QTimer>
Bullet::Bullet(){
setRect(0,0,10,50);
QTimer * timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(move()));
timer->start(50);
}
void Bullet::move(){
this->setPos(x(),y()-10);
}
main.cpp
#include <QApplication>
#include <QGraphicsScene>
#include "MyRect.h"
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene * scene = new QGraphicsScene();
MyRect * rect = new MyRect();
rect->setRect(0,0,100,100);
rect->setFlag(QGraphicsItem::ItemIsFocusable);
rect->setFocus();
scene->addItem(rect);
QGraphicsView * view = new QGraphicsView(scene);
view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view->show();
return a.exec();
}
MyRect.cpp
#include "MyRect.h"
#include<QKeyEvent>
#include <QGraphicsScene>
#include "Bullet.h"
#include<QDebug>
void MyRect::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Left)
{
setPos(x()-10,y());
}
else if(event->key() == Qt::Key_Right)
{
setPos(x()+10,y());
}
else if(event->key() == Qt::Key_Up)
{
setPos(x(),y()-10);
}
else if(event->key() == Qt::Key_Down)
{
setPos(x(), y()+10);
}
else if(event->key() == Qt::Key_Space)
{
Bullet * bullet = new Bullet();
bullet->setPos(x(), y());
scene()->addItem(bullet);
}
}
I have written some similar error i Qt, but still i can't resolve my.Thank you very much for your attention.
I got the same kind of error with this statement in a base class.
virtual void setInitiator(QPainter* painter, QImage* image);
Undefined reference to 'vtable for FractalObject'
FractalObject is my base class.
I derive classes which use the member function but there is no implementation in the base class. To fix things all I had to do is this:
virtual void setInitiator(QPainter* painter, QImage* image) = 0;
I'm guessing the assignment to zero forces a vtable to be created that holds a null pointer to the member function. This simple assignment fixed everything for me.

Gtkmm application crashes when dereferencing window object

I am trying to create simple application with gtkmm but I'm having some problem.
Here's how it looks now:
Here's the code to generate it:
MyWindow.h:
#ifndef MYWINDOW_H_
#define MYWINDOW_H_
#include <gtkmm/window.h>
#include <gtkmm/frame.h>
#include "MyDrawingArea.h"
class MyWindow :public Gtk::Window {
public:
MyWindow();
virtual ~MyWindow() {}
private:
MyDrawingArea drawing_area;
};
#endif /* MYWINDOW_H_ */
MyWindow.cpp:
#include "MyWindow.h"
MyWindow::MyWindow() : drawing_area("Drawing area") {
set_title("My app");
set_border_width(10);
add(drawing_area);
drawing_area.draw_stuff_in_area();
show_all_children();
}
MyDrawingArea.h:
#ifndef MYDRAWINGAREA_H_
#define MYDRAWINGAREA_H_
#include <gtkmm/frame.h>
#include <gtkmm/drawingarea.h>
class MyDrawingArea : public Gtk::Frame {
public:
MyDrawingArea(const Glib::ustring& title);
virtual ~MyDrawingArea() {}
void draw_stuff_in_area();
private:
Gtk::DrawingArea area;
};
#endif /* MYDRAWINGAREA_H_ */
MyDrawingArea.cpp:
#include "MyDrawingArea.h"
#include <iostream>
#include <gtkmm/window.h>
MyDrawingArea::MyDrawingArea(const Glib::ustring& title) : Gtk::Frame(title) {
set_border_width(20);
add(area);
area.set_size_request(300, 250);
}
void MyDrawingArea::draw_stuff_in_area() {
Cairo::RefPtr<Cairo::Context> cr = area.get_window()->create_cairo_context(); // program crashes here!
// draw stuff with 'cr' here...
}
As the comment suggests, the program crashes when I try to create a Cairo::Context, though I don't think the Cairo::Context creation is the problem: Every dereferencing to the object returned by my_area.get_window() crashes the program!
Anyone know what's causing the problem?
Hi did you check the return value of area.get_window() because documentation says
Returns the widget’s window if it is realized, 0 otherwise.

Appcrash when i try to add QTabWidget with a button

i just started learning Qt few days ago, and i have a problem that i can't solve.
First there is the files :
main.cpp
#include <QApplication>
#include "test.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
test w;
w.show();
return a.exec();
}
test.h
#ifndef TEST_H
#define TEST_H
#include <QWidget>
#include <QTabWidget>
#include <QTextEdit>
#include <QPushButton>
class test : public QWidget
{
Q_OBJECT
public:
test();
~test();
private slots:
void addT();
private :
QTabWidget *tab;
QPushButton *b,*c;
};
#endif // TEST_H
and test.cpp
#include "test.h"
test::test()
{
QTabWidget *tab = new QTabWidget(this);
QPushButton *b = new QPushButton("Add",this);
tab->addTab(b,"test");
QObject::connect(b,SIGNAL(clicked()),this,SLOT(addT()));
}
test::~test()
{
}
void test::addT()
{
QPushButton *c= new QPushButton("Add",this);
tab->addTab(c,"test");
}
the program starts normally but when i push the button to add a new Tab it crashes
Please Help me!
In your constructor you are not assigning to the QTabWidget and QPushButton instanced declared in your header, but are creating two new instances (with the same name) that will be gone at the end of the scope. The tab instance is still a nullptr and when trying to derefence it in addT, your program will crash. You need to assign to the variables declared in test.h like this:
test::test() : tab(new QTabWidget(this), b(new QPushButton("Add", this) {
...
}

QT declare Mainwindow out of the main class

I have this two class in c++
GUI.cpp
#include "AL_GUI.h"
#include <QtGui/QApplication>
#include "mainwindow.h"
GUI::GUI() {
}
void GUI::startGUI(){
int c=1;
char *array[10];
char** v = &array[0];
QApplication qa(c,v);
w.show();
qa.exec();
}
void GUI::notifyAlert(){
}
GUI::~GUI() {
// TODO Auto-generated destructor stub
}
GUI.h
#include <QtGui/QApplication>
#include "mainwindow.h"
#include "mainwindow.h"
#ifndef GUI_H_
#define GUI_H_
class GUI {
public:
GUI();
virtual ~GUI();
void startGUI();
void notifyAlert();
private:
MainWindow w;
};
#endif
But when i run this program i have the error:
QWidget: Must construct a QApplication before a QPaintDevice
How can I declare MainWindow w in gui.h in such a way that I don't receive this error
You can't (well, you can, but you shouldn't). The MainWindon declaration is right where it should be. The problem is that you attempt to create a GUI object before you create the QApplication.
Why not create the QApplication where you create the GUI object, just before it?
I would have made w a pointer used a forward declaration for MainWindow and removed all the includes (including the 2 includes for mainwindow.h) from GUI.h. Then like the answer from Sebastian says construct the QApplication first.
AL_GUI.h
#ifndef GUI_H_
#define GUI_H_
class MainWindow;
class GUI {
public:
GUI();
virtual ~GUI();
void startGUI();
void notifyAlert();
private:
MainWindow* w;
};
gui.cpp
#include "AL_GUI.h"
#include <QtGui/QApplication>
#include "mainwindow.h"
GUI::GUI() : w(NULL)
{
}
void GUI::startGUI(){
int c=1;
char *array[10];
char** v = &array[0];
QApplication qa(c,v);
w = new MainWindow;
w->show();
qa.exec();
}
void GUI::notifyAlert(){
}
GUI::~GUI() {
delete w;
}