Using DocumentFilter iteratively - java

I am trying to run this code:
How to change the color of specific words in a JTextPane?
private final class CustomDocumentFilter extends DocumentFilter
{
private final StyledDocument styledDocument = yourTextPane.getStyledDocument();
private final StyleContext styleContext = StyleContext.getDefaultStyleContext();
private final AttributeSet greenAttributeSet = styleContext.addAttribute(styleContext.getEmptySet(), StyleConstants.Foreground, Color.GREEN);
private final AttributeSet blackAttributeSet = styleContext.addAttribute(styleContext.getEmptySet(), StyleConstants.Foreground, Color.BLACK);
// Use a regular expression to find the words you are looking for
Pattern pattern = buildPattern();
#Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributeSet) throws BadLocationException {
super.insertString(fb, offset, text, attributeSet);
handleTextChanged();
}
#Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
super.remove(fb, offset, length);
handleTextChanged();
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attributeSet) throws BadLocationException {
super.replace(fb, offset, length, text, attributeSet);
handleTextChanged();
}
/**
* Runs your updates later, not during the event notification.
*/
private void handleTextChanged()
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
updateTextStyles();
}
});
}
/**
* Build the regular expression that looks for the whole word of each word that you wish to find. The "\\b" is the beginning or end of a word boundary. The "|" is a regex "or" operator.
* #return
*/
private Pattern buildPattern()
{
StringBuilder sb = new StringBuilder();
for (String token : ALL_WORDS_THAT_YOU_WANT_TO_FIND) {
sb.append("\\b"); // Start of word boundary
sb.append(token);
sb.append("\\b|"); // End of word boundary and an or for the next word
}
if (sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1); // Remove the trailing "|"
}
Pattern p = Pattern.compile(sb.toString());
return p;
}
private void updateTextStyles()
{
// Clear existing styles
styledDocument.setCharacterAttributes(0, yourTextPane.getText().length(), blackAttributeSet, true);
// Look for tokens and highlight them
Matcher matcher = pattern.matcher(yourTextPane.getText());
while (matcher.find()) {
// Change the color of recognized tokens
styledDocument.setCharacterAttributes(matcher.start(), matcher.end() - matcher.start(), greenAttributeSet, false);
}
}
}
And
((AbstractDocument) yourTextPane.getDocument()).setDocumentFilter(new CustomDocumentFilter());
I would like to use it iteratively, that is, that any new string ALL_WORDS_THAT_YOU_WANT_TO_FIND will be automatically colored. I thought of deleting
styledDocument.setCharacterAttributes(0, yourTextPane.getText().length(), blackAttributeSet, true);
(that is, to not destroy the previous colored words) but it does not work: it only keeps colored the input words given at the last iteration. How could I do that?

