Gtkmm Window is blank, not showing any widgets or title - c++

I'm learning gtkmm in order to program Conway's Game of Life as a demo. Currently I'm trying to show two buttons in a header bar, and I'm following a tutorial, but nothing is showing up in the window. Here's my code:
Display.h:
#include <gtkmm/window.h>
#include <gtkmm/headerbar.h>
#include <gtkmm/button.h>
class Display : public Gtk::Window
{
public:
Display();
Display(int xSize, int ySize);
virtual ~Display();
private:
//child widgets
Gtk::HeaderBar mHeader;
Gtk::Button startButton;
Gtk::Button stopButton;
};
Display.cpp:
#include "Display.h"
Display::Display(int xSize, int ySize):
startButton("start"),
stopButton("stop"),
mHeader()
{
//set window properties
set_title("Conway's Game of Life");
set_size_request(xSize, ySize);
set_border_width(5);
mHeader.set_title("Game of Life");
//add to header bar
mHeader.pack_start(startButton);
mHeader.pack_start(stopButton);
//add header bar
add(mHeader);
//make everything visible
show_all();
}
Display::Display()
{
Display(600, 600);
}
Display::~Display() {}
Main.cpp:
#include "Display.h"
#include <gtkmm.h>
int main(int argc, char **argv)
{
auto app = Gtk::Application::create(argc, argv);
Display Window;
return app->run(Window);
}
I've been trying to fix this for quite a while and can't seem to figure it out. Any help would be greatly appreciated.

The problem is that you are not using constructor delegation correctly. Try to write your default constructor as follow instead:
Display::Display()
: Display(600, 600) // Delegate here, not in body...
{
}
and it should work. Note that this is a C++11 feature.

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: 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.

How to declared widget in file .cpp gtkmm

I have a simple gtkmm program like that:
File main.cpp:
#include "mainwindow.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
MainWindow window;
//Shows the window and returns when it is closed.
return app->run(window);
}
File mainwindow.h:
#include <gtkmm/window.h>
#include <gtkmm.h>
class MainWindow : public Gtk::Window {
public:
MainWindow();
virtual ~MainWindow();
protected:
Gtk::Label myLabel;
};
and file mainwindow.cpp:
#include "mainwindow.h"
#include <iostream>
//using namespace gtk;
MainWindow ::MainWindow():myLabel("this is Label")
{
add(myLabel);
show_all_children();
}
MainWindow::~MainWindow() {}
This code run ok. But now I want to declared a Label in file mainwindow.cpp like that:
#include "mainwindow.h"
#include <iostream>
MainWindow ::MainWindow():myLabel("this is Label")
{
Gtk::Label myLabel2("this is label 2");
add(myLabel2);
show_all_children();
}
MainWindow::~MainWindow() {}
The Label don't show when I run this code, can someone tell me what wrong? Thank for your help!
The label doesn't show up, because it's destroyed at the end of the scope (i.e. at the end of the constructor).
To avoid this, you need to allocate Label on the heap. However, to avoid memory leak, you should use Gtk::manage function, so the memory of the label will be managed by the container [1].
Gtk::Label* myLabel2 = Gtk::manage(new Gtk::Label("this is label 2"));
add(myLabel2);
show_all_children();
[1] https://developer.gnome.org/gtkmm-tutorial/stable/sec-memory-widgets.html.en#memory-managed-dynamic
You have two problems here. First myLabel2 goes out of scope have the end of your constructor and is destroyed. The second is Gtk::Window as a single item container and can only hold one widget.
The solution for myLabel2 going out of scope is to allocate it on the heap see #Marcin Kolny answer. Or construct it similar to how you have done with myLabel.
For the second issue a multi-item container needs to be added to your Gtk::Window, then you can add your other widgets to that. This container can be a Gtk::Box, Gtk::Grid, etc... It depends on your needs.
One of many possible solutions is:
mainwindow.h
#include <gtkmm.h>
class MainWindow : public Gtk::Window {
public:
MainWindow();
virtual ~MainWindow();
protected:
Gtk::Box myBox;
Gtk::Label myLabel;
Gtk::Label myLabel2;
};
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow():
myLabel("this is Label"), myLabel2("this is label 2");
{
add myBox;
myBox.pack_start(myLabel);
myBox.pack_start(myLabel2);
show_all_children();
}
MainWindow::~MainWindow() {}

