How to get 2 textentry in gtk3 - c

I'v been seaching google for 2 weeks now.
2 textentry in a gride.
(ex: userid, password)
Glade let me design that no problem...
For one textentry widget, it working.
I'm compiling/linking with mysql
so I would like to call functions, stored procedures
with entry1 and entry2.
Please help
thanks
:EDIT:
15:18 4 may 2019
I found a conclusive solution.
(But it's throwing seg fault)
bit of code following :
this is some kind of a transcription of the video into text (C code).
https://www.youtube.com/watch?v=_yTmW1QG3uk
obviously according to my goal really...
it's kind of working but let say you want to use the same
instance a second time, "seg fault"
I'm sure I will find the problem (gtk_main_quit) or something,
but the textentry multiples lines is solved :P
here's the code :
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <mysql/mysql.h>
GtkEntry *userid, *password;
static void Button_Pressed(GtkWidget *w, gpointer *data){
/* char *userid, *password;*/ //seg fault
/* userid[0]='\0';
password[0]='\0';*/
userid=gtk_entry_get_text(userid);
password=gtk_entry_get_text(password);
g_print("%s\n\r%s\n\r",userid, password);
}
static void CreateWindow(GtkApplication *myapp, gpointer *user_data){
GtkWidget *window;
window=gtk_application_window_new(myapp);
gtk_window_set_title(GTK_WIDGET(window), "Double Entry Solution");
gtk_window_set_default_size(GTK_WINDOW(window),400,400);
GtkWidget *vbox=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
// userid pack
userid=gtk_entry_new();
gtk_box_pack_start(GTK_CONTAINER(vbox), userid, TRUE, TRUE,0);
gtk_widget_show(userid);
GtkWidget *hbox=gtk_hbox_new(TRUE,0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
// password pack
password=gtk_entry_new();
gtk_box_pack_start(GTK_BOX(hbox), password, TRUE, TRUE,0);
gtk_widget_show(password);
GtkWidget *submit=gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
gtk_box_pack_start(GTK_BOX(vbox), submit, TRUE, TRUE,0);
GtkWidget *button=gtk_button_new_with_label("Login");
g_signal_connect(button, "clicked", G_CALLBACK(Button_Pressed), NULL);
gtk_container_add(GTK_CONTAINER(submit), button);
gtk_widget_show(button);
gtk_widget_show_all(window);
}
int main(int argc, char** argv){
GtkApplication *doubleentry;
doubleentry=gtk_application_new("smdelectro.business.site.doubleentry", G_APPLICATION_FLAGS_NONE);
g_signal_connect(doubleentry, "activate", G_CALLBACK(CreateWindow), NULL);
g_application_run(G_APPLICATION(doubleentry), argc, argv);
g_object_unref(doubleentry);
return (EXIT_SUCCESS);
}

The code below work :
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
// Init
gtk_init(&argc,&argv);
// Create widgets
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkGrid *grid = GTK_GRID(gtk_grid_new());
// Attach entries
gtk_grid_attach(grid,gtk_entry_new(),0,0,1,1);
gtk_grid_attach(grid,gtk_entry_new(),0,1,1,1);
// Add the grid in the window
gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(grid));
// Dirty way to force clean termination when window is closed
g_signal_connect(window,"delete-event",G_CALLBACK(gtk_main_quit),NULL);
// Show **everythings** (not only the window)
gtk_widget_show_all(window);
// Main loop
gtk_main();
return 0;
}
Without any source code I can't provide more help, could you post it please.
A common trap in GTK+3 is creating widget without showing them. If you replace gtk_widget_show_all with gtk_widget_show you will see a window without widgets, they are here but not displayed, because by default the visible property is set to FALSE.

finally,
creating c file with reference to xml is ONE way, it's cool, thanks Glade.
Creating pure C Gtk3 is pain... omg
xml parser to generate c code...
aw..
BRB

Related

C, gtk: ‘window’ undeclared (first use in this function)

