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);
}
Related
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.
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() {}
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) {
...
}
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;
}
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.