Dr_Lion Posted February 28, 2012 Report Share Posted February 28, 2012 Consegui um código mais perto do que estava á procura utilizando um timer, para de segundo a segundo desenhar numa janela em gtk uma figura geométrica, e até aqui tudo bem. A figura é uma circunferência de radio "radius", este valor é suposto ser enviado numa mensagem, e para isso uso sockets. Até aqui tudo bem, no entanto, não sei onde colocar o socket a ler e tratar essa informação. Pensei colocar o código para tratar a informação na funcão main, mas o programa fica pendurado na janela e apenas quando fechasse a janela é que executa o restante código. E eu precisava que este estivesse constantemente a ler o socket e de x em x tempo, ou cada vez que chegue um valor novo, também é uma opção, ser desenhada a figura na janela. Já sei que no main estou a colocar mal o código, alguma ideia onde devo colocar? Porque parece-me que entre cada segundo em que é feito o desenho o programa fica pendurado no timer. Ou também me surgiu outra ideia que seria criar duas threads, e numa punha o socket a receber dados, e no outro, a janela do gtk a desenhar. #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <cairo.h> #include <gtk/gtk.h> #include <time.h> #define M_PI 3.1415 #define MYPORT "4950" // the port users will be connecting to #define MAX_EST 70 #define MAXBUFLEN 100 double radius1 = 100.0; static char buffer[256]; static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { double xc1 = 300.0; double yc1 = 225.0; double angle1 = 0.0 * (M_PI/180.0); /* angles are specified */ double angle2 = 360.0 * (M_PI/180.0); /* in radians */ cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 500, 500); //cairo_t *cr = cairo_create (surface); cairo_t *cr; cr = gdk_cairo_create(widget->window); //circ 1 cairo_set_line_width (cr, 10.0); cairo_arc (cr, xc1, yc1, radius1, angle1, angle2); cairo_stroke (cr); cairo_destroy(cr); return FALSE; } static gboolean time_handler(GtkWidget *widget) { if (widget->window == NULL) return FALSE; time_t curtime; struct tm *loctime; curtime = time(NULL); loctime = localtime(&curtime); strftime(buffer, 256, "%T", loctime); //printf("\n %f", radius1); gtk_widget_queue_draw(widget); return TRUE; } // get sockaddr, IPv4 or IPv6: void *get_in_addr(struct sockaddr *sa) { if (sa->sa_family == AF_INET) { return &(((struct sockaddr_in*)sa)->sin_addr); } return &(((struct sockaddr_in6*)sa)->sin6_addr); } int main (int argc, char *argv[]) { int sockfd; struct addrinfo hints, *servinfo, *p; int rv; int numbytes; struct sockaddr_storage their_addr; char buf[MAXBUFLEN]; socklen_t addr_len; char s[iNET6_ADDRSTRLEN]; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4 hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; // use my IP if ((rv = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); return 1; } // loop through all the results and bind to the first we can for(p = servinfo; p != NULL; p = p->ai_next) { if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("listener: socket"); continue; } if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { close(sockfd); perror("listener: bind"); continue; } break; } if (p == NULL) { fprintf(stderr, "listener: failed to bind socket\n"); return 2; } freeaddrinfo(servinfo); GtkWidget *window; GtkWidget *darea; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); darea = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER (window), darea); g_signal_connect(darea, "expose-event", G_CALLBACK(on_expose_event), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 600, 600); gtk_window_set_title(GTK_WINDOW(window), "timer"); g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) window); gtk_widget_show_all(window); time_handler(window); gtk_main(); //codigo socket printf("listener: waiting to recvfrom...\n"); while (1) { printf("dentro do while\n"); addr_len = sizeof their_addr; if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0, (struct sockaddr *) &their_addr, &addr_len)) == -1) { perror("recvfrom"); exit(1); } printf("listener: got packet from %s\n", inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *) &their_addr), s, sizeof s)); printf("listener: packet is %d bytes long\n", numbytes); buf[numbytes] = '\0'; printf("RECEBIDO: \"%s\"\n", buf); radius1 = atoi(buf); printf("\n %f", radius1); } //fim do codigo socket return 0; } Link to comment Share on other sites More sharing options...
pmg Posted February 28, 2012 Report Share Posted February 28, 2012 Duas perguntas: 1) se enquanto estas a desenhar o circulo recebes outro radius, o que queres que aconteca ao desenho incompleto? 2) no fim de desenhar o circulo, o que vais fazer? Sugestao: usa "blocking input", isto e, input que bloqueia e nao faz nada enquanto espera pela valor do radius. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Link to comment Share on other sites More sharing options...
Dr_Lion Posted February 29, 2012 Author Report Share Posted February 29, 2012 1- A minha ideia é serem duas tarefas separadas em que estou constantemente a receber valores do radius, e de segundo a segundo é feito o desenho com o valor presente nessa altura. Se receber mais valores a meio do desenho só teria efeito na próxima iteração de desenho. 2- No fim de desenhar o circulo a ideia é continuar a receber o valor proveniente do socket. Link to comment Share on other sites More sharing options...
BernardoLourenco Posted March 21, 2012 Report Share Posted March 21, 2012 Para realizares duas tarefas separadas ao mesmo tempo tens que utilizar as Threads. Uma Thread é uma função que corre ao mesmo tempo que o programa principal. São utilizadas quando essas funções são loops de eventos (no teu caso o gtk_main()) ou são processos muito demorados (descompressão ou desencriptação). Já que que vais utilizar o gtk, sugiro que utilizes a Thread do glib. http://developer.gnome.org/glib/2.30/glib-Threads.html Boa sorte, porque estas cenas são um bocado dificeis de perceber à primeira. 😁 Link to comment Share on other sites More sharing options...
Dr_Lion Posted March 22, 2012 Author Report Share Posted March 22, 2012 Optei por não usar o gtk visto que ia complicar muito o que era possível de ser feito mais simples e rápido com ferramentas já existentes. Mas de qualquer forma, obrigado pela ajuda. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now