I'm very new in C, i've started learning this language about 1 week ago, coming from Python. So,I have difficult understanding the C syntax, and the solution online. I'm trying building a simple graphic interface. In this example project created for this post, if the user types "create_window", the program creates a window, and if after it the user types "create_button" the program should create a button.. but it doesn't work. Below there is the error, but first the code:
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
void main(int argc, char* argv[]){
char row[50];
for(int i=0;i<=1;i++){
scanf("%s",row);
if(strstr(row,"create_window")!=NULL){
GtkWidget* window;
GtkWidget* button;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "New window");
g_signal_connect(window,"destroy",G_CALLBACK(gtk_main_quit),NULL);
gtk_window_set_default_size(GTK_WINDOW(window),200,200);
gtk_widget_show_all(window);
gtk_main();
}
if(strstr(row,"create_button")!=NULL){
button = gtk_button_new_with_label("Button text");
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show_all(window);
gtk_main();
}
}
}
this code create successfully the window, but not the button. After creating the window, i type "create_button" and i receive this error:
error: ‘window’ undeclared (first use in this function)
80 | gtk_container_add(GTK_CONTAINER(window), button);
the complete error refers to my """complete""" project, if you need it write in a comment.
Your window variable is scoped exclusively to that first if.
Variables only exist within the scope in which they've been declared.
#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
void main(int argc, char* argv[]) {
char row[50];
for(int i = 0; i <= 1; i++) {
scanf("%s", row);
GtkWidget* window;
GtkWidget* button;
if (strstr(row, "create_window") != NULL) {
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "New window");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
gtk_widget_show_all(window);
gtk_main();
}
if (strstr(row, "create_button") != NULL) {
button = gtk_button_new_with_label("Button text");
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show_all(window);
gtk_main();
}
}
}
Also, I suggest using a width specifier with scanf to avoid overflows.
scanf("%49s", row);
Your program doesn't make sense. You cannot create a button till you have a window to place it on (even if you fix the syntax error of making the variable available in the 2nd if statement). Also, gtk_main() runs an event loop and doesn't return. Perhaps you want to optionally create a button?
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
void main(int argc, char* argv[]){
gtk_init(&argc, &argv);
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "New window");
g_signal_connect(window,"destroy", G_CALLBACK(gtk_main_quit),NULL);
gtk_window_set_default_size(GTK_WINDOW(window),200,200);
char row[50];
fgets(row, 50, stdin);
if(!strcmp(row, "create_button\n")) {
GtkWidget *button = gtk_button_new_with_label("Button text");
gtk_container_add(GTK_CONTAINER(window), button);
}
gtk_widget_show_all(window);
gtk_main();
}
I build the program and executed it like this:
gcc 1.c $(pkg-config --cflags atk) $(pkg-config --cflags gdk-3.0) $(pkg-config gtk-3.0) $(pkg-config --libs gtk+-3.0) $(pkg-config --libs gdk-3.0) && ./a.out
If you enter create_button\n it will create a window with a button, and if you enter any other line it will just create the window.
Otherwise, you need to tell us what should happen for "create_button"? Do we automatically create a window and then the button? Do we just remember that we need to create the button when user asks to "create_window"? If you want to show the window, then regain control, you need to use gtk_main_iteration_do(FALSE) instead of gtk_main(), and then you can add the button.

gtk3 on macos: window does not restore from the dock

