I simply want to know which size a widget has. I need this info to set a ScrolledWindow to a maximum size if the size of the widget is bigger than the screen.
But all functions I know give a constant value of 1.
#include <iostream>
#include <gtkmm.h>
#include <gtkmm/window.h>
class ExampleWindow: public Gtk::Window
{
Gtk::Button button;
public:
ExampleWindow(): button("Hallo")
{
add(button);
GetSize();
}
void GetSize()
{
std::cout << button.get_width() << " " << button.get_height() << std::endl;
std::cout << button.get_allocated_width() << " " << button.get_allocated_height() << std::endl;
}
};
int main(int argc, char* argv[])
{
Gtk::Main kit(argc, argv);
ExampleWindow window;
window.GetSize();
window.show_all_children();
window.GetSize();
Gtk::Main::run(window);
return 0;
}
This looks a lot like this answer.
Basically it says that before the get_height() and get_width() methods return meaningful values, the widget must be realized. Since you are calling these (through your GetSize() wrapper) inside the window constructor, it (the button inside the window) might not yet be realized, hence the wrong values.
BONUS
According to this ticket:
Realize means to create the GDK resources for a widget. i.e. to
instantiate the widget on the display.
Also, to clarify the meaning of the word realize, see this. The author seems to have done some interesting research on the subject to clarify the documentation.
Related
The goal is to connect GTK+ signals to non-static class methods using libsigc++ without gtkmm. I want to use the Glade user interface designer to design a non-trivial UI with many views, comparable to a setup wizard. The UI should be portable (Embedded Linux and Windows). So, I want to reduce the dependencies and use the C GTK+ only without the C++ language binding component gtkmm, but the UI should be written in C++. The MVC pattern should be applied to separate the responsibilities and for decoupling. As a result, my C++ views and other classes have to connect their signal handlers to the GTK+ C signals using g_signal_connect(). Later they have to use g_signal_handlers_disconnect_by_func() to disconnect the handlers. The following example demonstrates the problem:
File: GladeProgram.h
#ifndef _GLADEPROGRAMM_H
#define _GLADEPROGRAMM_H
#include "gtk/gtk.h"
class GladeProgram
{
public:
GladeProgram(int argc, char *argv[]);
virtual ~GladeProgram();
void Run();
void Exit();
};
#endif // !_GLADEPROGRAMM_H
File: GladeProgram.cpp
#include "GladeProgram.h"
#include "sigc++/sigc++.h"
GladeProgram::GladeProgram(int argc, char *argv[])
{
gtk_init(&argc, &argv);
}
GladeProgram::~GladeProgram()
{
}
// C-style callback method with object pointer
void onExit(GladeProgram* pProg)
{
pProg->Exit();
}
void GladeProgram::Run()
{
GtkBuilder *builder;
GtkWidget *window;
builder = gtk_builder_new_from_file("window_main.glade");
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
// C-style signal handler with object pointer
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(onExit), this);
// PROBLEM: Howto connect non-static class method GladeProgram::Exit() with libsigc++ ???
// g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK( ??? ), NULL);
g_object_unref(builder);
gtk_widget_show(window);
gtk_main();
}
void GladeProgram::Exit()
{
gtk_main_quit();
}
File: Main.cpp
#include <iostream>
#include "GladeProgram.h"
using namespace std;
int main(int argc, char *argv[])
{
std::cout << "**********************************************************************" << endl;
std::cout << "* GTK+ Test UI *" << endl;
std::cout << "**********************************************************************" << endl;
GladeProgram prog(argc, argv);
prog.Run();
// wait until the Enter key is pressed
cout << endl << "Press [Enter] to exit." << endl;
cin.get();
return 0;
}
The test program (console program) currently runs on Windows 10 and is compiled with Visual Studio 2017.
Any help is appreciated.
I want to derive from Gtk::Window and want to create a stand alone window from that object. If the user closes that window, how can I achieve that the destructor of my derived object will be called.
I want to close it in the moment the window is destroyed by user. I tried to do it inside the "on_signal_delete" handler, but that results in segfault.
Currently my code did never call the destructor of the stand alone window!
#include <iostream>
#include <string>
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
protected:
//Child widgets:
Gtk::Box m_VBox;
Gtk::Label m_Label1;
std::string mytext;
public:
ExampleWindow(const std::string& text_):
m_VBox{ Gtk::ORIENTATION_VERTICAL }
,m_Label1{ text_ }
,mytext{ text_ }
{
set_title("Example");
set_border_width(10);
set_default_size(400, 200);
add(m_VBox);
m_VBox.pack_start( m_Label1 );
show_all_children();
}
virtual ~ExampleWindow()
{
// Not called for the stand alone win while closing it. How to achieve that?
std::cout << "Destructor called for " << mytext << std::endl;
}
bool on_delete_event( GdkEventAny* ) override
{
std::cout << "sig on delete called" << mytext << std::endl;
// free( this ); // that results in segfault
return true;
}
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "some.base");
ExampleWindow window{ "First Window" };
// Create the same window as free window ( toplevel )
ExampleWindow* win2 = new ExampleWindow("Stand Alone Win");
win2->show(); // How can I desruct this window, if a user closes it?
//Shows the window and returns when it is closed.
return app->run(window);
}
EDIT: As comming up discussion from comments why it is not possible to not use new I provide this more complicated example to show that my real world application has to create the new windows from a signal handler inside gtk. So there is a need to create the objects on demand.
Full example which can create new windows on demand:
#include <iostream>
#include <string>
#include <gtkmm.h>
class ExampleWindow : public Gtk::Window
{
protected:
//Child widgets:
Gtk::Box m_VBox;
Gtk::Button m_button;
std::string mytext;
public:
ExampleWindow(const std::string& text_):
m_VBox{ Gtk::ORIENTATION_VERTICAL }
,m_button{ text_ }
,mytext{ text_ }
{
set_title("Example");
set_border_width(10);
set_default_size(400, 200);
add(m_VBox);
m_VBox.pack_start( m_button );
m_button.signal_clicked().connect(sigc::mem_fun(this,&ExampleWindow::on_clicked));
show_all_children();
}
void on_clicked()
{
ExampleWindow* win2 = new ExampleWindow("Stand Alone Win");
win2->show(); // How can I desruct this window, if a user closes it?
}
virtual ~ExampleWindow()
{
// Not called for the stand alone win while closing it. How to achieve that?
std::cout << "Destructor called for " << mytext << std::endl;
}
bool on_delete_event( GdkEventAny* ) override
{
std::cout << "sighandler on_delete called" << mytext << std::endl;
//delete this; // results in segfault
return false;
}
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "some.base");
ExampleWindow window{ "Press to create new win" };
//Shows the window and returns when it is closed.
return app->run(window);
}
The question is still: Where can I hook into the signal handlers to free the dynamically created top level windows.
You dynamically allocate win2 but you never free the memory afterwards.
Call delete on win2 after Gtk::Application::run() returns:
delete win2;
Edit, after a discussion in the comments of this answer
Instead of dynamically allocating your pointer in ExampleWindow::on_clicked(), showing it and then forgetting about it, you should have some sort of a global registry, e.g. an array, of created windows that you can track and destroy when required. Coming up with a design on how to do this is not in scope of the original question so I won't suggest anything more concrete here. You can then even avoid having the dynamic allocation, as it was also suggested below.
i am using the library Gtkmm with c++ but i have a problem to display the value of an entry. This is my code :
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <gtkmm/entry.h>
#include <iostream>
int main(int argc, char* argv[]) {
Gtk::Main app(argc, argv);
Gtk::Window fenetre;
Gtk::VBox *boiteV = Gtk::manage(new Gtk::VBox(false, 10));
Gtk::Entry *param = Gtk::manage(new Gtk::Entry());
boiteV->pack_start(*param);
Gtk::Button *bouton = Gtk::manage(new Gtk::Button("Tester !"));
boiteV->pack_start(*bouton);
fenetre.add(*boiteV);
std::string a = param->get_text();
bouton->signal_clicked().connect([&a]() {std::cout << a << std::endl;});
fenetre.show_all();
Gtk::Main::run(fenetre);
return EXIT_SUCCESS;
}
My problem is when i click on the button i have nothing whereas i wrote a value in the entry. Thank you a lot for your help !
The problem is that you take the string a after creation of the button and capture that string (which is empty) in the lambda function. When you press the button, the text is not queried again, but the value of the string a, which never changed, is printed.
You can instead capture the pointer to the button itself (by value!) and call get_text() every time like this:
bouton->signal_clicked().connect(
[param]() {
std::cout << param->get_text() << std::endl;
}
);
I have a problem where I can't seem to get a output to display in a console when doing it through a function.
It works when doing it through Main(), but just blank when doing it through the function.
Below is some of my code:
#include "ConferencePaper.h"
#include "JournalArticle.h"
#include "Reference.h"
#include <QDebug>
#include <QTextStream>
QTextStream cout(stdout);
int main()
{
//QApplication app(argc, argv);
QStringList list1;
list1 << "This is a test";
Reference a("Marius",list1,1,"c"); //Instance of the Reference class created with parameter values
cout << "Title: " << a.getTitle(); //This works fine
a.toString();
return 0;
}
//Reference Function
#include <QString>
#include <QStringList>
#include <QTextStream>
#include "Reference.h"
Reference::Reference(QString ti, QStringList as, int ye, QString id): title(ti), authors(as), year(ye), refID(id){}
QString Reference::toString()
{
return QString("Title: %1\n") .arg(getTitle()); //Does not display anything
}
In your toString() method:
QString Reference::toString() {
return QString("Title: %1\n") .arg(getTitle()); //Does not display anything
}
there is nothing which could cause to print anything on the console. You are simply returning the string as a result of that method.
To display something, you need to output the string which is returned from the method, e.g. in your main() function like
cout << a.toString().toUtf8().constData();
or
cout << a.toString().toLocal8Bit().constData();
Note that you need to convert your QString to a data type for which a << operator is available for ostream. See also How to convert QString to std::string?
As mentioned above several times, X.toString(); would just return QString to a caller, then depending on what you're trying to achieve you may:
print it to console using cout << ...
print it to Application Output pane in your Qt Creator using qDebug() << ...
(see QDebug Class reference for details, it's pretty common debugging technique)
Can someone help to clear up the confusion of how to update a gui window without user input.
In other words, I would like to be able to output text to either or both the console our the gui window.
At present I can call the gui window (Window with a label for example) and output the initial text. However, the process doesn't return to my c++ code until the window closes. I'm trying to figure out how to (or where to have my code) for updating the gui screen before the gui window exits.
This is an example:
#include <gtkmm.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
Gtk::TextView textview;
Gtk::Label label;
string mylabeltext = "This is the first line of text in my gui window.\n";
window.set_default_size(600, 360);
window.set_title("Gtkmm Programming - C++");
window.set_position(Gtk::WIN_POS_CENTER);
label.show();
window.add(label);
label.set_text(mylabeltext);
mylabeltext += "About to run some routines...\n";
label.set_text(mylabeltext);
cout << "An initial line has been set to the gui window." << endl;
// The Gui Window is displayed
Gtk::Main::run(window);
// Now my main program has performed some functions and wants to update
// the console and the gui window.
cout << "Continuing after various functions and processing..." << endl;
mylabeltext = "Showing the results of the functions and processing.";
label.set_text(mylabeltext);
return 0;
}
The last line of text is never printed to the console until the gui is exited. The last line of the mylabeltext is never printed to the label window.
What I'm trying to describe is how to keep the gtkmm window active while I run other routines in my c++ code and update the output to both the console and the gui window without closing the gui window to continue the c++ routines.
All the examples that I can find uses a button in the code. I have tested and experimented enough that I can update the gui screen after a button is pressed. However, I don't want to have to rely on the user for screen updates. I hope to be able to run disc scans and other functions and periodically update the screen so that the user can see the progress and know that the program is still working and not dead.
Some of the resources that I have studied in my attempts at understanding this include:
https://developer.gnome.org/
https://developer.gnome.org/gtkmm-tutorial/3.2/gtkmm-tutorial.html
http://en.wikipedia.org/wiki/Gtkmm
Like tp1 said in their comment on your question, a timer is going to be the easiest way to do this.
To set a 1.5 second timeout that will call another function, do this (gtkmm 3):
#include <gtkmm.h>
#include <iostream>
using namespace std;
class MyApp : public Gtk::Window{
public:
Gtk::Label label;
bool on_timeout(); //return true to keep the timeout and false to end it
MyApp();
virtual ~MyApp();
};
MyApp::MyApp(){
string mylabeltext = "This is the first line of text in my gui window.\n";
set_default_size(600, 360);
set_title("Gtkmm Programming - C++");
set_position(Gtk::WIN_POS_CENTER);
add(label);
label.set_text(mylabeltext);
mylabeltext += "About to run some routines...\n";
label.set_text(mylabeltext);
cout << "An initial line has been set to the gui window." << endl;
//create slot for timeout signal
int timeout_value = 1500; //in ms (1.5 sec)
sigc::slot<bool>my_slot = sigc::mem_fun(*this, &MyApp::on_timeout);
//connect slot to signal
Glib::signal_timeout().connect(my_slot, timeout_value);
show_all_children();
}
MyApp::~MyApp(){
}
bool MyApp::on_timeout(){
cout << "Continuing after various functions and processing..." << endl;
string temp = label.get_text();
temp += "Showing the results of the functions and processing.\n";
label.set_text(temp);
return true;
}
int main(int argc, char* argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "com.kaze.test");
MyApp myapp;
// The Gui Window is displayed
return app->run(myapp);
}
More info here: https://developer.gnome.org/gtkmm-tutorial/3.3/sec-timeouts.html.en
This is crude, but this is functional for what I was trying to do:
#include <gtkmm.h>
#include <iostream>
using namespace std;
class myLabel: public Gtk::Window
{
public:
myLabel();
virtual ~myLabel();
protected:
Gtk::Label m_label;
string labeltext;
string newtext;
void myprocess1();
};
myLabel::myLabel() :
m_label()
{
void myprocess1();
set_title("Gtkmm Programming - C++");
add(m_label);
m_label.show();
Glib::Thread::create(sigc::mem_fun(*this, &myLabel::myprocess1), true);
}
myLabel::~myLabel()
{
}
void myLabel::myprocess1()
{
labeltext = "About to preform a number of processes.\n";
labeltext += "Each process may take up to three hours.\n";
labeltext += "Please carry your daily chores and wait.\n";
cout << labeltext;
cout.flush();
m_label.set_text(labeltext);
sleep(10); // Back from a three hour function
newtext = "Back from a three hour function\n";
labeltext += newtext;
m_label.set_text(labeltext);
cout << newtext;
cout.flush();
sleep(10); // Back from a three hour function
newtext = "Back from another three hour function\n";
labeltext += newtext;
m_label.set_text(labeltext);
cout << newtext;
cout.flush();
newtext = "Exiting in 1 minute...\n";
labeltext += newtext;
m_label.set_text(labeltext);
cout << newtext;
cout.flush();
sleep(60);
exit(0);
}
int main(int argc, char* argv[])
{
if (Glib::thread_supported())
Glib::thread_init();
else
{
cerr << "Threads aren't supported!" << endl;
exit(1);
}
Gtk::Main kit(argc, argv);
myLabel mylabel;
Gtk::Main::run(mylabel);
return 0;
}
Hope the example can help anyone else that wants to output to the gtkmm gui with updates, similar to updating info to the console.