Home > Guide veloci, programmazione > Guida Gtk+ a puntate ( XV parte )

Guida Gtk+ a puntate ( XV parte )

Continuiamo a parlare di gtk+, data la richiesta da parte di luky oggi parleremo dell’input da parte dell’utente tramite caselle di testo ( Entry → GtkEntry ) e ho inserito anche un po’ di funzioni da conoscere sui widget di cui non avevo parlato.

Iniziamo :)

Caselle di testo ( GtkEntry )

gtkentry.png

Una casella di testo è quella che potete vedere come esempio a lato. La loro funzione è quella di ricevere l’input da parte dell’utente. Possono anche essere usate per ricevere password o altri dati da non visualizzare durante la scrittura. In questo caso esse visualizzeranno un “pallino” per ogni carattere.

La loro creazione può avvenire con due funzioni: gtk_entry_new (), che non riceve parametri e crea una semplice entry senza limitazioni riguardo la lunghezza del testo che è possibile inserire, e gtk_entry_new_with_max_length (), che riceve come unico parametro la lunghezza massima dei caratteri che l’utente potrà inserire. In ogni caso si può impostare la lunghezza massima a parte una volta creata con gtk_entry_new () richiamando la funzione gtk_entry_set_max_length ().

Prima di continuare volevo dirvi che questo widget fa parte dei GtkEditable e quindi si possono usare le funzioni di quel tipo per operare con questo. Ad esempio per selezionare il testo si può far così:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 #include <gtk/gtk.h>
 
int main (int argc, char *argv[])
{
 GtkWidget *window, *entry;
 int position;
 
 gtk_init (&argc, &argv);
 
 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 gtk_window_set_title (GTK_WINDOW (window), "Hello Entry");
 g_signal_connect (G_OBJECT (window), "delete_event",
                   G_CALLBACK (gtk_main_quit), NULL);
 
 entry = gtk_entry_new ();
 gtk_entry_set_text (GTK_ENTRY (entry), "Hello Entry World ;)");
 gtk_container_add (GTK_CONTAINER (window), entry);
 
 gtk_widget_show_all (window);
 gtk_editable_select_region (GTK_EDITABLE (entry), 6, 11);
 gtk_main ();
 
 return 0;
}

O per disabilitare l’inserimento del testo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <gtk/gtk.h>
 
int main (int argc, char *argv[])
{
 GtkWidget *window, *entry;
 int position;
 
 gtk_init (&argc, &argv);
 
 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 gtk_window_set_title (GTK_WINDOW (window), "Hello Entry");
 g_signal_connect (G_OBJECT (window), "delete_event",
                   G_CALLBACK (gtk_main_quit), NULL);
 
 entry = gtk_entry_new ();
 gtk_editable_set_editable (GTK_EDITABLE (entry), FALSE);
 gtk_container_add (GTK_CONTAINER (window), entry);
 
 gtk_widget_show_all (window);
 gtk_main ();
 
 return 0;
}

Comunque dovevo dire una cosa all’inizio delle puntate che essendo tutti questi widget possono essere nascosti ( gtk_widget_hide () ) e mostrati ( gtk_widget_show () o per mostrare anche eventuali sotto elementi del widget gtk_widget_show_all () ), disabilitati o abilitati ( gtk_widget_set_sensitive () che accetta come primo argomento il  widget a cui applicare l’abilitazione o la disabilitazione e come secondo argomento TRUE per abilitarlo o FALSE per disbailitarlo ), ecc.. tutte le funzioni le trovate come già detto altre volte nelle api delle gtk+.

Ora ritornando all’argomento delle GtkEntry vediamo come rendere un testo “oscurato” facendo visualizzare i pallini al posto delle scritte e di come inserire una stringa in un punto qualsiasi dell’entry e dell’eventuale testo contenuto.

Per quanto riguarda i pallini si ricorre alla funzione gtk_entry_set_visibility () che riceve come primo argomento la GtkEntry e come secondo argomento TRUE nel caso si voglia visualizzare il testo e FALSE nel caso si voglia visualizzare un pallino al posto di ogni carattere.

Per inserire il testo invece, come dicevo, bisogna ricorrere al tipo GtkEditable e alla funzione gtk_editable_insert_text (). Mostro prima il codice e poi spiego che facciam prima.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <gtk/gtk.h>
 