Can't add multiple buttons to window in gtkmm?

I am still new to using widget toolkits, but I really think this should work. I copied this code from developer.gnome.org and added my own object (button2) to the Buttons class , but only the original m_button shows in the window. The contents of buttons.h:
#ifndef GTKMM_EXAMPLE_BUTTONS_H
#define GTKMM_EXAMPLE_BUTTONS_H
#include <gtkmm/window.h>
#include <gtkmm/button.h>
class Buttons : public Gtk::Window
{
public:
Buttons()
{
m_button.add_pixlabel("info.xpm", "hi");
button2.add_pixlabel("info.xpm", "hello");
set_title("Pixmap'd buttons!");
set_border_width(10);
m_button.signal_clicked().connect( sigc::mem_fun(*this,
&Buttons::on_button_clicked) );
add(button2);
add(m_button);
show_all_children();
}
virtual ~Buttons()
{
}
protected:
//Signal handlers:
void on_button_clicked()
{
}
//Child widgets:
Gtk::Button button2;
Gtk::Button m_button;
};
#endif //GTKMM_EXAMPLE_BUTTONS_H
contents of main.cpp:
#include "buttons.h"
#include <gtkmm/application.h>
int main(int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app =
Gtk::Application::create(argc, argv,
"org.gtkmm.examples.base");
Buttons buttons;
return app->run(buttons);
}
I'm currently also learning Gtkmm, so this might not be the best answer, but I think that the correct way of doing that would be to add Gtk::Box object and then add Gtk::Buttons to the Gtk::Box
This is how I've done it. Also I have split your header gtkmm_example_buttons.h into gtkmm_example_buttons.hpp and gtkmm_example_buttons.cpp also I've changed button name m_button to button1 to match button2 name because of the consistency.
//gtkmm_example_buttons.hpp
#pragma once //used instead of the ifdef
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
class Buttons : public Gtk::Window
{
public:
Buttons();
virtual ~Buttons();
protected:
void on_button_clicked();
Gtk::Button button1, button2;
Gtk::Box box1;
};
Also I've removed signal handling because they would just make code more complicated. You will learn more about it later.
//gtkmm_example_buttons.cpp
#include "gtkmm_example_buttons.hpp"
#include <gtkmm/window.h>
#include <gtkmm/button.h>
#include <gtkmm/box.h>
Buttons::Buttons()
{
button1.add_pixlabel("info.xpm", "hi");
button2.add_pixlabel("info.xpm", "hello");
set_title("Pixmap'd buttons!");
set_border_width(10);
add(box1);
box1.pack_start(button1);
box1.pack_start(button2);
show_all_children();
}
Buttons::~Buttons()
{
}
void Buttons::on_button_clicked()
{
}
And main:
//main.cpp
#include "gtkmm_example_buttons.hpp"
#include <gtkmm.h>
int main (int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.test");
//Shows the window and returns when it is closed.
Buttons buttons;
return app->run(buttons);
}

qt openGL - draw triangle

So my goal is to (first) draw a triangle with openGL.
my questions:
1) How/when do both of my functions get called? I see that only one gets called. i.e. void MyGLWidget::paintGL. I am confused because as you can see I never call this function, it gets called automatically.I added a widget on my ui which I promoted to MyGLWidget. But when/why/how does it get (not) called?
my code:
myglwidget.cpp
#include "myglwidget.h"
#include <QtWidgets>
#include <QtOpenGL>
#include <GL/glu.h>
MyGLWidget::MyGLWidget(QWidget *parent)
: QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
}
void MyGLWidget::initializeGL()
{
glClearColor(1,1,0,1);
qDebug("init"); //<-------never gets printed
}
void MyGLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
qDebug("painting"); //<---- does get printed
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0);
glVertex3f(0.5,-0.5,0);
glVertex3f(0.0,0.5,0);
glEnd();
}
myglwidget.h
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QGLWidget>
class MyGLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
private:
};
#endif // MYGLWIDGET_H
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowTitle("OpenGL with Qt DAO");
w.show();
return a.exec();
}
I do not see a class called Widget made by you which is connected to the class MyGlWidget. Maybe I am wrong but shouldn't you have to make a instance of MyGlWidget (Call it's constructor instead of Widget?)
Both functions are called internally by the QGLWidget super class. See QT Docs
In the documentation you also see that these virtual functions are protected. In your code they are public. So you have to change that in order to make it work.