Edit: updated after two questions in the comments
So you want to add words to the list and update the JTextPane? In that case you would want to make sure that the list gets updated and used each time the updateTextStyles method runs.
You can use multiple lists of words that can apply unique formatting to the text. The code that you started with uses a regular expression, which you could expand to multiple regular expressions. You can also search for exact case sensitive matches of sub strings (or text fragments) without looking at word boundaries, as is used in the code below.
This means that the formatting of some text might be changed multiple times by matches from different groups. The order in which you search will determine the end result. For example, this small example allows you to fill a text pane and add new words to three highlight groups (with colors red, orange, and blue):
Here is the code of the three classes in the example (using Java 8):
IterativeDocumentFilter.java:
import java.awt.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.text.*;
public class IterativeDocumentFilter {
public static void main(String[] arguments) {
SwingUtilities.invokeLater(
() -> new IterativeDocumentFilter().createAndShowGui()
);
}
private void createAndShowGui() {
JFrame frame = new JFrame("Stack Overflow");
frame.setBounds(100, 100, 1000, 600);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel(new BorderLayout());
JTextPane textPane = new JTextPane(new DefaultStyledDocument());
CustomDocumentFilter documentFilter = new CustomDocumentFilter(textPane);
textPane.setBorder(new LineBorder(Color.BLACK, 1));
enlargeFont(textPane);
mainPanel.add(textPane, BorderLayout.CENTER);
mainPanel.add(createBottomPanels(documentFilter), BorderLayout.PAGE_END);
frame.getContentPane().add(mainPanel);
frame.setVisible(true);
}
private JPanel createBottomPanels(CustomDocumentFilter documentFilter) {
JPanel bottomPanels = new JPanel();
bottomPanels.setLayout(new BoxLayout(bottomPanels, BoxLayout.PAGE_AXIS));
for (HighlightGroup highlightGroup : documentFilter.getHighlightGroups()) {
List<String> textFragments = highlightGroup.getTextFragments();
JPanel groupPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
JLabel textFragmentsLabel = new JLabel("Current text fragments: "
+ textFragments);
textFragmentsLabel.setForeground(highlightGroup.getColor());
JLabel addTextFragmentLabel = new JLabel("Additional text fragment:");
addTextFragmentLabel.setForeground(highlightGroup.getColor());
JTextField addTextFragmentTextField = new JTextField(28);
JButton addTextFragmentButton = new JButton("Add text fragment");
addTextFragmentButton.setForeground(highlightGroup.getColor());
addTextFragmentButton.addActionListener(actionEvent -> {
String newTextFragment = addTextFragmentTextField.getText().trim();
if (!textFragments.contains(newTextFragment)) {
textFragments.add(newTextFragment);
documentFilter.handleTextChanged();
textFragmentsLabel.setText("Current text fragments: "
+ textFragments);
}
addTextFragmentTextField.setText("");
});
groupPanel.add(addTextFragmentLabel);
groupPanel.add(addTextFragmentTextField);
groupPanel.add(addTextFragmentButton);
textFragmentsLabel.setBorder(new EmptyBorder(0, 42, 0, 0));
groupPanel.add(textFragmentsLabel);
enlargeFont(addTextFragmentLabel);
enlargeFont(addTextFragmentTextField);
enlargeFont(addTextFragmentButton);
enlargeFont(textFragmentsLabel);
bottomPanels.add(groupPanel);
}
return bottomPanels;
}
private void enlargeFont(Component component) {
component.setFont(component.getFont().deriveFont(16f));
}
}
CustomDocumentFilter.java:
import java.awt.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.text.*;
public class CustomDocumentFilter extends DocumentFilter
{
private final JTextPane textPane;
private final List<HighlightGroup> highlightGroups;
private final StyleContext styleContext = StyleContext.getDefaultStyleContext();
private final AttributeSet blackAttributeSet
= styleContext.addAttribute(styleContext.getEmptySet(),
StyleConstants.Foreground, Color.BLACK);
public CustomDocumentFilter(JTextPane textPane) {
this.textPane = textPane;
highlightGroups = createHighlightGroups();
((AbstractDocument) textPane.getDocument()).setDocumentFilter(this);
}
private List<HighlightGroup> createHighlightGroups() {
List<HighlightGroup> groups = new ArrayList<>();
groups.add(new HighlightGroup(Arrays.asList("one", "two", "three"), Color.RED));
groups.add(new HighlightGroup(Arrays.asList("a", "the"), Color.ORANGE));
groups.add(new HighlightGroup(Arrays.asList("th", "o"), Color.BLUE));
return groups;
}
public List<HighlightGroup> getHighlightGroups() {
return highlightGroups;
}
#Override
public void insertString(FilterBypass fb, int offset, String text,
AttributeSet attributeSet) throws BadLocationException {
super.insertString(fb, offset, text, attributeSet);
handleTextChanged();
}
#Override
public void remove(FilterBypass fb, int offset, int length)
throws BadLocationException {
super.remove(fb, offset, length);
handleTextChanged();
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attributeSet) throws BadLocationException {
super.replace(fb, offset, length, text, attributeSet);
handleTextChanged();
}
/**
* Runs your updates later, not during the event notification.
*/
public void handleTextChanged()
{
SwingUtilities.invokeLater(this::updateTextStyles);
}
private void updateTextStyles()
{
// Reset the existing styles by using the default black style for all text.
StyledDocument document = textPane.getStyledDocument();
document.setCharacterAttributes(0, textPane.getText().length(),
blackAttributeSet, true);
// Apply styling for the different groups (the order of the groups is relevant).
for (HighlightGroup highlightGroup : highlightGroups) {
highlightGroup.highlightWords(textPane);
}
}
}
HighlightGroup.java:
import java.awt.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.text.*;
public class HighlightGroup {
private final List<String> textFragments;
private final Color color;
private final AttributeSet attributeSet;
public HighlightGroup(List<String> textFragments, Color color) {
this.textFragments = new ArrayList<>(textFragments);
this.color = color;
StyleContext styleContext = StyleContext.getDefaultStyleContext();
this.attributeSet = styleContext.addAttribute(styleContext.getEmptySet(),
StyleConstants.Foreground,
color);
}
public List<String> getTextFragments() {
return textFragments;
}
public Color getColor() {
return color;
}
public void highlightWords(JTextPane textPane) {
String text = textPane.getText();
StyledDocument styledDocument = textPane.getStyledDocument();
for (String textFragment : textFragments) {
int fromIndex = 0;
int startIndex = text.indexOf(textFragment, fromIndex);
while (startIndex != -1) {
// Change the color of recognized text fragments.
styledDocument.setCharacterAttributes(startIndex, textFragment.length(),
attributeSet, false);
fromIndex = startIndex + textFragment.length();
startIndex = text.indexOf(textFragment, fromIndex);
}
}
}
}