int main (int argc, char *argv[])
{
 GtkWidget *window, *entry;
 int position;
 
 gtk_init (&argc, &argv);
 
 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 gtk_window_set_title (GTK_WINDOW (window), "Hello Entry");
 g_signal_connect (G_OBJECT (window), "delete_event",
                   G_CALLBACK (gtk_main_quit), NULL);
 
 entry = gtk_entry_new ();
 gtk_entry_set_text (GTK_ENTRY (entry), "Hello World ;)");
 position = 6;
 gtk_editable_insert_text (GTK_EDITABLE (entry), "Entry ", -1, &position);
 /* Visualizzerà alla fine la frase "Hello Entry World ;)" */
 gtk_container_add (GTK_CONTAINER (window), entry);
 
 gtk_widget_show_all (window);
 gtk_main ();
 
 return 0;
}

Come si può vedere i parametri della funzione sono in ordine:

  1. La entry convertita in GtkEditable
  2. Il testo da inserire
  3. La lunghezza del testo ( o -1 per farlo calcolare alla funzione )
  4. La posizione in cui inserire il nuovo testo

Per finire con le entry resta solo da capire come recuperare il testo inserito, come eliminare una parte del testo all’interno dell’entry e infine i segnali che possono essere collegati.

Per recuperare il testo si utilizza la funzione gtk_entry_get_text () che riceve come unico argomento l’entry da cui prelevare il testo. Restituisce un “const char *” ovvero una stringa non modificabile ( che all’uscita dovrà essere riconvertita tramite cast a “char *” per poterla assegnare a qualche variabile ) essa non ha bisogno di essere liberata in quanto è allocata staticamente dalla funzione. Non sarà mai nulla la stringa ritornata infatti per controllare che sia stato inserito qualcosa bisogna vedere se il primo elemento dell’array di char è uguale a 0 ( o ‘\0′ o 0×00 o chiamatelo un po’ come vi pare ).
Per finire in bellezza con le funzioni principali che riguardano il tipo GtkEntry parliamo di come si può eliminare una porzione di testo da quello inserito. E lo si fa con la funzione gtk_editable_delete_text () che riceve come primo argomento la entry convertita a GtkEditable, come secondo argomento la posizione iniziale da cui eliminare il testo e come terzo argomento il punto finale in cui terminare l’eliminazione.

E andiamo ora a vedere i segnali, faccio la descrizione dei tre principali relativi più che altro al tipo GtkEditable:

  •  ”changed” – Viene inviato quando il testo all’interno dell’entry è cambiato, quindi quando: si inserisce un nuovo carattere, si elimina un carattere o una porzione di testo, si incolla e si taglia qualcosa.. in pratica ogni qualvolta venga cambiato.
  • “delete-text” – Viene inviato solamente quando si cancella una parte del testo o un carattere.
  • “insert-text” – Viene inviato solamente quando si inserisce qualcosa nel testo.

Fine Quindicesima Puntata
Bene, abbiam finito anche le entry così da poter iniziare a sviluppare i primi programmini grafici che prendono un input dall’utente. Buona programmazione ;)

