Ayuda con filtracion de datos mediante keyreleased
Buenas, estoy haciendo un sistema y aplique un buscador con el keyreleased y me funciono a la perfeccion pero quisiera saber si me ayudan para que se muestre solo con las letras que inicia cada dato por ejemplo:
Buscar: M
*Maria
*Marta
*Carlos Martinez
en lugar de:
Buscar: M
*Maria
*Carmen
- Inicie sesión o regístrese para enviar comentarios
fuente
De dónde vienen tus datos? De una base de datos, o están en memoria?
No es recomendable que hagas un SELECT en cada teclazo del usuario. Pero si son datos que ya tienes en memoria y sólo quieres filtrar sobre eso, pues con una expresión regular. Aunque no es muy claro qué quieres buscar; con tu ejemplo, podríamos decir que sólo quieres buscar M mayúscula, o sea que la búsqueda sea sensible a mayúsculas, que es lo más fácil; o también quieres encontrar por ejemplo "mario" pero no "carMen"?
En fin, si es insensible a mayúsculas pero que sea la primera letra de una palabra, me parece que es una expresión regular
[Mm].*|.*\s[Mm].*
En Groovy esta expresión:
['Maria','carMen','mario','Carlos Marquez'].findAll { it ==~ /[Mm].*|.*\s[Mm].*/ }
Me devuelve Maria, mario, Carlos Marquez
los datos los recojo de una
los datos los recojo de una base de datos... entonces que es recomendable para filtrar datos?
porque cuando yo busco por ejemplo:
Buscar: c (ya sea en mayuscula o minuscula)
me salen datos como por ejemplo:
Carlos Arias
Francisco Luna
Martha Sanchez
y lo que yo quiero es q solo muestre datos q empiecen con lo que yo pongo en el jtextfield que no importe si yo pongo en mayusculas o minusculas
ilike
Tu PreparedStatement con este SQL
SELECT * FROM tabla WHERE campo ILIKE ?
Y le pasas como parámetro
C*
(supongo que actualmente le pasas*C*
)La cosa es que si ejecutas esa consulta en respuesta a un teclazo del usuario, puedes terminar enviando muchísimas consultas seguidas y finalmente ni vas a usar los resultados de las consultas intermedias. Eso va a generarle mucha carga a la base de datos, además innecesaria porque ni siquiera estás utilizando los resultados. Por ejemplo si empiezas a teclear CAR, y lo haces rápido, vas a disparar tres consultas a la base de datos, pero solamente vas a usar los resultados de la última; los de las otras dos ya ni te sirven.
Lo mejor para esos casos es una combinación de búsqueda en base de datos y posteriormente un filtro sobre los resultados en memoria, combinado con un timer para hacer la búsqueda periódicamente cuando el valor cambia, o un buffer para agrupar todos los teclazos y solamente realizar la búsqueda cuando hay una pausa mayor a cierto tiempo entre teclazos.
Gracias, pero como haria para
Gracias, pero como haria para que tecleando una letra me salgan todos los datos que "EMPIECEN" con dicha letra
Desde luego gracias por responder
Para explicarlo mejor:Yo
Este es otro problema que tengo es con defimalformat
Para explicarlo mejor:
Yo ingreso estos datos:
http://www.subirimagenes.net/i/140813091750106198.png
Y quisiera que no pase esto:
http://www.subirimagenes.net/i/140813091757917523.png
Gracias de antemano
DecimalFormat
Ese es sencillo.
new DecimalFormat("0.00")
. Si lo quieres con comas separando magnitudes, el formato sería "#,##0.00"DecimalFormat
Y eso como le aplicaria en el jtable lo estaba intentando pero no sabia como!
ni idea
Tiene años que no toco Swing.
Probablemente no es necesario DecimalFormat
Sería bueno que mostraras un poco del código que estás usando para asignar los datos a tu JTable... ¿estás usando el diseñador de formularios de netbeans o estás desarrollando todo el código tú?
@ezamudio Estoy intrigado con
@ezamudio Estoy intrigado con lo que acabas de decir sobre filtrar los resultados en memoria, el timer y/o el buffer, yo suelo hacer lo mismo que menciona kristxpher, lo de las consultas cada vez que se da un teclazo, porque no se me ocurría ningún otro método. ¿Tendrás un ejemplo de como implementar el filtro de resultados en la memoria porfavor?
no
No tengo código para eso, pero hay varias maneras de implementar ese patrón. Pero probablemente ya haya alguna biblioteca que lo haga. Y si no, pues una manera simple es más o menos así (me lo estoy improvisando, en Groovy):
JdbcTemplate jdbc //para buscar en base de datos
String query = "SELECT *FROM tabla WHERE columna ILIKE ?" //configurable
private List<Map<String,Object>> results //la lista obtenida
String columna //La columna por la que quieren filtrar
private String last //La ultima cadena buscada
void reset() {
results = null
last = null
}
//Este lo llaman cada keyPressed
List<Map<String,Object>> filtra(String s) {
s = s.toLowerCase()
if (last != null && !(last.startsWith(s) || s.startsWith(last))) {
results = null
}
if (results == null) {
//TODO esto no debería hacerse en el mismo hilo de la GUI, hay que usar SwingWorker y sincronizar esto para evitar que se hagan varias llamadas si la consulta se tarda
results = jdbc.queryForList(query, s+"*")
last = s
return results
} else {
last = s
return results.findAll { it[columna] == null || it[columna].empty || it[columna].toLowerCase().startsWith(s) }
}
}
}
De tu GUI debes tener un KeyListener o como se llame pegado a un JTextField, ese recibe los teclazos (y ahí harías el buffering en todo caso), y ahí es donde invocas al Buscador, pasándole el texto actual del textfield. El Buscador la primera vez que tecleas algo, como no tiene resultados, va a la base de datos por ellos, pero de ahí en adelante solamente filtra en memoria, a menos que la cadena cambie por completo, pero sirve para cuando estás tecleando y si acaso borras alguna cosa.
Suponte que está en blanco tu campo. Tecleas C, entonces el Buscador va a la base de datos por los registros que comienzan con C o c. Luego tecleas A, entonces sobre los registros que ya trajo el Buscador, que ya los tiene en memoria, filtra y te devuelve sólo los que empiezan con CA (combinaciones de mayúsculas/minúsculas). Luego tecleas R, entonces igual en memoria te trae los que empiezan con CAR. Das backspace, la nueva cadena es CA otra vez, el buscador te da esos filtrando en memoria. Tecleas M, filtra en memoria y te trae los que empiezan con CAM. Pero si seleccionas el texto y tecleas D, entonces se sustituye todo y como D no se parece en nada a lo que estabas filtrando, pues va de nuevo a la base de datos.
En cuanto al buffer de teclazos, es un poco más elaborado; es algo similar a lo que hace Hystrix con lo de colapsar varios eventos en uno solo.
Codigo
Este es el codigo que utilizo para mostrar los datos en el jtable
initComponents();
conexion();
cargarProgramas("");
FormatoProgramas();
centrar_datos(0);
centrar_datos(2);
centrar_datos(3);
centrar_datos(4);
centrar_datos(5);
setLocationRelativeTo(null);
}
private void cargarProgramas(String valor) {
try {
String titulos[] = {"Cód.", "Programas", "Precio", "Idioma", "Clasificación", "Tamaño"};
m = new DefaultTableModel(null, titulos);
JTable p = new JTable(m);
String fila[] = new String[6];
TblProgramas.conectate obj = new TblProgramas.conectate();
String consulta = "SELECT * FROM verprogramas where CONCAT(idProgramas,' ',Programas,' ',Precio,' ',Idioma,' ',Clasificacion, Tamano) LIKE '%"+valor+"%'";
ResultSet r;
r = obj.Listar(consulta);
while (r.next()) {
fila [0] = r.getString(1);
fila [1] = r.getString(2);
fila [2] = r.getString(3);
fila [3] = r.getString(4);
fila [4] = r.getString(5);
fila [5] = r.getString(6);
m.addRow(fila);
}
tblProgramas.setModel(m);
decimalestabla(2);
centrar_datos(0);
centrar_datos(2);
centrar_datos(3);
centrar_datos(4);
centrar_datos(5);
FormatoProgramas();
sorter = new TableRowSorter<TableModel>(m);
tblProgramas.setRowSorter(sorter);
this.tblProgramas.setModel(m);
tblProgramas.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, "Error al extraer los datos", "Advertencia", JOptionPane.WARNING_MESSAGE);
}
esta es la clase que cree para darles formato a los decimales:
private DecimalFormatSymbols simbolos;
private DecimalFormat formateador;
public Renderdeci() {
simbolos = new DecimalFormatSymbols();
simbolos.setDecimalSeparator('.');
formateador = new DecimalFormat("###0.00", simbolos);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
return this;
}
}
y asi es como la inserto:
tblProgramas.getColumnModel().getColumn(colum).setCellRenderer(new Renderdeci());
}
no era necesario que
no era necesario que mostraras todo el código para los decimales ni tampoco es necesaria tu clase para dar formato .
con una línea de código puedes agregar lo que preguntabas y es mas legible
//este código inserta una fila con una sola columna , agregale mas columnas si deseas
m.addRow(new String[]{ new DecimalFormat("#,##0.00").format(numero)});
DecimalFormat
Hola de nuevo, bueno yo no soy un experto en el lenguaje ni en swing, pero puedo ver que hay algunos problemas de diseño en tu código (revuelves código de manejo de interfaz gráfica con consultas a la base de datos, por ejemplo) y esto a la larga te puede traer confusiones o problemas cuando quieras dar mantenimiento al programa.
Bueno, como tu código es funcional, me propuse hacer un par de sugerencias para ayudarte a que quede como deseas haciendo los menos cambios posibles.
1) He visto que estás declarando un arreglo de Strings para crear la fila:
String fila[] = new String[6];
lo cual creo que es un error porque el formateador DecimalFormat no te cambiará el formato de un String, sino de un número (por ejemplo, Double), por lo que mi primera recomendación es que cambies ese arreglo de String por un arreglo de Object:Object fila[] = new Object[6];
2) Estás dándole formato a la columna de Precio después de haber insertado todas las filas que vienen de la base de datos, te recomiendo que muevas las instrucciones
decimalestabla(2);
antes del
while(r.next())
3) Investigué en google un ejemplo de DefaultTableCellRenderer y me encontré con este link: http://stackoverflow.com/questions/9834508/defaulttablecellrenderer-gett...
Por lo que vi que es necesario agregar un par de instrucciones al método que estás sobreescribiendo en Renderdeci:
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
this.setText(formateador.format(value));
return this;
}
4) Estás guardando todos los datos de tus filas en un mismo arreglo, te recomiendo que dentro de
while(r.next())
instancies de nuevo el arreglofila = new Object[6];
5) Estás obteniendo puros Strings con el método
r.getString();
, te recomiendo que cambies de método por cada tipo de dato que te devuelve cada columna, por ejemplo, para precio supongo que querrás usarr.getDouble(3);
Uff, espero no se me esté olvidando nada jeje, con esto creo que ya debería formatearte el número como tú quieres
Gracias
Muchas Gracias... hare lo que me sugieres... esas respuestas son las que me ayudan a mejorar... ya que estoy aprendiendo
De nuevo gracias!!
Funciona
He hecho lo que me has sugerido y si me sirvio pero me sale con un solo decimal es decir 2.0, 8.0, etc..
No lo entiendo xq yo declaro esto en el decimalformat (###0.00)
De antemano gracias, hasta ahora ha sido la mejor respuesta
Problema de palabras Parecidas
Para encontrar textos con palabras parecidas existe el algoritmo Levenshtein. tiene implementaciones en varios lenguajes e incluso en bases de datos.
Mientras que el problema de las consultas a la base de datos para esa particular funcionalidad podría servirte una base de datos NOSQL. Mongodb u otra.
WHAT?
En serio estás recomendando usar NoSQL simplemente por un algoritmo que además está super sobrado para lo que piden?
Solo es una opción
Solo son opciones, si les puede servir y si realmente es lo que buscan.
Para el requerimiento del inicio, no para el segundo.
LLegue muy tarde al foro...
Pues
Hola, pues no será posible saber qué está pasando si no podemos ver el código... ¿ya probaste debuggeando y poniendo puntos de interrupción para ver qué entra y qué sale de la instrucción
formateador.format();
?Si quieres, puedes postear aquí una parte RELEVANTE de tu código (no postees todo porque es confuso), alguna parte que no entiendas como funciona o donde creas que esté el error
Clase
No se en que este mal pero hice lo que me dijiste en la clase renderdeci y nada
este es el codigo de la clase:
private final DecimalFormatSymbols simbolos;
private final DecimalFormat formateador;
public Renderdeci() {
simbolos = new DecimalFormatSymbols();
simbolos.setDecimalSeparator('.');
formateador = new DecimalFormat("###0.00");
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
this.setText(formateador.format(value));
return this;
}
}
setMinimumFractionDigits
¿Ya probaste poniendo esto en tu constructor:
formateador.setMinimumFractionDigits(2);
?EDICION: También creo que te falta asignarle los símbolos al formateador:
formateador = new DecimalFormat("#,##0.00", simbolos);
Solucionado
Muchas Gracias ya lo solucione.. no hubo necesidad de crear la clase... tan solo hice los cambios que me dijiste sobre object, etc...
y lo que hice fue:
simbolo.setDecimalSeparator('.');
DecimalFormat formateador = new DecimalFormat("###0.00", simbolo);
while(r.next())
.....
fila [2] = formateador.format(r.getFloat(3))
Y listo todo me funciono!
Y ahora volviendo al tema principal (que ya me desvie jeje) tu sabes como hacer lo del filtro de datos pero solo que me aparezca datos que inicien con lo que yo escribo!
ya te dijeron
Ya te dijo ezamudio en los primeros comentarios hechos, que puedes utilizar en tu consulta
"SELECT * FROM tabla WHERE campo LIKE '" + valor + "%'"
,y además filtrar los datos obtenidos mediante expresiones regulares.
Aunque en vez de usar la consulta "plana" te recomendaron usar PreparedStatement e insertar el string de filtro. También por rendimiento, ezamudio te recomendó hacer una sola consulta a la base de datos y para el resto de tecleos filtrar a partir de los datos que ya tienes en memoria, para lo cual también nos mostró un poco de código de cómo podría hacerse (aunque en groovy y usando clases especiales como JdbcTemplate), algo que te tocaría averiguar cómo hacer si te interesa
No concatenes
No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA.
Usa un PreparedStatement y pásale la cadena.
ps=conn.prepareStatement("SELECT* FROM tabla WHERE campo LIKE ?")
y luego le pasas el parámetro conps.setString(1, "C*")
(en JDBC usas asterisco y ya el driver lo sustituirá por un % si eso es lo que usa la base de datos).No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA. No concatenes SQL NUNCA.