为什么JTextField.setText(“String”)在DocumentListener中不起作用?

时间:2015-01-08 18:10:56

标签: java swing settext documentlistener

我必须构建一个GUI,它采用4个可着色的形状(MyShape类),它们在开始时会变成灰色。稍后,在GUI底部的三个JTextField上写入RGB值,我将能够设置新颜色,以便绘制我稍后会点击的每张图片。

除了在DocumentListener中我不能使用setText方法或者我将得到IllegalStateException之外,一切都很有效。我想调用该方法以纠正RGB组件的错误值:例如,如果用户写入500,则文本将自动将JTextField设置为255.

以下是完整项目的代码,以便您可以运行它(在代码中我在问题的方法之前注释了该行(我知道它有点长,阅读,谢谢你,如果你能帮助我的话)无论如何!:)):

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.util.Arrays;
import java.util.List;

public class ShapesGUI extends JFrame {
private ShapesPlayGround shapesPlayGround;
private ColorPreview colorPreview;
private RGB rgb;
private List<MyShape> shapeList;

public ShapesGUI() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setLayout(new BorderLayout());
    Container cnt = getContentPane();

    shapesPlayGround = new ShapesPlayGround();
    colorPreview = new ColorPreview();
    rgb = new RGB();

    cnt.add(shapesPlayGround, BorderLayout.CENTER);
    cnt.add(colorPreview, BorderLayout.WEST);
    cnt.add(rgb, BorderLayout.SOUTH);

    pack();
    setVisible(true);

}

public void setShapeList(List<MyShape> shapeList) {this.shapeList = shapeList;}

class ShapesPlayGround extends JPanel {
    MyShape[] shapes;

    public ShapesPlayGround() {
        setPreferredSize(new Dimension(800, 450));
        setBorder(new TitledBorder("Shapes"));

        shapes = new MyShape[4];

        shapes[0] = new MyShape(new Rectangle2D.Double(50, 250, 40, 180));      // Rettangolo, basso sinistra
        shapes[1] = new MyShape(new Rectangle2D.Double(500, 100, 250, 250));    // Quadrato, estrema destra
        shapes[2] = new MyShape(new Ellipse2D.Double(75, 50, 250, 120));        // Ellisse, alto sinistra
        shapes[3] = new MyShape(new Ellipse2D.Double(310, 200, 230, 230));      // Cerchio, destra

        setShapeList(Arrays.asList(shapes));
        addMouseListener(new MyMouseListener());

    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;

        for (MyShape shape : shapes) {
            g2.setPaint(shape.getColor());
            g2.fill(shape.getShape());

            g2.setPaint(Color.black);
            g2.draw(shape.getShape());

        }
    }

    class MyMouseListener extends MouseAdapter {
        @Override
        public void mouseClicked(MouseEvent e) {
            Point p = new Point(e.getX(), e.getY());

            if (shapeList != null) {

                for (MyShape shape : shapes) {
                    if (shape.getShape().contains(p)) {
                        shape.setColor(rgb.getColor());

                    }
                    repaint();

                }
            }
        }
    }
}

class ColorPreview extends JPanel {
    int[] rgbValue = new int[3];
    JPanel panel;
    Shape preview;

    public ColorPreview() {
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        add(new JLabel("      Preview      "));

        panel = new JPanel();
        panel.setBorder(new TitledBorder("Color"));

        add(panel);

    }

    public void setColor(int[] rgbValue) {this.rgbValue = rgbValue;}
    public int[] getColor() {return rgbValue;}

    public void paintColor() {
        Graphics2D g2 = (Graphics2D)getGraphics();

        preview = new Rectangle2D.Double(panel.getX() + 5, panel.getY() + 20, panel.getWidth() - 10, panel.getWidth() - 10);

        g2.setPaint(rgb.getColor());
        g2.fill(preview);

    }
}

class RGB extends JPanel {
    private JPanel[] rgbPanel = new JPanel[3];
    private String[] panelTitles = {"Red", "Green", "Blue"};
    private JTextField[] rgbText = new JTextField[3];
    private JTextField[] partialColor = new JTextField[3];
    private Shape[] rgbShape;
    private int[] rgbValue = new int[3];
    private Color color;