Related

JTextField set input limit

Hi I am trying to use setDocument method to limit the number of characters a user can input in the text field. But somehow it does not limit the no of input characters. Here's the code
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
public class JTextFieldCharLimit extends PlainDocument {
private int limit;
public JTextFieldCharLimit(int limit)
{
super();
this.limit = limit;
}
public void inserString(int offset, String str, AttributeSet set) throws BadLocationException
{
if(str == null)
{
return;
} else if((getLength() + str.length()) <= limit)
{
str = str.toUpperCase();
super.insertString(offset, str, set);
}
}
}
I am using this class in another class where I have declared my text field as follows:
void playerInfoScreen(JFrame mainFrame, JPanel menuPanel)
{
final ScreenConstructor playerName = new ScreenConstructor();
final JFrame frame = mainFrame;
final JPanel returnPanel = menuPanel;
final JPanel panel = playerName.createPanel("menu panel");
final JButton returnButton = playerName.createButton("MAIN MENU");
final JTextField textEntry = playerName.createTextField(10);
// text field length needs to be set to prevent long texts
final JLabel label = playerName.createLabel("Enter Player Name:");
playerName.addButtonToPanel(panel, returnButton);
playerName.addLabelToPanel(panel, label);
playerName.addJTextFieldToPanel(panel, textEntry);
textEntry.setDocument(new JTextFieldCharLimit(5));
playerName.displayScreen(frame, panel);
// check for esc button to let user return back to main menu
textEntry.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String player = textEntry.getText(); // save entered player name
storedPlayerName = player; // store player in order to use it in highscores and display on game screen
GameScreen game = new GameScreen(frame, panel); // go to game screen
}
});
returnButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
frame.setContentPane(returnPanel); // go back to previous panel
}
});
}
Use a DocumentFilter. See Implementing a Document Filter and DocumentFilter Examples for more details.
public class SizeFilter extends DocumentFilter {
private int maxCharacters;
public SizeFilter(int maxChars) {
maxCharacters = maxChars;
}
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
throws BadLocationException {
if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)
super.insertString(fb, offs, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
throws BadLocationException {
if ((fb.getDocument().getLength() + str.length()
- length) <= maxCharacters)
super.replace(fb, offs, length, str, a);
else
Toolkit.getDefaultToolkit().beep();
}
}
Credit to MDP
((AbstractDocument)textEntry.getDocument()).setDocumentFilter(new SizeFilter(5));

How to make Jtable cell character length

I want to make my j table column to limit character like allowed only 16 character.I tried various methods nothing works.can anybody helps me?.
Here's what I did
The Call:
JTable table = new JTable();
JTextField textField = new JTextField();
limitCharacters(jtf, 16);
table.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(jtf));
The limitCharacters Method:
private void limitCharacters(JTextField textField, final int limit) {
PlainDocument document = (PlainDocument) textField.getDocument();
document.setDocumentFilter(new DocumentFilter() {
#Override
public void replace(DocumentFilter.FilterBypass fb, int offset,
int length, String text, AttributeSet attrs)
throws BadLocationException {
String string = fb.getDocument().getText(0,
fb.getDocument().getLength())
+ text;
if (string.length() <= limit)
super.replace(fb, offset, length, text, attrs);
}
});
}
An answer found here https://community.oracle.com/thread/1482301
"Custom Cell Editors
http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#validtext
and a custom document on a JTextField
One example worth thousand words"
import java.awt.*;
import javax.swing.*;
public class Test2 extends JFrame {
public Test2() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = getContentPane();
String[] head = {"One","Two","Three"};
String[][] data = {{"R1-C1", "12345678", "R1-C3"},
{"R2-C1", "R2-C2", "R2-C3"},
{"R3-C1", "R3-C2", "R3-C3"}};
JTable jt = new JTable(data, head);
content.add(new JScrollPane(jt), BorderLayout.CENTER);
JTextField jtf = new JTextField();
jtf.setDocument(new LimitedPlainDocument(10));
jt.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(jtf));
setSize(300,300);
}
public static void main(String[] args) { new Test2().setVisible(true); }
}
class LimitedPlainDocument extends javax.swing.text.PlainDocument {
private int maxLen = -1;
/** Creates a new instance of LimitedPlainDocument */
public LimitedPlainDocument() {}
public LimitedPlainDocument(int maxLen) { this.maxLen = maxLen; }
public void insertString(int param, String str,
javax.swing.text.AttributeSet attributeSet)
throws javax.swing.text.BadLocationException {
if (str != null && maxLen > 0 && this.getLength() + str.length() > maxLen) {
java.awt.Toolkit.getDefaultToolkit().beep();
return;
}
super.insertString(param, str, attributeSet);
}
}

