Gtkmm application crashes when dereferencing window object - c++

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.

Related

Qt: application crashes when using QWidget::show()

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.

Make an object know what is happening inside a show function it's created

It's my first time using Qt IDE and I got stuck on a problem.
I have two classes that are connected through an interface. One is the ContrGeral and the other is the IAAutenticacao. The ContrGeral opens the main window. How can the class ContrGeral knows what's happening inside the show function that it has executed in order to make the class IAAutenticacao runs another window (or update it)?
I'm following the concept of interface, so I can't just put a sequential of actions inside the MainWindow class (created by ContrGeral). I need it to inform the ContrGeral somehow about the situation.
As the show function that opens the window don't return anything nor receive anything, I don't know what to do.
main.cpp
#include "windows.h"
#include "controladoras.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CntrGeral tela_inicial;
tela_inicial.mostra();
return a.exec();
}
controladores.h
#ifndef CONTROLADORAS_H
#define CONTROLADORAS_H
#include "interfaces.h"
#include "dominios.h"
#include "windows.h"
#include <QApplication>
#include <stdexcept>
using namespace std;
class CntrGeral {
private:
IAAutenticacao *cntrIAAutenticacao;
IAUsuario *cntrIAUsuario;
IAEventos *cntrIAEventos;
MainWindow inicial;
public:
void setIAAutenticacao(IAAutenticacao *);
void setIAUsuario(IAUsuario *);
void setIAEventos(IAEventos *);
void mostra();
};
void inline CntrGeral::setIAAutenticacao(IAAutenticacao *cntrIAAutenticacao) {
this->cntrIAAutenticacao = cntrIAAutenticacao;
}
void inline CntrGeral::setIAEventos(IAEventos *cntrIAEventos) {
this->cntrIAEventos = cntrIAEventos;
}
void inline CntrGeral::setIAUsuario(IAUsuario *cntrIAUsuario) {
this->cntrIAUsuario = cntrIAUsuario;
}
void inline CntrGeral::mostra() {
inicial.show();
}
#endif // CONTROLADORAS_H
The problem is at inicial.show(), once it is executed it does not return anything.
thanks in advance.
You need more knowledge about Qt signals and slots. read this before.
Then you can do the connections as follows:
First add slots in your class CntrGeral:
controladores.h
class CntrGeral {
...
public slots:
void onMainWindowPressButton();
...
}
Then connect and add the implementation of the slot:
controladores.cpp
CntrGeral::CntrGeral()
{
...
// connect for example "pushButton" (a QPushButton's object)
// Which is a member of your MainWindow's object "inicial"
connect(inicial.pushbutton, SIGNAL(release()),
this, onMainWindowPressButton());
...
}
CntrGeral::onMainWindowPressButton()
{
/** TODO after push button pressed **/
}
Hope it helps you.

QPixmap Image doesnt appear

Im new with Qt and im making a game in it. I want to display icon but after putting there some code i cant find it anywhere. Im confused because i dont get any errors, so im pretty sure that i just didnt add something. Help.
Combat.h file
#ifndef COMBAT
#define COMBAT
#include <QImage>
#include <QGraphicsPixmapItem>
class Combat: public QGraphicsPixmapItem{
public:
// constructors
//Combat(QPixmap *parent=NULL);
Combat(const QString x);
// setters/getters
void getOwner(QString x);
private:
QString owner;
};
Combat.cpp
#include "Combat.h"
#include <QGraphicsScene>
Combat::Combat(const QString x){
// draw graphics
setPixmap(QPixmap(x));
}
void Combat::getOwner(QString x){
owner = x;
}
#endif // COMBAT
Interface.h
#ifndef INTERFACE
#define INTERFACE
#include <QList>
#include "Hex.h"
#include "Combat.h"
class Interface{
public:
// constructors
Interface();
// getters/setters
QList<Hex*> getHexes();
void getOwner(int x);
// public methods
void placeHexes();
void placeCombat();
private:
void createHexColumn(int x, int y, int numOfRows);
QList<Hex*> hexes;
void createCombatIcon(int x, int y, QString z);
int owner;
};
#endif // INTERFACE
Interface.cpp
#include "Interface.h"
#include "Game.h"
extern Game* game;
Interface::Interface(){
}
QList<Hex *> Interface::getHexes(){
return hexes;
}
void Interface::placeHexes(){
createHexColumn(100,100,6);
}
void Interface::placeCombat()
{
createCombatIcon(100,100,":/grafika/atak_magiczny.png");
}
void Interface::createCombatIcon(int x, int y, QString z)
{
Combat* icon = new Combat(z);
icon->getOwner("player1");
icon->setPos(x,y);
game->scene->addItem(icon);
}
Im not sure where something is missing
I solved the problem by adding my graphics to resource file in Qt Creator...

Emitting a signal not working properly

