我必须构建一个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();
}
}
答案 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;
}
}