i was doing a small project where i had a a fullscreen GUI (Glade, GTK and C) and needed to give the user a way to close the screen (obviously the window manager was not available due to the window being fullscreen).
problem rices when i attempt to compile this piece of code
//close sidebar1
void on_window_sidebar1_back_clicked()
{
gtk_window_close (GtkWindow *window);
}
i receive the following error
/usr/bin/arm-linux-gnueabihf-gcc -c -g -O0 -Wall -pthread -pipe src/main.c `pkg-config --cflags --libs gtk+-3.0` -o main.o
src/main.c: In function 'on_window_sidebar1_back_clicked':
src/main.c:61:2: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'gtk_window_close'
gtk_window_close (GtkWindow *window);
^
src/main.c:61:20: error: expected expression before 'GtkWindow'
gtk_window_close (GtkWindow *window);
^
makefile:30: recipe for target 'main.o' failed
make: *** [main.o] Error 1
I tried to follow the documentation here, but seem to have failed badly
Does anyone have any ideas?
PS.
here is the full main.c if someone is intrested. Its my first attempt at C with gtk, so dont be too harsh, Thank you (=
#include <gtk/gtk.h>
GtkWidget *g_lbl_test;
GtkWidget *g_lbl_count;
int main(int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "glade/window_main.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));
gtk_builder_connect_signals(builder, NULL);
//pointers for the labels (...used in button press)
g_lbl_test = GTK_WIDGET(gtk_builder_get_object(builder, "lbl_test"));
g_lbl_count = GTK_WIDGET(gtk_builder_get_object(builder, "lbl_count"));
g_object_unref(builder);
gtk_widget_show(window);
//gtk_window_fullscreen (GtkWindow *window); //dont know how to use this, same with gtk_window_close
gtk_main();
return 0;
}
//button press (just a test to make sure the window didnt freeze)
void on_btn_count_clicked()
{
static unsigned int count= 0;
char str_count[30] = {0};
gtk_label_set_text(GTK_LABEL(g_lbl_test), "Test success!");
count++;
sprintf(str_count, "%d", count);
gtk_label_set_text(GTK_LABEL(g_lbl_count), str_count);
}
//sidebar1
void on_sidebar_1_clicked()
{
GtkBuilder *builder;
GtkWidget *window;
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "glade/window_main.glade", NULL);
window = GTK_WIDGET(gtk_builder_get_object(builder, "window_sidebar1"));
gtk_widget_show(window);
}
//close sidebar1
void on_window_sidebar1_back_clicked()
{
gtk_window_close (GtkWindow *window);
}
// called on closing window
void on_window_main_destroy()
{
gtk_main_quit();
}
You probably should call
gtk_close_window(window);
But that window should come from somewhere.
(you may use a Gtk closure with a connection, or a callback with a client data, etc. or store somehow that window in a global variable, etc...)
Read more about C programming, then read a bit about callbacks and closures, then read more about GTK, and the signal mechanism of Gobject.
(your code shows a lot of confusion; I suggest to read the Getting started with GTK chapter after having read a good C programming book; BTW, I suggest to first write something which is not fullscreen, and only later improve it)
Don't forget to enable all warnings and debug info when compiling, that is compile with gcc -Wall -Wextra -g (and other arguments, perhaps using $(pkg-config --cflags gtk+-3.0) and also $(pkg-config --libs gtk+-3.0) for linking).
Attention! This does not follow any industrial standards and there are multiple flaws in this. I don't make any money or fame out of this so my only requirement is that it works. Take this into consideration when reading this!
I made edits to my code with what I learned and this seems to work:
void on_sidebar_1_clicked(int argc, char *argv[])
{
GtkBuilder *builder;
gtk_init(&argc, &argv);
builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "glade/window_sidebar1.glade", NULL); //a whole own file for the second window
secondWindow = GTK_WIDGET(gtk_builder_get_object(builder, "window_sidebar1")); //secondWindow is defined at the start of main.c like this: "GtkWidget *secondWindow = NULL;" so that both callbacks can use it.
gtk_builder_connect_signals(builder, NULL);
gtk_widget_show(secondWindow);
gtk_main();
}
void on_sidebar1_back_clicked()
{
gtk_widget_destroy(GTK_WIDGET(secondWindow)); //here we call the widget to be closed instead of the window. Seems to work a lot better than the gtk_window_close, dunno why.
}
This code was written fast (and furious) so it's a little crude. I made some changes to my glade files as well, if someone needs a reference to those, please ask. As far as I care, this was the answer for my question. Also, I would recommend learning C and GTK (like Basile Starynkevitch said) before you start doing this kind of stuff, I didn't have the time nor motivation to do so.
Related
I made a small sample code in gtk4 + vte to run a fake terminal with a button in the bottom to run a simple command when the button is clicked.
main.c
#include <gtk/gtk.h>
#include <vte/vte.h>
#define WINDOW_HEIGHT 400
#define WINDOW_WIDTH 600
GtkApplication *app;
GtkWidget *window, *terminal, *grid, *scrollview1,*button;
int status;
void run_button(void){
char **argv_test[2] = {
"echo\0",
"Hello!!\0"
};
// can't run this command in fake terminal!
vte_terminal_spawn_async(VTE_TERMINAL(terminal),VTE_PTY_NO_HELPER,NULL,argv_test,NULL,G_SPAWN_SEARCH_PATH,NULL,NULL,NULL,2000,NULL,NULL,NULL);
}
void window_renderer(GtkApplication *app, gpointer user_data) {
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window),"My terminal");
gtk_window_set_default_size (GTK_WINDOW(window), WINDOW_WIDTH, WINDOW_HEIGHT);
grid = gtk_grid_new();
gtk_window_set_child(GTK_WINDOW(window), grid);
gtk_widget_set_vexpand(grid,TRUE);
gtk_widget_set_hexpand(grid,TRUE);
scrollview1 = gtk_scrolled_window_new();
gtk_grid_attach(GTK_GRID(grid), scrollview1, 0, 0, 1, 1);
gtk_widget_set_size_request(GTK_WIDGET(scrollview1),WINDOW_WIDTH,WINDOW_HEIGHT);
button = gtk_button_new_with_label("Run!");
gtk_grid_attach(GTK_GRID(grid), button, 0, 1, 1, 1);
g_signal_connect(button,"clicked", G_CALLBACK(run_button), NULL);
terminal = vte_terminal_new();
gtk_window_set_child(GTK_WINDOW(scrollview1), terminal);
gtk_widget_show(window);
}
int main(int argc, char **argv)
{
app = gtk_application_new(NULL, G_APPLICATION_FLAGS_NONE);
g_signal_connect(app,"activate", G_CALLBACK(window_renderer), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
Makefile
CFLAGS += -Wall
CFLAGS += `pkg-config --cflags gtk4 vte-2.91-gtk4`
LIBS += `pkg-config --libs gtk4 vte-2.91-gtk4`
.PHONY: all clean
all: main
main:main.c
gcc $(CFLAGS) main.c -o main $(LIBS)
clean:
rm main
I have compiled VTE (for gtk4) and gtk4 developer package, building a gtk4 app is not an issue!
When running the built binary, the program crashes when I click the button with a segmentation fault, probably because of a pointer not properly initialized (according to tutorials point).
Can someone help me to find out what I have missed?
I tested out your code and I believe I found the main issue with your terminal command along with some warnings that were displayed when I tested. First off, from reviewing other sample code using the "vte_terminal_spawn_async" function, the character string set included an ending array element of "NULL". So instead of the following code snippet.
char **argv_test[2] = {
"echo\0",
"Hello!!\0"
};
You would need to add in a third array element as in the following revised code snippet.
char *argv_test[3] = {
"echo\0", "Hello!!\0", NULL
};
If you notice one other minor revision to the above code snippet, I revised the definition of the character array from "char ** argv_test[3]" to "char *argv_test[3]". The compiler was listing a warning about incompatible pointer references. Also, when I was testing out this code I was receiving a warning and not able to view the terminal when the "Run" button was clicked.
Gtk-CRITICAL **: 14:49:46.383: gtk_window_set_child: assertion 'GTK_IS_WINDOW (window)' failed
From some previous troubleshooting with another user, we had determined that the child setup for the scrolled window needed to utilize the scrolled window child reference function along with the scrolled window macro. So I revised the scrolled window child assignment to be as follows.
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scrollview1), terminal);
Making those small revisions resulted in displaying the terminal with your "echo Hello" command (I clicked the button twice in my testing).
I believe that if you try out those minor revisions to your code, you will be able to view your terminal and progress with your coding.
Regards.
Hey guys I've recently started dabbling in Glade with C. I have been able to compile a few GTK+ applications in C but I keep getting compilation errors when compiling the following C file with a glade file (taken from Micah Carrick's tutorial)
main.c
#include <gtk/gtk.h>
void
on_window_destroy (GtkObject *object, gpointer user_data)
{
gtk_main_quit ();
}
int
main (int argc, char *argv[])
{
GtkBuilder *builder;
GtkWidget *window;
gtk_init (&argc, &argv);
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "tutorial.glade", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_builder_connect_signals (builder, NULL);
g_object_unref (G_OBJECT (builder));
gtk_widget_show (window);
gtk_main ();
return (0);
}
tutorial.glade
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.0 on Tue Nov 20 14:05:37 2007 -->
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<placeholder/>
</child>
</widget>
</glade-interface>
and compiling in MSYS with:
gcc -Wall -g -mwindows -O2 main.c -o program.exe `pkg-config --cflags --libs gtk+-3.0`
I get the following error:
main.c:4:20: error: unknown type name 'GtkObject'
on_window_destroy (GtkObject *object, gpointer user_data)
^
I've tried using changing tutorial.glade to an XML file but didn't change anything. Maybe I have to rename GtkObject to something different, or I missed a compilation flag? Sorry if it's a noob question, still learning :S
Change GtkObject to GtkWidget. It looks like your tutorial uses the old GTK 2.0 API, while you are compiling using the current 3.0 API.
I suggest emailing whoever is hosting the tutorial to update it, or at least put a warning banner above it saying that it uses an out of date API.
My O.S. is Ubuntu 12.04 (64 bit).
I am having an error when I compiled my gtk+ program on command line terminal:
second.cpp:8:43: error: too few arguments to function ‘GtkWidget* gtk_widget_new(GType, const gchar*, ...)’
/usr/include/gtk-2.0/gtk/gtkwidget.h:834:12: note: declared here
#include <gtk/gtk.h>
int main(int argc, char* argv[])
{
gtk_init(&argc, &argv);
GtkWidget *window, *label;
window=gtk_widget_new(GTK_WINDOW_TOPLEVEL);
label=gtk_label_new("LabelName");
g_signal_connect(window, "delete-event",G_CALLBACK(gtk_main_quit), NULL);
gtk_container_add(GTK_CONTAINER(window), label);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Please help me to rectify the error, this program is executing good when I write the program without the label Widget.
It is window = gtk_window_new(GTK_WINDOW_TOPLEVEL), not window = gtk_widget_new(GTK_WINDOW_TOPLEVEL).
Hello guys I'm using C and GTK+ 2 I want to make a simple paint program like MS program but by these two tools only okay I just started and I want your hands to reach the end :)
look to my code here
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *drawingArea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window), "delete_event",
G_CALLBACK(gtk_main_quit), G_OBJECT(window));
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit),
G_OBJECT(window));
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
drawingArea = gtk_drawing_area_new();
/*The problem is in the next line */
gtk_drawing_area_size(G_OBJECT(drawingArea), 200, 200);
gtk_container_add(GTK_CONTAINER(window), drawingArea);
gtk_widget_show(drawingArea);
gtk_widget_show(window);
gtk_main();
return 0;
}
my problem is in the commented line
gtk_drawing_area_size(G_OBJECT(drawingArea),200,200);
the error when compiling
ibrahim#ibrahim-PC:~/Desktop$ gcc main.cpp -o base `pkg-config --cflags --libs gtk+-2.0`
main.cpp: In function ‘int main(int, char**)’:
main.cpp:14:52: error: cannot convert ‘GObject* {aka _GObject*}’ to ‘GtkDrawingArea* {aka _GtkDrawingArea*}’ for argument ‘1’ to ‘void gtk_drawing_area_size(GtkDrawingArea*, gint, gint)’
So Please help me
That's a common gotcha in GTK+. You have to cast the widget to the type that exposes the method (i.e. the implementing type). You should write:
gtk_drawing_area_size(GTK_DRAWING_AREA(drawingArea), 200, 200);
Instead of:
gtk_drawing_area_size(G_OBJECT(drawingArea), 200, 200);
Because the GObject type does not support the gtk_drawing_area_size() method, but the GtkDrawingArea type does.
(Actually, it's more like gtk_drawing_area_size() does not support taking a GObject instance, since GTK+'s object oriented nature is abstracted that way in C.)
I am trying to make an example of a simple GTK+ viewer using poppler and cairo which I found at gtkforums.com work. However I am getting a segmentation fault (I use anjuta).
When I use the debugger I get this:
ID:1
File: /usr/lib/i386-linux-gnu/libgdk-x11-2.0.so.0
Line: 0
Function: ??
Address: 0x1d3f16 (dont think that matters anyway)
terminal message while debugging:
Debug Terminal for the process:
------------------------------- &"warning: GDB: Failed to set controlling terminal: Operation not permitted\n"
GLib-GObject-WARNING **: cannot register existing type `GdkWindow'
GLib-GObject-CRITICAL **: g_object_new: assertion `G_TYPE_IS_OBJECT
(object_type)' failed
Here is my code:
#include <config.h>
#include <glib/gi18n.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo.h>
#include <poppler.h>
/* gcc `pkg-config --cflags --libs gtk+-2.0 poppler-glib` -o pdfviewer pdfviewer.c */
static PopplerDocument* doc;
static PopplerPage* page;
static void
on_destroy(GtkWidget* w, gpointer data) {
gtk_main_quit();
}
static gboolean
on_expose(GtkWidget* w, GdkEventExpose* e, gpointer data) {
cairo_t* cr;
cr = gdk_cairo_create(w->window);
poppler_page_render(page, cr);
cairo_destroy(cr);
return FALSE;
}
int main(int argc, char* argv[]) {
GtkWidget* win;
GError* err = NULL;
gtk_init(&argc, &argv);
doc = poppler_document_new_from_file("file:///home/user/test.pdf", NULL, &err);
if (!doc) {
printf("%s\n", err->message);
g_object_unref(err);
return 2;
}
page = poppler_document_get_page(doc, 0);
if(!page) {
printf("Could not open first page of document\n");
g_object_unref(doc);
return 3;
}
int pages = poppler_document_get_n_pages(doc);
printf("There are %d pages in this pdf.\n", pages);
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL);
g_signal_connect(G_OBJECT(win), "expose-event", G_CALLBACK(on_expose), NULL);
gtk_widget_set_app_paintable(win, TRUE);
gtk_widget_show_all(win);
gtk_main();
g_object_unref(page);
g_object_unref(doc);
return 0;
}
Based upon your comment it ("Cannot access memory at address 0x0") appears that the program has a function that fails, but you didn't check the function's return value to ensure it is not NULL before using it.
Based purely on the code example above the first case of that would be if gtk_window_new failed; then the g_signal_connect and other functions cannot use the win value sensibly.
When I compiled the snippet, it compiled fine without warnings, and executed correctly. There was a poppler error message about the PDF document, but it wasn't relevant to your problems.
So your problem is likely either elsewhere (not within the included example) or a trivial mistake.
One way to get more information is to set a breakpoint on g_log in the debugger and get a backtrace of the warning / critical. With the backtrace you'll be able to see where exactly your code is calling the gtk+ function that is failing.