I have a class called dosecalibration which contains dosecalibration.cpp and dosecalibration.h. The class is associated to a separate ui form. On the form, when a button is clicked, a signal is emitted.
There is a connection within main window to receive this signal, however it doesn't seem to be working. The code is as following:
dosecalibration.h :
#ifndef DOSECALIBRATION_H
#define DOSECALIBRATION_H
#include <QDialog>
#include <QDebug>
namespace Ui {
class dosecalibration;
}
class dosecalibration : public QDialog
{
Q_OBJECT
public:
explicit dosecalibration(QWidget *parent = 0);
~dosecalibration();
double dosefactor;
//bool dose;
private slots:
void on_useCharge_clicked();
void on_useCounts_clicked();
void on_pushButton_clicked();
// void on_pCSB_valueChanged();
// void on_countsSB_valueChanged();
signals:
void applydose();
private:
Ui::dosecalibration *ui;
};
#endif // DOSECALIBRATION_H
dosecalibration.cpp :
#include "dosecalibration.h"
#include "ui_dosecalibration.h"
dosecalibration::dosecalibration(QWidget *parent) :
QDialog(parent),
ui(new Ui::dosecalibration)
{
ui->setupUi(this);
ui->countsSB->setEnabled(false);
ui->countsSB->setValue(ui->pCSB->value()*100/9.6);
}
dosecalibration::~dosecalibration()
{
delete ui;
}
void dosecalibration::on_useCharge_clicked()
{
ui->countsSB->setEnabled(false);
ui->pCSB->setEnabled(true);
}
void dosecalibration::on_useCounts_clicked()
{
ui->pCSB->setEnabled(false);
ui->countsSB->setEnabled(true);
}
void dosecalibration::on_pushButton_clicked()
{
if(ui->useCharge->isChecked()){
dosefactor = ui->pCSB->value();
}
else if(ui->useCounts->isChecked()){
dosefactor = ui->countsSB->value();
}
emit applydose();
}
//void dosecalibration::on_pCSB_valueChanged()
//{
// ui->countsSB->setValue(ui->pCSB->value()*100/9.6);
//}
//void dosecalibration::on_countsSB_valueChanged()
//{
// ui->pCSB->setValue(ui->countsSB->value()*9.6/100);
//}
And mainwindow.h (only included the 'includes' and the slots):
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <AFE_variables.h>
#include <QMainWindow>
#include "FPGA/fpga.h"
#include "FPGA/okFrontPanelDLL.h"
#include "decoder.h"
#include "analysis.h"
#include "about.h"
#include "logfile.h"
#include "Graph/graphicsscene.h"
#include "Graph/graphdialog.h"
#include "Graph/qcustomplot.h"
#include "Graph/graphicsview.h"
#include "settingsdialog.h"
#include "dosecalibration.h"
#include <QFileDialog>
#include <QProgressBar>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QDialog>
#include <QDebug>
#include <math.h>
slots:
//Dose calibration
void InitialiseGraphsAfterDose();
void on_actionDose_Calibration_4_triggered();
//void doseCalibrationEnabled();
private:
//Initalisation
void onStart();
void AllocateMemory();
void ConnectFPGA();
bool CheckConnection();
Ui::MainWindow *ui;
okCFrontPanel *xem;
FPGA *fpga;
QProgressBar *progressBar;
QTimer *PlayTimer;
LogFile *logfiledialog;
LogFile *logfileanalysis;
QString LoadLogFilePath;
dosecalibration *dose;
and a snippet from graphing.cpp, which is a part of the main window class:
//connects for dose calibration
dose = new dosecalibration(this);
connect(dose,SIGNAL(applydose()),this,SLOT(InitialiseGraphsAfterDose()));
}
void MainWindow::InitialiseGraphsAfterDose()
{
apply_dose = true;
InitialiseGraphs();
qDebug() << apply_dose;
}
So the applydose() signal is emitted at the push of a button in the dosecalibration ui. The connect should mean that the value of apply_dose is sent to console, however nothing is displayed.
EDIT:
Placing the connect within an if statement to determine if it is truly connecting confirms that it is indeed working correctly.
//connects for dose calibration
dose = new dosecalibration(this);
if(connect(dose,SIGNAL(applydose()),this,SLOT(InitialiseGraphsAfterDose())))
{
qDebug() << "connect worked";
}
}
The code above successfully outputs the message confirming the connect.
Any idea?
Remove the multiple instances of dosecalibration, or make sure to connect each one of those, if you really need multiple instances.

Incomplete type C++

I get the following error when I try to execute this code segment : "Menu does not name a type".I know its something to do with the circular references, but for the life of me I can't figure out what. Also, menu, go, and manager are repeatedly giving errors. The code segments are posted below :
#ifndef GO__H
#define GO__H
#include <SDL.h>
#include <iostream>
#include <string>
using std::cout; using std::endl;
using std::string;
#include "ioManager.h"
#include "gui.h"
#include "clock.h"
#include "menu.h"
//class Menu;
class Go {
public:
Go ();
void play();
private:
SDL_Surface *screen;
Gui gui;
Menu menu;
void drawBackground() const;
Go(const Go&);
Go& operator=(const Go&);
};
#endif
Here's Menu :
#ifndef MENU_H
#define MENU_H
#include <SDL.h>
#include <iostream>
#include "ioManager.h"
#include "gui.h"
#include "clock.h"
#include "manager.h"
class Menu {
public:
Menu ();
void play();
private:
const Clock& clock;
bool env;
SDL_Surface *screen;
Gui gui;
Manager mng;
void drawBackground() const;
Menu(const Menu&);
Menu& operator=(const Menu&);
};
#endif
Manager :
#ifndef MANAG_H
#define MANAG_H
#include "go.h"
class Manager {
Go go;
//other code
}
Can you see where the problem is? Error message:
In file included from go.h:13:0,
from manager.h:33,
from manager.cpp:2:
menu.h:28:11: error: field ‘mng’ has incomplete type
manager.h includes go.h which includes menu.h which includes manager.h ...
The class Menu is being defined before it ever gets to the definition of class Manager.
However, class Menu needs a Manager but since the compiler doesn't know about Manager yet it doesn't know how big to make it.
You could forward declare class Manager and make the mng member of Menu a pointer or reference:
class Manager;
class Menu {
...
Manager* mng;
// or this:
//Manager& mng;
...
Here's a good explanation of circular references and how to fix them.
It appears you are missing the semicolon at the end of the declaration of your Manager class in manger.h.
You are also missing the #endif to close your include guard.