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

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:

[code]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);
}  

}[/code]
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?

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

Aqui está:

import javax.swing.text.*;

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

	@Override
	public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
		super.insertString(offs, str.replaceAll(INVALID, &quot;&quot;), 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.

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!