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 )

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:
- La entry convertita in GtkEditable
- Il testo da inserire
- La lunghezza del testo ( o -1 per farlo calcolare alla funzione )
- 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
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();
}
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)
Fritto misto di plugin XD
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 )
l’esempio non mi funziona……scrivo nella entry ma non succede niente
ho provato pure a passare entry al posto di NULL nek g_signal
Avvia da terminale dovrebbe scriverti ogni volta che cambi testo il nuovo testo inserito nel terminale.
ahh ora capisco a che serve g_print….. però non ho capito certe cose : cosa fai con questa funzione?? GtkEntry *entry = GTK_ENTRY (editable);
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à
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.
Mi sembra di averlo scritto nella guida mm: boh vabbè male che vada ripeto:
gtk_entry_set_text (GTK_ENTRY (tua_entry), “Nuovo testo”);
sii hds, serviamo la pappa pronta vai xD
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
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);
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();
}
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.
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
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 ().
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….
mi sono appena accorto di avere scritto ignoranza con al i…..^.^
http://www.hds619.net/lys_show.php?c=checkQQcg0.c
con questo cosa hai fatto?? GtkWidget **entry = (GtkWidget **) data;
ha preso la entry passata nella funzione mmh
io ho seguito la guida in c in blacklight ma (GtkWidget **) è un cast? e perchè ci sono due asterischi?
Un cast è qualunque conversione di tipo, che sia ad (int), un (void *), un (pinco pallino **) ecc…
come posso settare la posizione della finestra con valori x e y e non GTK_WIN_POS_CENTER??
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.
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
non si potrebbe convertire la finestra in qualche widget per settare la pos, oppure non si può fare con qualche funzione screen??
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.
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…..
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.
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 ?
Guarda il penultimo esempio di codice
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?
no, come detto nell’articolo:
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
Io mi attengo a quello che c’è nelle api ufficiali delle gtk+, comunque sono andato a controllare nell’header e io ho:
G_CONST_RETURN viene descritta dalla documentazione come:
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.