Programación en
Linux con KDevelop 1.0
Solución a los ejercicios planteados en la
página:
Crear diálogos
personalizados (formularios) y gestionar eventos.
Autor: Guillermo 'guille' Som
Actualizado: 17/Jun/2003
Pues mira tú por dónde... no puse la solución al ejercicio que planteé en la página en la que se explica cómo crear formularios y acceder a los eventos (slots) de los controles (widgets), así que... aunque sea con cuatro años de retraso (supongo que lo habrás resuelto bien), aquí tienes el código con la solución.
¿No te acuerdas de cual era el ejercicio a resolver?
Pues era lo siguiente: (en esta página tienes más información)...sería interesante que nuestra aplicación tuviese un botón que nos permita borrar los elementos seleccionados de la lista.
Otra mejora podría ser sustituir el elemento seleccionado por el contenido de la caja de texto.
Y para terminar con los ejercicios (o proposiciones no indecentes), sería que se nos permitiera usar por defecto un nombre de fichero, de esa forma, cada vez que esa opción esté marcada y pulsemos en abrir o guardar, se use ese fichero en lugar de tener que preguntarnos el nombre...Este es el código a usar, el diseño del formulario o ventana tendrás que hacerlo por tu cuenta.
En el fichero .h tendrás que añadir estas declaraciones bajo private slots:
// Conectar la pulsación de los botones Añadir y Eliminar a las funciones void cmdDel_click(); void cmdReplace_click();En la sección private: vamos a crear una enumeración para la acción a tomar en la función testFile (que se encargará de comprobar si se usa o no el fichero por defecto):
// Enumeración para la acción a tomar en la función testFile enum eAccion {Leer_Fichero, Guardar_Fichero}; // Función para comprobar si se usa o no el fichero por defecto QString testFile( eAccion accion );
En el fichero .cpp tendrás que añadir lo siguiente:
En el constructor de la clase habrá que conectar los nuevos controles (widgets) con sus respectivos eventos (slots):// ------------------------------------------------------------------------ // Solución de los ejercicios // ------------------------------------------------------------------------ // Conectar la pulsación de los botones Añadir y Eliminar a las funciones connect( cmdDel, SIGNAL(clicked()), SLOT(cmdDel_click()) ); connect( cmdReplace, SIGNAL(clicked()), SLOT(cmdReplace_click()) );Este será el código del botón eliminar:
void KPrueba02::cmdDel_click(){ // Cuando pulsamos en el botón Eliminar lblStatus->setText("Eliminando..."); // Borramos todos los elementos seleccionados uint i; // número de elementos antes de borrar uint t = lstNames->count(); // Sólo si hay elementos en la lista... if(t<1) lblStatus->setText("No hay nada que borrar..."); else{ // Es curioso, pero de esta otra forma no funciona: // for( i = t - 1 ; i >= 0; i-- ) for( i = t; i > 0; i-- ) if( lstNames->isSelected(i-1) ) // eliminamos el elemento seleccionado lstNames->removeItem(i-1); // Si el número de elementos actual es diferente de lo que había if( t != lstNames->count() ) // es que se ha modificado la lista... modificado = true; QString s; // Convertimos el número en una cadena s.setNum( lstNames->count() ); // mostramos el número de elementos en la lista lblStatus->setText( "Nombres en la lista: " + s ); } }Este otro, es el código del botón Reemplazar:
void KPrueba02::cmdReplace_click(){ // Al pulsar en Reemplazar // Asignamos el contenido del textbox al elemento seleccionado de la lista QString s = txtName->text(); // currentItem nos da el número de elemento actualmente seleccionado // en caso de que haya más de un elemento seleccionado, // devolverá el último que se seleccionó int i = lstNames->currentItem(); // si vale -1 es que no hay seleccionado if( i != -1){ // en caso contrario, cambiamos el contenido del elemento seleccionado lstNames->changeItem(s, i); // marcamos el flag de que se ha modificado la lista modificado = true; } }Esta es la función testFile:
// Cuando se pulsa en Guardar o Abrir se comprobará si se quiere usar el fichero por defecto // en caso de que sea así, no se mostrará el cuadro de diálogo, // salvo que el fichero en cuestión no exista. // Esta función se encargará de mostrar el cuadro de diálogo si procede. // Devolverá una cadena (QString) con el nombre del fichero a usar. QString KPrueba02::testFile( eAccion accion ){ // El checkbox estará seleccionado, // si queremos usar el fichero por defecto if( chkFile->isChecked() ){ QString s; // esta variable sólo es visible dentro del bloque if // Asignar el nombre del fichero s = lblFile->text(); // Si es una cadena vacía, es que no hay nombre asignado if( !s.isEmpty() ){ // Si la accion es leer, devolver el nombre del fichero sólo si existe if( accion == Leer_Fichero ){ QFile f(s); if( f.exists() ) return s; }else return s; } } // Si llegamos aquí, es que tenemos que mostrar el diálogo QString sFile; // Comprobar si es el de abrir o guardar if( accion == Leer_Fichero ) // Seleccionar el fichero para abrir sFile = QFileDialog::getOpenFileName("./", "*.txt", this); else // Seleccionar el fichero para guardar sFile = QFileDialog::getSaveFileName("./", "*.txt", this); // Devolver el nombre del fichero seleccionado // en caso de que se haya cancelado, la cadena estará vacia, // pero ese caso se tiene en cuenta en las funciones correspondientes return sFile; }Por último, veamos el código de los botones Guardar y Abrir con los cambios para usar testFile:
void KPrueba02::cmdSave_click(){ // Cuando se pulsa en Guardar // Sólo si hay elementos en la lista if( lstNames->count() ){ // Preguntar el nombre del fichero //QString sFile = QFileDialog::getSaveFileName("./","*.txt",this); // Usamos la función que comprueba si se debe usar el fichero por defecto QString sFile = testFile( Guardar_Fichero); // Si se ha seleccionado un nombre // (cuando se pulsa en cancelar se devuelve una cadena vacia) if( !sFile.isEmpty() ){ // Asignar el fichero seleccionado QFile f(sFile); // Abrirlo para escribir en él f.open(IO_WriteOnly); // Guardar cada elemento de la lista uint i; for( i=0;i<lstNames->count();i++ ){ // Añadir un retorno de carro y cambio de línea... al estilo MS-DOS QString c = lstNames->text(i) + QString("\n\r"); // writeBlock espera una cadena y el número de caracteres f.writeBlock( c, c.length() ); lblStatus->setText("guardando... "+c); } // cerrar el fichero f.close(); modificado = false; lblStatus->setText("Datos guardados en: " + sFile); // Asignar el nombre del fichero que se puede usar por defecto lblFile->setText( sFile ); }else lblStatus->setText("No has seleccionado un nombre"); }else lblStatus->setText("No hay elementos que guardar!"); } void KPrueba02::cmdOpen_click(){ // Cuando se pulsa en Abrir // Si se ha modificado la lista, preguntar si se guarda... if( modificado ){ if( QMessageBox::warning(this,"Abrir - Prueba de Diálogos", "¡ATENCION! La lista se ha modificado y no está guardada\n\n¿Quieres guardarla?", " Si ", " No ",0,0)==0 ) cmdSave_click(); } // Borrar el contenido de la lista lstNames->clear(); // Preguntar el nombre del fichero a abrir //QString sFile = QFileDialog::getOpenFileName("./","*.txt",this); // Usamos la función que comprueba si se debe usar el fichero por defecto QString sFile = testFile( Leer_Fichero); // Si se ha seleccionado un nombre // (cuando se pulsa en cancelar se devuelve una cadena vacia) if( !sFile.isEmpty() ){ // Asignar el fichero seleccionado QFile f(sFile); // Abrirlo para lectura f.open(IO_ReadOnly); // Leer del fichero y asignarlo al listbox QString s; // Asignamos el fichero a un TextStream para poder "navegar" por el contenido QTextStream t(&f); while( !t.eof() ) { // Leemos la siguiente línea s = t.readLine(); // Quitamos los espacios del principio y final s = s.stripWhiteSpace(); // Si no es una cadena vacia... if( !s.isEmpty() ) // Lo añadimos a la lista lstNames->insertItem(s); } // cerrar el fichero f.close(); modificado = false; s.setNum( lstNames->count() ); lblStatus->setText("Nombres en la lista: " + s ); // Asignar el nombre del fichero que se puede usar por defecto lblFile->setText( sFile ); }else lblStatus->setText("No has seleccionado un nombre"); }Bueno, esto es todo... menos mal que siempre habrá gente que lea esto "mucho" después de que fuera originalmente publicado (me refiero sobre todo al ejercicio), así no habrá problemas con este "desfase" de tiempo...
Nos vemos.
GuillermoNerja, 17 de Junio de 2003