【问题标题】:Java swing: Extended jpanel class will not brighten upon repainting.Java swing:扩展的 jpanel 类在重绘时不会变亮。
【发布时间】:2014-04-14 12:56:29
【问题描述】:

我已经完成了更复杂的问题,但我的课程没有任何问题,但这让我很适应!我的问题很简单,我不能变亮或改变我的 jpanels 的颜色。我觉得我的扩展 jpanel 类如何与我覆盖的绘制组件以及我的其他类交互时缺少一些关键的东西。任务很简单,当单击一个 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 );
   }
 } 

}

【问题讨论】:

    标签: java swing user-interface mouseevent


    【解决方案1】:

    您在一个位置更改变量的值,并期望完全不同的变量,即 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 会显示新的色调。
    【解决方案2】:

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

    看看JavaDocs你会注意到

    更暗/更亮

    返回:
    创建一个新的Color,它是一个更暗/更亮的版本 这个Color.

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

    您可能应该做的是在actionListener 触发时为每个面板设置您想要的颜色。

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

    【讨论】:

    • 我确实花时间阅读了 java 文档,这就是我对它的渗透。我认为通过调用 repaint 它将再次绘制对象并将我的公共变量更改为新颜色,它将与该颜色变量一起使用。正如气垫船在下面所说,我根本没有真正改变颜色。这对您有帮助。
    • @user2557015 对不​​起我的假设
    猜你喜欢
    • 2011-01-10
    • 2013-04-16
    • 2018-02-25
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多