2014-04-14 70 views
1

我的課程沒有問題,我做了很多複雜的問題,但這是給我適合!我的問題很簡單,我無法照亮或改變我的jpanels的顏色。我覺得我失去了一些關鍵的東西,我的擴展jpanel類如何與我的重寫paint組件以及其他類進行交互。任務很簡單,點擊一個jpanel時,顏色應該變亮,而其他兩種顏色變暗。Java swing:擴展jpanel類在重新繪製時不會變亮。

運行:我擴展了Jframe並向它添加了3個面板。我爲每個添加了一個鼠標監聽器。當每個按下時,鼠標監聽器確實工作「確認打印語句」。但它不會更改對象的顏色。我認爲通過在我的TrafficLight類中包含我的鼠標適配器,我可以改變顏色並調用重繪。我用我能想到的所有方式去玩,我的組織是否錯了?

import java.awt.*; 
import javax.swing.*; 
import java.awt.event.*; 


class TrafficLight3 extends JFrame { 

//class variables 
public JPanel red; 
public JPanel yellow; 
public JPanel green; 
public Color r; 
public Color y; 
public Color gr; 

public static void main (String [] args) { 
    TrafficLight3 tl = new TrafficLight3 (); 
} 

// Constructor 
public TrafficLight3() { 

    setTitle("Traffic Light"); 
    setLayout (new GridLayout (3, 1)); 
    setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 

    r = Color.RED; 
    red = new StopLightPanel(100, r); 
    red.setPreferredSize(new Dimension (120, 120)); 
    red.addMouseListener (new MouseClicked()); 
    add(red); 

    y = Color.YELLOW; 
    yellow = new StopLightPanel(100, y); 
    yellow.setPreferredSize(new Dimension (120, 120)); 
    yellow.addMouseListener (new MouseClicked()); 
    add(yellow);   

    gr = Color.GREEN; 
    green = new StopLightPanel(100, gr); 
    green.addMouseListener (new MouseClicked()); 
    green.setPreferredSize(new Dimension (120, 120)); 
    add (green);   

    pack(); 
    setLocationRelativeTo(null); 
    setVisible(true); 
    } 
    class MouseClicked extends MouseAdapter { 
    @Override 
    public void mouseClicked (MouseEvent me) { 
     if (me.getSource().equals(red)) { 
      r = r.brighter(); 
      y = y.darker(); 
      gr = gr.darker(); 
      repaint(); 
     } 
     if (me.getSource().equals(yellow)) { 
      r = r.darker(); 
      y = y.brighter(); 
      gr = gr.darker(); 
      repaint(); 
     } 
     if (me.getSource().equals(red)) { 
      r = r.darker(); 
      y = y.darker(); 
      gr = gr.brighter(); 
      repaint(); 
     } 
    } 
} 

class StopLightPanel extends JPanel { 

    private int diameter; 
    public Color color; 

    public StopLightPanel (int d, Color c) { 

     diameter = d; 
     color = c; 
    } 

    public void paintComponent (Graphics g) { 

     super.paintComponent(g); 
     g.setColor (color); 
     g.fillOval (10, 10, diameter, diameter); 
    } 
} 

}

回答

4

你在一個不斷變化的變量的值位置,並期望一個完全不同的變量,即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); 
    } 
} 
+0

謝謝,這真的很有幫助。我認爲mouseListener可以訪問我的顏色變量,從而能夠改變它們,調用repaint將顯示新的色調。 – Rocky

4

有你在actionListener正在改變顏色,面板使用油漆本身的顏色之間沒有任何關係。

考慮看看JavaDocs你會注意到,

暗/亮

返回:
創建一個新的Color,它是此Color的暗/亮 版本。

darker/brighter不會改變Color對象本身,而是創建一個新的Color對象,它是darker/brighter比您正在使用

你應該做的是設置你想要什麼顏色的顏色當觸發actionListener時,每個面板。

更重要的是,你應該使用某種模式,改變模型會通知面板的每個實例,然後它會通過更新自身迴應...

+0

我確實需要時間閱讀java文檔,那是我的相互滲透。我認爲通過調用重繪它會再次繪製對象,並將我的公共變量更改爲新的顏色,它將與該顏色變量一起使用。正如下面的氣墊船所說,我根本沒有真正改變顏色。這有助於謝謝你。 – Rocky

+0

@ user2557015對不起,我的假設 – MadProgrammer