Using GTK3 on MacOS, after minimizing the window, the dock icon does not restore the window. I have to use the "Show All Windows" selection from the dock icon menu.
Does anyone have a work-around or know something to make the dock icons work?
I would be happy with some simple objective-c code that would make the dock icons work.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <getopt.h>
#include <unistd.h>
#include <gtk/gtk.h>
static void testBuildUI (void);
gboolean testMainLoop (void);
int
main (int argc, char *argv[])
{
gtk_init (&argc, NULL);
testBuildUI ();
testMainLoop ();
return 0;
}
static void
testBuildUI (void)
{
GtkWidget *window;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
assert (window != NULL);
gtk_widget_show_all (window);
}
int
testMainLoop (void)
{
while (1) {
gtk_main_iteration_do (FALSE);
while (gtk_events_pending ()) {
gtk_main_iteration_do (FALSE);
}
sleep (1);
}
return 0;
}
There is no special code or Objective-C needed if you use gtk_application_new instead of gtk_init and start your main loop with g_application_run.
The documentation states the following:
Currently, GtkApplication handles GTK+ initialization, application uniqueness, session management, provides some basic scriptability and desktop shell integration by exporting actions and menus and manages a list of toplevel windows whose life-cycle is automatically tied to the life-cycle of your application.
see https://docs.gtk.org/gtk3/class.Application.html
Self contained test program
Your code slightly adapted to the above points might look like the following:
#include <gtk/gtk.h>
#include <assert.h>
static void testBuildUI(GApplication *app, gpointer data);
int main(int argc, char *argv[]) {
printf("gtk version: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
GtkApplication *app = gtk_application_new("com.example.MyApp",G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(testBuildUI), NULL);
g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return 0;
}
static void testBuildUI(GApplication *app, gpointer data) {
GtkWidget *window;
window = gtk_application_window_new(GTK_APPLICATION(app));
assert (window != NULL);
gtk_widget_show_all(GTK_WIDGET(window));
}
If you click on the dock icon of this test program, the window will restore as expected.
Alternative solution
If you want to avoid GApplication/GtkApplication, you could also use the gtk-mac-integration library instead, see https://github.com/jralls/gtk-mac-integration.
The library is rather small, only a few thousand lines of C code, so you can also easily take a look at how it works internally.
There is an important hint:
Older Gtk applications that aren't based around GApplication can be adapted to use the macOS menu bar and to integrate with the Dock using GtkOSXApplication. The Gtk API that GtkOSXApplication uses is deprecated in Gtk3 and has been removed from Gtk4. Since macOS integration is available directly in Gtk using GApplication GtkOSXIntegration will not be updated for the new menu API and is deprecated. Application maintainers are strongly encouraged to redesign their programs around GApplication, particularly before migrating to Gtk4.
see https://wiki.gnome.org/Projects/GTK/OSX/Integration
The integration is easy: after gtk_init create an application object. After setting up the window call gtkosx_application_ready with the application object.
As a side note, there is also a slightly more complex example in the src folder called test-integration.c under the Github link mentioned above that shows a more advanced menu and dock integration.
Finally, your program only minimally changed to work with the gtk-mac-integration lib:
#include <gtk/gtk.h>
#include <gtkosxapplication.h>
#include <assert.h>
static void testBuildUI(void);
static void testMainLoop(void);
static void
testBuildUI(void) {
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
assert (window != NULL);
gtk_widget_show_all(window);
}
void
testMainLoop(void) {
while (1) {
gtk_main_iteration_do(FALSE);
while (gtk_events_pending()) {
gtk_main_iteration_do(FALSE);
}
sleep(1);
}
}
int
main(int argc, char *argv[]) {
printf("gtk version: %d.%d.%d\n", gtk_major_version, gtk_minor_version, gtk_micro_version);
gtk_init(&argc, &argv);
GtkosxApplication *theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
testBuildUI();
gtkosx_application_ready(theApp);
testMainLoop();
g_object_unref(theApp);
return 0;
}
I installed the library using brew install gtk-mac-integration and linked the C program with libgtkmacintegration-gtk3.dylib. Also in this variant, the window is restored as expected. when you click on the dock icon of the program.

How to refresh a GTK image?

Hi people from Stackoverflow, I have some knowledge of programming, but not very much. My idea is to program something like a video-game or visualizer in c, to do so I make and process somehow an array that represents an image and it has to be visualized and always being refreshed, like a video-game. I have the algorithm already done, I need to optimize it, I mean I know how to create the array representing an image at anytime, what I need now is to visualize it like an animation and later optimize with opencl.
The program that I want to make has to do something like this:
"create the image"
"render it",
"create the image"
"render it",
...
For that reason I know that I could start easily from a very simple example and I don't have to learn everything of GTK. I have been intensively searching for simple examples and trying to understand how it works but it didn't help, I need just to do that simple action, refresh it. A command somewhere should be enough.
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <glib.h>
const int Width = 1200, Height = 800;
char *buffer;
int i = 0;
GdkPixbuf *pixbuf;
GtkWidget *window;
GtkWidget* image;
void delay(int number_of_seconds){
int milli_seconds = 1000 * number_of_seconds;
clock_t start_time = clock();
while (clock() < start_time + milli_seconds);
}
int main (int argc, char *argv[]){
buffer = (char*)malloc(3 * Width * Height);
// CREATE AN IMAGE IN BUFFER SOMEHOW
// buffer = something;
//
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, FALSE, 8, Width, Height, (Width)*3, NULL, NULL);
image = gtk_image_new_from_pixbuf (pixbuf);
gtk_container_add(GTK_CONTAINER (window), image);
gtk_window_set_title (GTK_WINDOW (window), "Visualizador");
gtk_widget_show_all (window);
delay(0.04);
gtk_main ();
free (buffer);
return 0;
}
The program is really simple, when I create/load the image there it shows a picture, but I would like to put the function already programmed there, to return a "buffer" and then refresh the displayed image.
I read that gtk_widget_queue_draw has something to do, or gdk_pixbuf_simple_anim_add_frame or g_timeout_add but I have no idea how they work and what to put in this program.
Thank you in advance!
If you want a moving image or something that needs to get refreshed a lot then I would suggest using a GtkDrawingArea and implement it's draw signal, for that you'll need to use cairo. It should look something like this:
static gboolean
your_draw_cb(GtkWidget *widget, cairo_t *context, gpointer data)
{
// Do your drawing
return FALSE;
}
int main()
{
// Some code before ...
GtkWidget *area = gtk_drawing_area_new();
g_signal_connect(G_OBJECT(area), "draw", G_CALLBACK(your_draw_cb), your_data);
gtk_container_add(GTK_CONTAINER(your_container), area);
// More code ...
}
Each time you want to refresh it you should call
gtk_widget_queue_draw(area);
to get the draw signal called.
You won't need to store a buffer as that comes inside the cairo context.
But you may want to use other libraries for this purpose, like SDL2 or OpenGL as they are designed for videogames.
I hope this helps.

