你在一個不斷變化的變量的值位置,並期望一個完全不同的變量,即JPanel所擁有的變量,以協調一致地變化,但這不是變量的工作原理。
取而代之,我會給我的停車燈面板一個方法,說public void setLightOn(boolean lightOn)
,並會在我的MouseListener中調用此方法。該方法將改變JPanel的顏色並重繪它。
例如:
class StopLightPanel extends JPanel {
private int diameter;
private Color onColor;
private Color offColor;
private boolean lightOn;
public boolean isLightOn() {
return lightOn;
}
public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
repaint();
}
public StopLightPanel(int d, Color c) {
diameter = d;
onColor = c.brighter();
offColor = c.darker().darker();
lightOn = false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color color = lightOn ? onColor : offColor;
g.setColor(color);
g.fillOval(10, 10, diameter, diameter);
}
}
例如,
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
@SuppressWarnings("serial")
class TrafficLight3 extends JFrame {
private static final int DIAMETER = 100;
private static final Color[] COLORS = { Color.red, Color.yellow, Color.green };
private StopLightPanel[] lightPanels = new StopLightPanel[COLORS.length];
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TrafficLight3();
}
});
}
public TrafficLight3() {
setTitle("Traffic Light");
setLayout(new GridLayout(3, 1));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
MouseAdapter mouseClicked = new MouseClicked();
for (int i = 0; i < COLORS.length; i++) {
lightPanels[i] = new StopLightPanel(DIAMETER, COLORS[i]);
lightPanels[i].addMouseListener(mouseClicked);
add(lightPanels[i]);
}
pack();
setLocationRelativeTo(null);
setVisible(true);
}
class MouseClicked extends MouseAdapter {
// better overriding mousePressed not mouseClicked
@Override
public void mousePressed(MouseEvent me) {
// set all lights dark
for (StopLightPanel lightPanel : lightPanels) {
lightPanel.setLightOn(false);
}
// turn only selected light on.
((StopLightPanel) me.getSource()).setLightOn(true);
}
}
class StopLightPanel extends JPanel {
// avoid "magic" numbers
private static final int GAP = 10;
private int diameter;
private Color onColor;
private Color offColor;
private boolean lightOn;
public boolean isLightOn() {
return lightOn;
}
public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
repaint();
}
public StopLightPanel(int diameter, Color color) {
this.diameter = diameter;
this.onColor = color.brighter();
this.offColor = color.darker().darker();
this.lightOn = false;
}
@Override
public Dimension getPreferredSize() {
int prefW = diameter + 2 * GAP;
int prefH = prefW;
return new Dimension(prefW, prefH);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// smooth out the edge of our circle
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Color color = lightOn ? onColor : offColor;
g2.setColor(color);
g2.fillOval(GAP, GAP, diameter, diameter);
}
}
}
有點MCV-指明分數。雖然缺少接口
import java.awt.*;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;
@SuppressWarnings("serial")
class TrafficLight3 {
private static final int DIAMETER = 100;
private static void createAndShowGui() {
StopLightModel model = new StopLightModel();
StopLightView view = new StopLightView(DIAMETER);
new StopLightControl(view, model);
JFrame frame = new JFrame("Traffic Light");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(view.getMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum MyColor {
RED(Color.red, "Red"),
YELLOW(Color.yellow, "Yellow"),
GREEN(Color.green, "Green");
public Color getColor() {
return color;
}
public String getName() {
return name;
}
private MyColor(Color color, String name) {
this.color = color;
this.name = name;
}
private Color color;
private String name;
}
class StopLightModel {
public static final String SELECTED_COLOR = "selected color";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private MyColor selectedColor = null;
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public MyColor getSelectedColor() {
return selectedColor;
}
public void setSelectedColor(MyColor selectedColor) {
MyColor oldValue = this.selectedColor;
MyColor newValue = selectedColor;
this.selectedColor = selectedColor;
pcSupport.firePropertyChange(SELECTED_COLOR, oldValue, newValue);
}
}
class StopLightControl {
private StopLightView view;
private StopLightModel model;
public StopLightControl(final StopLightView view, final StopLightModel model) {
this.view = view;
this.model = model;
view.setStopLightControl(this);
model.addPropertyChangeListener(new ModelListener());
}
public void setSelectedColor(MyColor myColor) {
model.setSelectedColor(myColor);
}
private class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (StopLightModel.SELECTED_COLOR.equals(evt.getPropertyName())) {
MyColor myColor = model.getSelectedColor();
view.setSelectedColor(myColor);
}
}
}
}
class StopLightView {
private JPanel mainPanel = new JPanel(new GridLayout(0, 1));
private StopLightControl control;
private Map<MyColor, StopLightPanel> colorPanelMap = new EnumMap<>(MyColor.class);
public StopLightView(int diameter) {
MouseAdapter mouseClicked = new MouseClicked();
for (MyColor myColor : MyColor.values()) {
StopLightPanel lightPanel = new StopLightPanel(diameter, myColor);
lightPanel.addMouseListener(mouseClicked);
mainPanel.add(lightPanel);
colorPanelMap.put(myColor, lightPanel);
}
}
public void setSelectedColor(MyColor myColor) {
for (MyColor color : MyColor.values()) {
colorPanelMap.get(color).setLightOn(color == myColor);
}
}
public JComponent getMainPanel() {
return mainPanel;
}
public void setStopLightControl(StopLightControl control) {
this.control = control;
}
private class MouseClicked extends MouseAdapter {
@Override
public void mousePressed(MouseEvent mEvt) {
if (control == null) {
return;
}
StopLightPanel panel = (StopLightPanel) mEvt.getSource();
control.setSelectedColor(panel.getMyColor());
}
}
}
@SuppressWarnings("serial")
class StopLightPanel extends JPanel {
// avoid "magic" numbers
private static final int GAP = 10;
private int diameter;
private MyColor myColor;
private Color onColor;
private Color offColor;
private boolean lightOn;
public boolean isLightOn() {
return lightOn;
}
public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
repaint();
}
public StopLightPanel(int diameter, MyColor myColor) {
this.diameter = diameter;
this.myColor = myColor;
this.onColor = myColor.getColor().brighter();
this.offColor = myColor.getColor().darker().darker();
this.lightOn = false;
}
public MyColor getMyColor() {
return myColor;
}
@Override
public Dimension getPreferredSize() {
int prefW = diameter + 2 * GAP;
int prefH = prefW;
return new Dimension(prefW, prefH);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// smooth out the edge of our circle
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Color color = lightOn ? onColor : offColor;
g2.setColor(color);
g2.fillOval(GAP, GAP, diameter, diameter);
}
}
謝謝,這真的很有幫助。我認爲mouseListener可以訪問我的顏色變量,從而能夠改變它們,調用repaint將顯示新的色調。 – Rocky