JFormattedTextField for Double still takes characters [duplicate]

This question already has answers here:
Is there any way to accept only numeric values in a JTextField?
(20 answers)
Closed 9 years ago.
I have a JFormattedTextField where the user would input prices, I have this, but if I type a character, it'll let me anyway. I need this text field to only read numbers or , from the keyboard, and ignore if it's a char. How should I change it in order to make it work?
JFormattedTextField formattedTextField = new JFormattedTextField();
formattedTextField.setBounds(25, 330, 56, 20);
contentPanel.add(formattedTextField);
formattedTextField.setValue(new Double(10.0));
You need to set a Formatter:
NumberFormat f = NumberFormat.getNumberInstance();
JFormattedTextField field = new JFormattedTextField(f);
Take a look: Format
and
NumberFormat
Then try this:
PlainDocument doc = new PlainDocument();
doc.setDocumentFilter(new DocumentFilter() {
#Override
public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
throws BadLocationException
{
fb.insertString(off, str.replaceAll("\\D++", ""), attr); // remove non-digits
}
#Override
public void replace(FilterBypass fb, int off, int len, String str, AttributeSet attr)
throws BadLocationException
{
fb.replace(off, len, str.replaceAll("\\D++", ""), attr); // remove non-digits
}
});
JFormattedTextField field = new JFormattedTextField();
field.setDocument(doc);
A JFormattedTextField can be used for many things, it can be also used to filter dates or phone numbers. You will either need to set a NumberFormater to the TextField or you use the DocumentFilter (works with JTextField only too).
Check this code snippet, that's how you allow only digits in JTextField, by using DocumentFilter, as the most effeciive way :
import java.awt.*;
import javax.swing.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;
public class InputInteger
{
private JTextField tField;
private MyDocumentFilter documentFilter;
private void displayGUI()
{
JFrame frame = new JFrame("Input Integer Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setBorder(
BorderFactory.createEmptyBorder(5, 5, 5, 5));
tField = new JTextField(10);
((AbstractDocument)tField.getDocument()).setDocumentFilter(
new MyDocumentFilter());
contentPane.add(tField);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args)
{
Runnable runnable = new Runnable()
{
#Override
public void run()
{
new InputInteger().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
class MyDocumentFilter extends DocumentFilter
{
#Override
public void insertString(DocumentFilter.FilterBypass fp
, int offset, String string, AttributeSet aset)
throws BadLocationException
{
int len = string.length();
boolean isValidInteger = true;
for (int i = 0; i < len; i++)
{
if (!Character.isDigit(string.charAt(i)))
{
isValidInteger = false;
break;
}
}
if (isValidInteger)
super.insertString(fp, offset, string, aset);
else
Toolkit.getDefaultToolkit().beep();
}
#Override
public void replace(DocumentFilter.FilterBypass fp, int offset
, int length, String string, AttributeSet aset)
throws BadLocationException
{
int len = string.length();
boolean isValidInteger = true;
for (int i = 0; i < len; i++)
{
if (!Character.isDigit(string.charAt(i)))
{
isValidInteger = false;
break;
}
}
if (isValidInteger)
super.replace(fp, offset, length, string, aset);
else
Toolkit.getDefaultToolkit().beep();
}
}

JTextField: How to limit the number of characters?

Please have a look at the following code.
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
public class Bean extends JFrame
{
private JTextField field1, field2, field3, field4;
private JLabel text;
private JButton ok, cancel;
private JPanel centerPanel,southPanel, textPanel;
private GridLayout grid;
private FlowLayout flow1, flow2;
public Bean()
{
//Declaring instance Variables
field1 = new JTextField(10);
field2 = new JTextField(5);
field3 = new JTextField(5);
field4 = new JTextField(5);
text = new JLabel("Insert Your Numbers Here");
AbstractDocument d = (AbstractDocument) field1.getDocument();
d.setDocumentFilter(new Bean.Field1Listener());
ok = new JButton("OK");
cancel = new JButton("Cancel");
/***********************Creating the main view*************************/
centerPanel = new JPanel();
grid = new GridLayout(2,1,1,1);
//Adding TextFields
textPanel = new JPanel();
flow1 = new FlowLayout(FlowLayout.CENTER);
textPanel.setLayout(flow1);
textPanel.add(field1);
//Adding Buttons
southPanel = new JPanel();
southPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
southPanel.add(ok);
southPanel.add(cancel);
//Creating Center View
centerPanel.setLayout(grid);
centerPanel.add(text);
centerPanel.add(textPanel);
//Gathering everything together
getContentPane().add(centerPanel,"Center");
getContentPane().add(southPanel,"South");
this.setSize(500,200);
this.validate();
this.setVisible(true);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private class Field1Listener extends DocumentFilter
{
#Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException
{
if(fb.getDocument().getLength()+string.length()>5)
{
return;
}
fb.insertString(offset, string, attr);
}
#Override
public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException
{
fb.insertString(offset, "", null);
}
#Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs)throws BadLocationException
{
if(fb.getDocument().getLength()+text.length()>5)
{
System.out.println("OK");
return;
}
fb.insertString(offset, text, attrs);
}
}
public static void main(String[]args)
{
new Bean();
}
}
In here, I am trying to limit the number of character to 5. OK, it stops inserting anymore characters when it reaches 5, but the case is, it also doesn't allow to delete the inserted characters, replace, or anything. How to correct this issue?
simply change your current remove method:
#Override
public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException
{
fb.insertString(offset, "", null);
}
for this one:
#Override
public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException
{
fb.remove(offset, length);
}
it should now work.
You should make your own class that checks whether you gave more input than the maximum allowed length: See an example on http://www.java2s.com/Tutorial/Java/0240__Swing/LimitJTextFieldinputtoamaximumlength.htm.

How to display a temporary baloon tooltip during input validation?

I'm somewhat used to the GUI idiom where when I type something wrong in a text input field a balloon pops up from the field with info about what I got wrong / expected input. It remains visible until I type again.
But now I couldn't find any example to point to.
Given a JTextfield do you know of any library/code that would display such a balloon when triggered by my keylistener?
#see http://www.javapractices.com/topic/TopicAction.do?Id=151
Balloon Tip is a library that does that:
balloonTip = new BalloonTip(f, "Tooltip msg");
That was all needed! If you insist on a having it be a tooltip too:
tooltipBalloon = new BalloonTip(someComponent, "I'm a balloon tooltip!");
// Now convert this balloon tip to a tooltip, such that the tooltip shows up after 500 milliseconds and stays visible for 3000 milliseconds
ToolTipUtils.balloonToToolTip(tooltipBalloon, 500, 3000);
The link given by James Poulson probably provides a better solution, but I had to see if this were possible with some simple Java code using a DocumentFilter and a JWindow. Here's one possible way to do this:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Window;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
public class InfoBalloon extends JPanel {
private static final int PREF_WIDTH = 400;
private static final int PREF_HEIGHT = 300;
private static final String REGEX_TEST = "\\d*";
private static final String ERROR_TEXT = "Please only add numbers to the text field";
private JTextField textField = new JTextField(10);
private JWindow errorWindow;
public InfoBalloon() {
add(new JLabel("Please Enter Number"));
add(textField);
((PlainDocument)textField.getDocument()).setDocumentFilter(new MyNumberDocFilter());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_WIDTH, PREF_HEIGHT);
}
private void showErrorWin() {
if (errorWindow == null) {
JLabel errorLabel = new JLabel(ERROR_TEXT);
Window topLevelWin = SwingUtilities.getWindowAncestor(this);
errorWindow = new JWindow(topLevelWin);
JPanel contentPane = (JPanel) errorWindow.getContentPane();
contentPane.add(errorLabel);
contentPane.setBackground(Color.white);
contentPane.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
errorWindow.pack();
}
Point loc = textField.getLocationOnScreen();
errorWindow.setLocation(loc.x + 20, loc.y + 30);
errorWindow.setVisible(true);
}
private boolean textOK(String text) {
if (text.matches(REGEX_TEST)) {
return true;
}
return false;
}
private class MyNumberDocFilter extends DocumentFilter {
#Override
public void insertString(FilterBypass fb, int offset, String string,
AttributeSet attr) throws BadLocationException {
if (textOK(string)) {
super.insertString(fb, offset, string, attr);
if (errorWindow != null && errorWindow.isVisible()) {
errorWindow.setVisible(false);
}
} else {
showErrorWin();
}
}
#Override
public void replace(FilterBypass fb, int offset, int length, String text,
AttributeSet attrs) throws BadLocationException {
if (textOK(text)) {
super.replace(fb, offset, length, text, attrs);
if (errorWindow != null && errorWindow.isVisible()) {
errorWindow.setVisible(false);
}
} else {
showErrorWin();
}
}
#Override
public void remove(FilterBypass fb, int offset, int length)
throws BadLocationException {
super.remove(fb, offset, length);
if (errorWindow != null && errorWindow.isVisible()) {
errorWindow.setVisible(false);
}
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Info Balloon");
frame.getContentPane().add(new InfoBalloon());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Constructive or destructive criticism is most welcome!

Categories