compiling a simple gtk program with glade

i hav downloaded glade3 and i cant find any glade.h in it when i extract it so when i compile the following program
#include <stdio.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
GladeXML *xml;
GtkWidget *widget;
GtkWidget *display;
G_MODULE_EXPORT void on_displayButton_clicked(GtkButton *button,gpointer *data)
{
/* Find the Glade XML tree containing widget. */
xml = glade_get_widget_tree(GTK_WIDGET( widget ));
/* Pull the widgets out of the tree */
display= glade_xml_get_widget(xml, "displayLabel");
gtk_label_set_text(GTK_LABEL(display),"Hello World!\n gihansblog.com");
}
G_MODULE_EXPORT void on_exitButton_clicked(GtkButton *button,gpointer *data)
{
gtk_main_quit();
}
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
/*import glade file*/
xml = glade_xml_new("hello.glade", NULL, NULL);
/* get a widget (useful if you want to change something) */
widget = glade_xml_get_widget(xml, "mainWindow");
/* connect signal handlers */
glade_xml_signal_autoconnect(xml);
/*show widget*/
gtk_widget_show (widget);
gtk_main();
return 0;
}
i get an error saying glade.h not found,i have been working on it from past 5 hours but cant find a solution.
Have you tried by giving the full directory to your
"hello.glade" file.
Where it is in your system???
Otherwise you may have to convert your .glade file to .xml
Anyway in which Gtk version aru you in?

How to draw / render to a widget using the widgets Xid in GTK/Cairo in 'C'

I have a need to write a GTK application in C that does some animation using Cairo that will render into a GTK widget that exists in another running application. The idea is to do the very same thing you can do with VLC and Mplayer. For example Mplayer has the -wid option:
-wid (also see -guiwid) (X11, OpenGL and DirectX only)
This tells MPlayer to attach to an existing window. Useful to embed MPlayer in a browser (e.g. the plugger extension). This option
fills the given window completely, thus aspect scaling, panscan, etc
are no longer handled by MPlayer but must be managed by the
application that created the window.
With this Mplayer option you can create a GTK application with a GTKImage widget, get it's Xid and then play a movie in the GTK application using Mplayer with the Xid specified.
I'm trying to do the same thing except render/draw into the external window using Cairo. Anybody have suggestions or better yet a small code sample?
Take a look to the GtkSocket and GtkPlug classes.
The main program will create a GtkSocket and the XID you can pass to the other program will be returned by the function gtk_socket_get_id(). Then the other program will use it as argument to the gtk_plug_new() function. All the render will be done in children of this new GtkPlug object.
UPDATE: Well, if you want... here it is a minimal example of GtkSocket/GtkPlug. You don't say if you are using GTK+2 or GTK+3, so I'm assuming version 2.
server.c:
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
GtkWidget *wnd = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *sck = gtk_socket_new();
gtk_container_add(GTK_CONTAINER(wnd), sck);
gtk_window_set_default_size(GTK_WINDOW(wnd), 400, 300);
gtk_widget_show_all(wnd);
GdkNativeWindow nwnd = gtk_socket_get_id(GTK_SOCKET(sck));
g_print("%lu\n", nwnd);
gtk_main();
return 0;
}
client.c:
#include <stdlib.h>
#include <gtk/gtk.h>
#include <cairo/cairo.h>
#include <math.h>
gboolean OnDraw(GtkWidget *w, GdkEvent *ev, gpointer data)
{
GtkAllocation size;
gtk_widget_get_allocation(w, &size);
cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(w));
cairo_set_source_rgb(cr, 1, 0, 0);
cairo_arc(cr, size.width/2, size.height/2, size.height/2, 0, 2*M_PI);
cairo_fill(cr);
cairo_destroy(cr);
return TRUE;
}
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
GdkNativeWindow nwnd = strtoul(argv[1], NULL, 10);
GtkWidget *plug = gtk_plug_new(nwnd);
GtkWidget *canvas = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(plug), canvas);
g_signal_connect(canvas, "expose-event", (GCallback)OnDraw, NULL);
gtk_widget_show_all(plug);
gtk_main();
return 0;
}
The XID to be used is printed by the server and has to be copied/pasted as argument to the client:
$ ./server
60817441
^Z
[1]+ Stopped ./server
$ bg
$ ./client 60817441

Resources