    public RGB() {
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));

        for (int i = 0; i < 3; i++) {
            rgbPanel[i] = new JPanel();
            rgbPanel[i].setLayout(new GridLayout(1, 2));
            rgbPanel[i].setBorder(new TitledBorder(panelTitles[i]));

            rgbText[i] = new JTextField();
            partialColor[i] = new JTextField();

            rgbValue[i] = 0;
            rgbText[i].setText("0");

            rgbText[i].getDocument().addDocumentListener(new TextChanged(i));

            partialColor[i].setBackground(Color.black);
            partialColor[i].setEditable(false);

            rgbPanel[i].add(rgbText[i]);
            rgbPanel[i].add(partialColor[i]);
            add(rgbPanel[i]);

        }

        color = new Color(rgbValue[0], rgbValue[1], rgbValue[2]);

    }

    public int[] getRgbValue() {return rgbValue;}
    public Color getColor() {return color;}

    public void setRgbValue(int[] rgbValue) {this.rgbValue = rgbValue;}
    public void setColor(Color color) {this.color = color;}

    class TextChanged implements DocumentListener {
        private int i;

        public TextChanged(int i) {this.i = i;}

        @Override
        public void insertUpdate(DocumentEvent e) {listen(i);}

        @Override
        public void removeUpdate(DocumentEvent e) {listen(i);}

        @Override
        public void changedUpdate(DocumentEvent e) {listen(i);}

        private int fixValue(int value) {return value < 0 ? 0 : (value > 255 ? 255 : value);}
        // HERE'S THE PROBLEM!!!
        private void listen(int i) {
            try {
                rgbValue[i] = fixValue(Integer.parseInt(rgbText[i].getText()));

            } catch (NumberFormatException e) {
                rgbValue[i] = 0;

            }

            color = new Color(rgbValue[0], rgbValue[1], rgbValue[2]);
            rgb.setColor(color);
            colorPreview.paintColor();

            try {
                rgbText[i].setText("" + rgbValue[i]);

            } catch (IllegalStateException e) {
                System.out.println("~Shit, Exception");

            }

            if (i == 0) partialColor[0].setBackground(new Color(rgbValue[0], 0, 0));
            else if (i == 1) partialColor[1].setBackground(new Color(0, rgbValue[1], 0));
            else if (i == 2) partialColor[2].setBackground(new Color(0, 0, rgbValue[2]));

        }
    }
}

public static void main(String args[]) {
    new ShapesGUI();

}

}

1 个答案:

答案 0 :(得分:1)

一种可能的解决方案是将更改包装在Runnable中的文本中,并使用SwingUtilitiles.invokeLater(yourRunnable)将其排在事件线程上,但最好也许.....你之前尝试纠正输入它完全在文本组件中注册。在这种情况下,不要使用DocumentListener,而是使用DocumentFilter。

更好的是 - 使用JSlider或JSpinner

如,

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.EnumMap;
import java.util.Map;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SpinnerEg extends JPanel {
   private Map<RGB, JSlider> sliderMap = new EnumMap<>(RGB.class);
   private JPanel displayPanel = new JPanel();
   private Color displayPanelColor = new Color(0, 0, 0);

   public SpinnerEg() {
      displayPanel.setBackground(displayPanelColor);
      JPanel sliderPanel = new JPanel(new GridLayout(1, 0));
      for (RGB rgb : RGB.values()) {
         createRgbSlider(sliderPanel, rgb);
      }

      displayPanel.setPreferredSize(new Dimension(400, 400));

      setLayout(new BorderLayout());
      add(displayPanel);
      add(sliderPanel, BorderLayout.PAGE_END);
   }

   private void createRgbSlider(JPanel sliderPanel, final RGB rgb) {
      final  JSlider slider = new JSlider(0, 255, 0);
      slider.setMajorTickSpacing(50);
      slider.setPaintLabels(true);
      slider.setPaintTicks(true);
      sliderMap.put(rgb, slider);

      slider.addChangeListener(new ChangeListener() {

         @Override
         public void stateChanged(ChangeEvent e) {
            int red = sliderMap.get(RGB.RED).getValue();
            int green = sliderMap.get(RGB.GREEN).getValue();
            int blue = sliderMap.get(RGB.BLUE).getValue();
            displayPanelColor = new Color(red, green, blue);
            displayPanel.setBackground(displayPanelColor);
         }
      });

      JPanel rgbPanel = new JPanel(new BorderLayout());
      rgbPanel.setBorder(BorderFactory.createTitledBorder(rgb.getName()));
      rgbPanel.add(slider);

      sliderPanel.add(rgbPanel);
   }

   private static void createAndShowGui() {
      SpinnerEg mainPanel = new SpinnerEg();

      JFrame frame = new JFrame("SpinnerEg");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

enum RGB {
   RED("Red", Color.red), GREEN("Green", Color.green), BLUE("Blue", Color.blue);
   private String name;
   private Color color;

   private RGB(String name, Color color) {
      this.name = name;
      this.color = color;
   }

   public String getName() {
      return name;
   }

   public Color getColor() {
      return color;
   }

}