Java swing:扩展的jpanel类在重新绘制时不会变亮



我在课程中没有遇到任何问题,但这让我很头疼!我的问题很简单,我不能提亮或改变我的jpanels的颜色。我觉得在我的扩展jpanel类如何与重写的paint组件以及其他类交互方面,我缺少了一些关键的东西。任务很简单,当点击一个jpanel时,它的颜色应该会变亮,而其他两种颜色会变暗。

Run down:我扩展了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 );
   }
 } 

}

您在一个位置更改变量的值,并期望一个完全不同的变量,即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);
   }
}

actionListener中更改的颜色与面板用于绘制自身的颜色之间没有关系。

看看JavaDocs,你会注意到

较暗/较亮

返回:
创建一个较暗/较亮版本的新Color该CCD_ 4。

darker/brighter不会更改Color对象本身,而是创建一个新的Color对象,它是darker/brighter,而不是您使用的颜色

actionListener触发时,您可能应该为每个面板设置所需的颜色。

更好的是,您应该使用某种模型,更改模型会通知面板的每个实例,然后它会通过更新自己来响应。。。

相关内容

  • 没有找到相关文章

最新更新