Impedir caracteres especiais inválidos em nomes de arquivos na JTextField usando DocumentFilter

3 respostas
S

Estou desenvolvendo um sistema de caderneta escolar, onde, ao salvar, o usuário digitará o nome do arquivo a ser salvo. Gostaria de, impedir o usuário de digitar um dos caracteres inválidos em nomes de arquivos:

\ / ? : * " > < |

ou até mesmo outros, se houver (não sei, conheço somente estes)...

Já pesquisei no Google e em vários fóruns possibilidades como: JFormattedTextField, PlainDocument, DocumentFilter, KeyListener (o que eu logo descartei, pois é possível copiar e colar), mas a grande maioria, senão 100% dos casos o pessoal pede filtros a-z ou 0-9, o que não me ajuda.

O mais próximo que eu cheguei foi aqui:
public class Filtro extends DocumentFilter{
    @Override  
    public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr)  
    throws BadLocationException {  
        fb.insertString(offset, text.replaceAll("[\\W]", ""), attr);  
    }  

    @Override  
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)  
    throws BadLocationException {  
        fb.replace(offset, length, text.replaceAll("[\\W]", ""), attrs);
    }  
}
Onde o \W permite apenas letras, dígitos e underline. Já é alguma coisa, mas aí impede outros caracteres interessantes pra nomes de arquivos, como traço, ponto e Ç, além do espaço em branco. Tentei colocar a expressão no lugar do \W assim:
fb.replace(offset, length, text.replaceAll("[\\/?:*\"><|]", ""), attrs);
mas não funcionou... ainda continua possível digitar esses caracteres.

Li também sobre expressões regulares, onde o ? e * são operadores... tentei reajustá-los dentro dos colchetes, mas sem sucesso...

Alguém teria alguma ideia interessante?

3 Respostas

H

Opa,

Estive dando uma olhada neste listener aqui, veja se ajuda em algo:

texto = new JTextField("");
texto.getDocument().addDocumentListener(new DocumentListener() {
	public void changedUpdate(DocumentEvent e) {
	}
	public void removeUpdate(DocumentEvent e) {
	}
	public void insertUpdate(DocumentEvent e) {
	}
});

Ele dispara o insertUpdate quando é inserido um caracter no textfield… Talvez você possa adicionar esses replace’s ai neste evento. Tentei ver se achava algum e.cancel() ou algo do tipo, mas quando o evento é disparado, o caracter já está lá, então teria que ser removido, eu imagino… =(

Valeu

V

Aqui está:

import javax.swing.text.*;

public class FileDocument extends PlainDocument {
	private static final long serialVersionUID = 2336333725841515731L;
	private static String INVALID = "[\\\\/?:*\"&gt;&lt;|]";

	@Override
	public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
		super.insertString(offs, str.replaceAll(INVALID, ""), a);
	};
}

Se quiser testá-lo:

import java.awt.BorderLayout;

import javax.swing.*;

public class Teste {
	public static void main(String[] args) {
		JFrame frame = new JFrame();
		frame.setSize(400, 80);
		frame.setLocationRelativeTo(null);
		frame.add(BorderLayout.NORTH, new JLabel("Entre com o nome do arquivo:"));
		frame.add(BorderLayout.SOUTH, new JTextField(new FileDocument(), "", 50));		
		frame.setVisible(true);
	}
}

Sua expressão regular estava errada. Sempre teste sua expressão regular antes de tentar aplicá-la em algum lugar.
O caracter \ em regex é \\ e não \. A expressão regular deve conter o caracter \ para representar o . Mas como para escrever uma única \ em String vc usa \, é necessário usar \\ para inserir duas barras na String da regex. Provavelmente o que ocorria é que a regex tentava interpretar /, que é inválido, e isso impedia que o resto da expressão fosse avaliada.

S

Opa, realmente não tinha segredo… era só a expressão que estava errada. Não sabia o fato de que era necessário duas sequências de duas barras invertidas na regex pra valer só uma. Agora funcionou legal…

Obrigado pessoal!

Criado 31 de dezembro de 2011
Ultima resposta 1 de jan. de 2012
Respostas 3
Participantes 3