Ciauz ;)

  1. luky
    12 giugno 2009 a 10:16 | #1

    ma perchè non funziona……che devo mettere nella funzione “cliccato” per far inserire del testo in entry???

    #include

    void cliccato(GtkWidget *entry){

    gtk_entry_set_text (GTK_ENTRY (entry), “Hello Entry World ;) ”);

    gtk_widget_show(entry);
    }
    int main(int argc, char *argv[]){

    GtkWidget *window, *table, *button, *entry;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 700, 700);
    gtk_widget_show(window);
    table = gtk_table_new(TRUE, 2,2);
    gtk_container_add(GTK_CONTAINER(window), table);
    gtk_widget_show(table);
    entry = gtk_entry_new();
    gtk_table_attach(GTK_TABLE(table), entry, 0,1, 0,1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,0,0);
    gtk_widget_show(entry);
    button = gtk_button_new_with_label(“inserisci”);
    gtk_table_attach(GTK_TABLE(table), button, 1,2,1,2,GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND,0,0);
    gtk_widget_show(button);

    gtk_signal_connect(GTK_OBJECT(button), “clicked”, GTK_SIGNAL_FUNC(cliccato), NULL);
    gtk_signal_connect(GTK_OBJECT(window), “delete_event”, GTK_SIGNAL_FUNC(gtk_main_quit), NULL);

    gtk_main();

    }

  2. 13 giugno 2009 a 14:37 | #2

    mmh, devi passare la entry come parametro ( al posto dell’ultimo NULL ), nella funzione che connette il segnale clicked del pulsante a “cliccato”.
    E poi, usa g_signal_connect, gtk_signal_connect è deprecato nelle nuove gtk.

    PS: hds, ma perche ci sono due pulsanti che fanno la stessa cosa nei commenti? xD (Preview e Anteprima)

  3. 13 giugno 2009 a 17:31 | #3

    Fritto misto di plugin XD

  4. 13 giugno 2009 a 17:41 | #4

    Un esempio pratico vale più di mille parole:
    http://www.hds619.net/lys_show.php?c=‘file2kwEY.c’

    ( Comunque se stai seguendo quella guida di mathematik o come si chiama quel sito.. sulle gtk+ in italiano lasciala perdere perché è riferita alle gtk+ 1 in cui quasi tutti i widget ormai sono deprecati e spostati in altre librerie o sostituiti da tipi più efficienti )

  5. luky
    14 giugno 2009 a 15:15 | #5

    l’esempio non mi funziona……scrivo nella entry ma non succede niente

  6. luky
    14 giugno 2009 a 15:15 | #6

    ho provato pure a passare entry al posto di NULL nek g_signal

  7. 14 giugno 2009 a 23:45 | #7

    Avvia da terminale dovrebbe scriverti ogni volta che cambi testo il nuovo testo inserito nel terminale.

  8. luky
    15 giugno 2009 a 10:56 | #8

    ahh ora capisco a che serve g_print….. però non ho capito certe cose : cosa fai con questa funzione?? GtkEntry *entry = GTK_ENTRY (editable);

  9. luky
    15 giugno 2009 a 11:12 | #9

    ha si un’altra cosa….il programma che hai fatto non modifica i widget, io volevo sapere come fare per esempio se schiacci un bottone a modificare il testo nella entry. Grazie per la disponibilità :)

  10. Anonimo
    15 giugno 2009 a 22:19 | #10

    converto il tipo GtkEditable che viene passato automaticamente alla funzione quando si usa il segnale changed ad una entry al tipo GtkEntry per poi operare più semplicemente nell’ottenere il testo inserito.

  11. Anonimo
    15 giugno 2009 a 22:21 | #11

    Mi sembra di averlo scritto nella guida mm: boh vabbè male che vada ripeto:

    gtk_entry_set_text (GTK_ENTRY (tua_entry), “Nuovo testo”);

  12. 15 giugno 2009 a 22:38 | #12

    sii hds, serviamo la pappa pronta vai xD

  13. luky
    15 giugno 2009 a 23:16 | #13

    non intendevo quello….mi spiego meglio: io volevo sapere per esempio cosa devo mettere nella funzione “cliccato” in modo che mi cambi un label con il testo inserito nell’entry, spero di essermi spiegato

  14. 16 giugno 2009 a 4:45 | #14

    Dopo aver recuperato il testo con gtk_entry_get_text () basta usare la funzione gtk_label_set_text ().

    Example:
    string = (char *) gtk_entry_get_text (GTK_ENTRY (entry));
    gtk_label_set_text (GTK_LABEL (label), string);

  15. luky
    16 giugno 2009 a 13:44 | #15

    scusami se sono così assillante ma ora non riesco a capire cos’è che non va……

    #include
    #include
    #include

    void login(char username){
    gchar user[10] = “luca”;
    if (strcmp(username, user) != 0) {
    mkdir(“C:/Users/Luca/Desktop/ok”);
    }
    else { mkdir(“C:/Users/Luca/Desktop/no”);
    }}

    int main(int argc, char *argv[]){

    GtkWidget *window, *table, *label, *entry, *button;

    char username[10];
    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 200, 500);

    table = gtk_table_new(4, 1, FALSE);
    gtk_container_add(GTK_CONTAINER(window), table);

    label = gtk_label_new(“inserire i dati d’accesso:”);
    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);

    entry = gtk_entry_new();
    gtk_entry_set_text(GTK_ENTRY(entry), “username”);
    username = gtk_entry_get_text(GTK_ENTRY(entry));
    gtk_table_attach(GTK_TABLE(table), entry, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);

    entry = gtk_entry_new();
    gtk_entry_set_text(GTK_ENTRY(entry), “password”);

    gtk_table_attach(GTK_TABLE(table), entry, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);

    button = gtk_button_new_with_label(“login”);
    gtk_table_attach(GTK_TABLE(table), button, 0, 1, 3, 4, GTK_FILL, FALSE, 0, 0);

    g_signal_connect(G_OBJECT(button), “clicked”, G_CALLBACK(login), username);
    g_signal_connect(G_OBJECT(window), “delete_event”, G_CALLBACK(gtk_main_quit), NULL);
    gtk_widget_show_all(window);
    gtk_main();
    }

  16. Anonimo
    16 giugno 2009 a 14:14 | #16

    Fai il get_text subito dopo aver creato l’entry e prima ancora di visualizzarla all’utente logico che avrai come testo quello che hai inserito.
    Dovresti passare a g_signal_connect l’entry e poi dalla funzione collegata eseguire il get del testo inserito. ( In questo tuo caso specifico dovresti creare un array di 2 widget per tutte e 2 le entry così da poterle passare tutte e due in un colpo solo ).

    Ciauz

    P.s.: Per pubblicare codice usa lys ( http://www.hds619.net/lys.php ) o qualsiasi altro nopaste altrimenti diventa difficile per gli legge i commenti seguirne il filo.

  17. luky
    16 giugno 2009 a 15:22 | #17

    ho fatto come hai detto tu ma quando compilo mi esce l’errore : “incompatible types in assignament” nella funzione “cliccato” quando inizializzo “username” —>http://www.hds619.net/lys_show.php?c=mainDH0p4.c

  18. 17 giugno 2009 a 5:25 | #18

    dichiarali come puntatori a char, e usa il cast a puntatore a char quando assegni il valore di ritorno della funzione gtk_entry_get_text ().

  19. luky
    17 giugno 2009 a 14:47 | #19

    scusa la mia ignioranza ma non sò cosa significa cast a puntatore non è che avresti la pazienza di modificare il mio codice così riesco a capire…….ah se puoi mi spieghi perchè dovrei dichiararli come puntatori, a quanto ho capito il puntatore sarebbe l’indirizzo di memoria dove c’è il dato ma a me che mi serve, non mi serve il dato?? grazie….

  20. luky
    17 giugno 2009 a 15:34 | #20

    mi sono appena accorto di avere scritto ignoranza con al i…..^.^

  21. luky
    18 giugno 2009 a 11:48 | #22

    con questo cosa hai fatto?? GtkWidget **entry = (GtkWidget **) data;

  22. 18 giugno 2009 a 21:44 | #23

    ha preso la entry passata nella funzione mmh

  23. luky
    18 giugno 2009 a 23:06 | #24

    io ho seguito la guida in c in blacklight ma (GtkWidget **) è un cast? e perchè ci sono due asterischi?

  24. 19 giugno 2009 a 3:22 | #25

    Un cast è qualunque conversione di tipo, che sia ad (int), un (void *), un (pinco pallino **) ecc…

  25. luky
    19 giugno 2009 a 17:41 | #26

    come posso settare la posizione della finestra con valori x e y e non GTK_WIN_POS_CENTER??

  26. 19 giugno 2009 a 18:33 | #27

    Non conoscevo una funzione che permettesse di fare ciò, girando tra le api delle gtk+ ho trovato questa: gtk_window_move ().

    Come primo argomento la finestra da “spostare”, come secondo di quanto spostarla sull’asse x e come ultimo di quanto spostarla sull’asse y ( il tutto espresso in pixel ).
    Conta però che lo spostamento se non ho capito male avviene dalla posizione corrente e non dalla coordinata 0,0 dello schermo. Quindi dovresti usarla insieme alla funzione gtk_image_get_position () ( 1. parametro la finestra, 2. parametro l’indirizzo di una variabile int che sarà il valore dell’asse x, 3. parametro l’indirizzo di una variabile int che sarà il valore dell’asse y ) e con i valori ottenuti capire bene dove posizionare la finestra.

  27. luky
    19 giugno 2009 a 19:18 | #28

    però è un pò strano che non si possa stabilire la posizione di una finestra direttamente……la potevano pure fare un funzione, quando usavo visual basic c’era, comunque grazie lo stesso

  28. luky
    19 giugno 2009 a 19:21 | #29

    non si potrebbe convertire la finestra in qualche widget per settare la pos, oppure non si può fare con qualche funzione screen??

  29. 19 giugno 2009 a 19:54 | #30

    I metodi che consiglio io son sempre orientati a non utilizzare mai funzioni deprecate che potrebbero sparire o cambiare radicalmente nelle versioni successive delle gtk+.
    Se però “insisti” ( come dice l’api delle gtk+ ) e vuoi impostare la posizione della finestra direttamente, anche se ciò potrebbe dare problemi con qualche window manager, esiste la funzione deprecata: gtk_widget_set_uposition ()
    1° parametro: il widget finestra, 2° parametro l’asse x, 3° parametro l’asse y.

  30. luky
    20 giugno 2009 a 14:55 | #31

    come faccio a passare al g_signal più argomenti?? ho provato con la , con && con || ma niente ……vorrei passare la entry e la window perchè la entry mi serve per il login e la window la devo distruggere e crearne un’altra…..

  31. 20 giugno 2009 a 21:43 | #32

    1. Utilizzi variabili globali
    2. Definisci globalmente delle strutture con i widget che vuoi passare insieme, e poi passi la struttura alla g_signal
    3. Crei array dinamici di widget come ho fatto io nell’ultimo esempio.

  32. 29 giugno 2009 a 16:40 | #33

    una piccola domanda.
    sto facendo una piccola calcolatrice, una volta premuto = deve spuntare il risultato dell’operazione nel GtkEntry, ma in questo modo l’utente può modificare il testo del GtkEntry, esiste una funzione che permette di settare il GtkEntry in modo che l’utente non possa modificare il contenuto ma solo leggerlo ?

  33. 29 giugno 2009 a 21:58 | #34

    Guarda il penultimo esempio di codice ;)

  34. luky
    8 luglio 2009 a 16:34 | #35

    scusami se ritorno a questo argomento ma non capisco perchè hai dovuto convertire il gtk_entry_get_text in gchar*…..ma questa funziona non ritorna già di suo gchar* e allora perchè la converti?

  35. 9 luglio 2009 a 3:08 | #36

    no, come detto nell’articolo:

    Per recuperare il testo si utilizza la funzione gtk_entry_get_text () che riceve come unico argomento l’entry da cui prelevare il testo. Restituisce un “const char *” ovvero una stringa non modificabile ( che all’uscita dovrà essere riconvertita tramite cast a “char *” per poterla assegnare a qualche variabile ) essa non ha bisogno di essere liberata in quanto è allocata staticamente dalla funzione. Non sarà mai nulla la stringa ritornata infatti per controllare che sia stato inserito qualcosa bisogna vedere se il primo elemento dell’array di char è uguale a 0 ( o ‘\0′ o 0×00 o chiamatelo un po’ come vi pare ).

  36. luky
    9 luglio 2009 a 18:57 | #37

    scusa se insisto ma voglio capire…..come mai nella libreria gtkentry.h c’è scritto gchar* gtk_entry_get_text()? gchar* non sarebbe il tipo di variabile che restituisce la funzione

  37. 10 luglio 2009 a 14:49 | #38

    Io mi attengo a quello che c’è nelle api ufficiali delle gtk+, comunque sono andato a controllare nell’header e io ho:

    /* returns a reference to the text */
    G_CONST_RETURN gchar* gtk_entry_get_text (GtkEntry *entry);

    G_CONST_RETURN viene descritta dalla documentazione come:

    By default, the macro expands to const. The macro should be used in place of const for functions that return a value that should not be modified. The purpose of this macro is to allow us to turn on const for returned constant strings by default, while allowing programmers who find that annoying to turn it off. This macro should only be used for return values and for out parameters, it doesn’t make sense for in parameters.

    Detto in parole povere nel nostro caso, converte il valore ritornato dalla funzione in un valore const per far si che non possa essere modificato all’uscita della funzione.

  1. Nessun trackback ancora...
Custom Avatars For Comments