简体   繁体   English

为什么我的ItemListener不起作用?

[英]Why my ItemListener doesn't work?

I'm trying to implements ItemListener in JCheckBox. 我正在尝试在JCheckBox中实现ItemListener。 The following code works: 以下代码有效:

public class Test {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel p = new JPanel();
        p.setLayout(new FlowLayout());

        int size = 5;
        JLabel[] labels = new JLabel[size];
        for (int i = 1; i < labels.length; i++) {
            labels[i] = new JLabel();
            labels[i].setText("" + i);
            ;

            labels[i].setPreferredSize(new Dimension(25, 25));
            p.add(labels[i]);
        }

        JCheckBox[] checkBoxs = new JCheckBox[size];
        for (int i = 1; i < checkBoxs.length; i++) {
            checkBoxs[i] = new JCheckBox();
            checkBoxs[i].setSelected(true);
            p.add(checkBoxs[i]);
            checkBoxs[i].addItemListener(new MyItemListener(labels[i]));
        }

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);
        frame.setContentPane(p);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

and the listener class: 和侦听器类:

public class MyItemListener implements ItemListener {

JLabel label = new JLabel();

public MyItemListener(JLabel label) {
    super();
    this.label = label;
}

@Override
public void itemStateChanged(ItemEvent e) {
    if (e.getStateChange() == ItemEvent.SELECTED) {
        label.setVisible(true);
        label.revalidate();
        label.repaint();
    } else {
        label.setVisible(false);
    }
}

} }

But now, I'm trying to do the same things with separate class, but it doesn't work: 但是现在,我正在尝试使用单独的类执行相同的操作,但是它不起作用:

Test.java Test.java

public class Test {
public static void main(String[] args) {
    JFrame frame = new JFrame();
    JPanel p = new JPanel();
    p.setLayout(new FlowLayout());

    PanelOfLabel panelOfLabel = new PanelOfLabel();
    panelOfLabel.setBorder(new LineBorder(Color.red));
    p.add(panelOfLabel);

    PanelOfBoxes panelOfBoxes = new PanelOfBoxes();
    panelOfBoxes.setBorder(new LineBorder(Color.green));
    p.add(panelOfBoxes);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setContentPane(p);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}

} }

PanelOfLabel.java PanelOfLabel.java

public class PanelOfLabel extends JPanel {

private JLabel[] labels = new JLabel[5];

public PanelOfLabel() {
    super();
    createLabels();
}

public void createLabels() {
    for (int i = 1; i < labels.length; i++) {
        labels[i] = new JLabel();
        labels[i].setText("" + i);
        labels[i].setPreferredSize(new Dimension(25, 25));
        this.add(labels[i]);
    }

}

PanelOfBoxes.java PanelOfBoxes.java

public class PanelOfBoxes extends JPanel {

private JCheckBox[] checkBoxs = new JCheckBox[5];
private PanelOfLabel[] PanelOfLabels = new PanelOfLabel[5];

public PanelOfBoxes() {
    super();
    createBoxes();
}

public void createBoxes() {
    for (int i = 1; i < checkBoxs.length; i++) {
        checkBoxs[i] = new JCheckBox();
        checkBoxs[i].setSelected(true);
        this.add(checkBoxs[i]);
        checkBoxs[i].addItemListener(new MyListener(PanelOfLabels[i]));
    }
}

} }

and MyListener.java 和MyListener.java

public class MyListener implements ItemListener {

private PanelOfLabel panelOfLabels;

public MyListener(PanelOfLabel panelOfLabels) {
    super();
    this.panelOfLabels = panelOfLabels;
}

@Override
public void itemStateChanged(ItemEvent e) {
    if (e.getStateChange() == ItemEvent.SELECTED) {
        panelOfLabels.setVisible(true);
        panelOfLabels.revalidate();
        panelOfLabels.repaint();
    } else {
        panelOfLabels.setVisible(false);
    }
}

} }

Where is the mistake that i made ? 我犯的错误在哪里? Can somebody help me please ? 有人可以帮我吗?

This doesn't make sense: 这没有道理:

private PanelOfLabel[] PanelOfLabels = new PanelOfLabel[5];

public PanelOfBoxes() {
    super();
    createBoxes();
}

public void createBoxes() {
    for (int i = 1; i < checkBoxs.length; i++) {
        checkBoxs[i] = new JCheckBox();
        checkBoxs[i].setSelected(true);
        this.add(checkBoxs[i]);
        checkBoxs[i].addItemListener(new MyListener(PanelOfLabels[i]));
    }
}

Since each PanelOfLabels item has not been constructed, each item will be null. 由于尚未构造每个PanelOfLabels项目,因此每个项目都将为null。 You're passing a null reference into your MyListener constructor. 您要将空引用传递到MyListener构造函数中。

And shouldn't you instead be passing in one JLabel into that constructor and not an array of JPanel? 而且,您不应该将一个 JLabel传递给该构造函数而不是一个JPanel数组吗?

eg, 例如,

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.LineBorder;

public class Test {
   public static void main(String[] args) {
      JFrame frame = new JFrame();
      JPanel p = new JPanel();
      p.setLayout(new FlowLayout());

      PanelOfLabel panelOfLabel = new PanelOfLabel();
      panelOfLabel.setBorder(new LineBorder(Color.red));
      p.add(panelOfLabel);

      PanelOfBoxes panelOfBoxes = new PanelOfBoxes(panelOfLabel); //!!
      panelOfBoxes.setBorder(new LineBorder(Color.green));
      p.add(panelOfBoxes);

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(400, 400);
      frame.setContentPane(p);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }
}

class PanelOfLabel extends JPanel {
   private JLabel[] labels = new JLabel[5];

   public PanelOfLabel() {
      super();
      createLabels();
   }

   public void setLabelVisibility(int index, boolean visible) {
      if (index < 0 || index >= labels.length) {
         throw new ArrayIndexOutOfBoundsException(index);
      }

      labels[index].setVisible(visible);
   }

   public void createLabels() {
      for (int i = 1; i < labels.length; i++) {
         labels[i] = new JLabel();
         labels[i].setText("" + i);
         labels[i].setPreferredSize(new Dimension(25, 25));
         this.add(labels[i]);
      }

   }
}

class PanelOfBoxes extends JPanel {

   private JCheckBox[] checkBoxs = new JCheckBox[5];
   // !! private PanelOfLabel[] PanelOfLabels = new PanelOfLabel[5];
   private PanelOfLabel panelOfLabel; //!!

   public PanelOfBoxes(PanelOfLabel panelOfLabel) {
      super();
      this.panelOfLabel = panelOfLabel; //!!
      createBoxes();
   }

   public void createBoxes() {
      for (int i = 1; i < checkBoxs.length; i++) {
         checkBoxs[i] = new JCheckBox();
         checkBoxs[i].setSelected(true);
         this.add(checkBoxs[i]);
         // !!
         checkBoxs[i].addItemListener(new MyListener(i, panelOfLabel)); //!!
      }
   }
}

class MyListener implements ItemListener {

   private PanelOfLabel panelOfLabels;
   private int index;

   // !!
   public MyListener(int index, PanelOfLabel panelOfLabels) {
      super();
      this.index = index; // !!
      this.panelOfLabels = panelOfLabels;
   }

   @Override //!!
   public void itemStateChanged(ItemEvent e) {
      boolean visible = e.getStateChange() == ItemEvent.SELECTED;
      panelOfLabels.setLabelVisibility(index, visible);
      Container parent = panelOfLabels.getParent();
      parent.repaint();
   }
}

Edit 编辑
My attempt at a Model-View-Control (MVC) solution: 我尝试的模型视图控件(MVC)解决方案:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;
import javax.swing.event.*;

public class TestMvc {

   private static final int SIZE = 6;

   private static void createAndShowGui() {
      TestModel model = new TestModel(SIZE);
      TestView view = new TestView();
      new TestControl(model, view);

      JFrame frame = new JFrame("TestMvc");
      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();
         }
      });
   }
}

class TestControl {

   private TestModel model;
   private TestView view;

   public TestControl(final TestModel model, final TestView view) {
      this.model = model;
      this.view = view;
      view.setModel(model);
      TestViewCheckBoxBox checkBoxBox = view.getCheckBoxBox();
      for (int i = 0; i < model.getSize(); i++) {
         checkBoxBox.addCheckBoxItemListener(i, new MyItemListener(i));
      }

      model.addPropertyChangeListener(new ModelPropertyChangeListener());
   }

   private class MyItemListener implements ItemListener {
      private int index;

      public MyItemListener(int index) {
         this.index = index;
      }

      @Override
      public void itemStateChanged(ItemEvent iEvt) {
         model.setValue(index, iEvt.getStateChange() == ItemEvent.SELECTED);
      }
   }

   private class ModelPropertyChangeListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent pcEvt) {
         if (TestModel.VALUE.equals(pcEvt.getPropertyName())) {
            IndexedPropertyChangeEvent ipcEvt = (IndexedPropertyChangeEvent) pcEvt;
            int index = ipcEvt.getIndex();
            boolean visible = (Boolean)ipcEvt.getNewValue();
            view.getLabelBox().setLabelVisible(index, visible);
         }
      }
   }

}

class TestView {
   private JPanel mainPanel = new JPanel();
   private TestModel model;
   private TestViewLabelBox labelBox;
   private TestViewCheckBoxBox checkBoxBox;

   public void setModel(TestModel model) {
      this.model = model;
      mainPanel.setLayout(new GridLayout(1, 0, 5, 0));
      labelBox = new TestViewLabelBox(model.getSize());
      checkBoxBox = new TestViewCheckBoxBox(model.getSize());

      mainPanel.add(labelBox.getMainPanel());
      mainPanel.add(checkBoxBox.getMainPanel());
   }

   public TestViewLabelBox getLabelBox() {
      return labelBox;
   }

   public TestViewCheckBoxBox getCheckBoxBox() {
      return checkBoxBox;
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

}

class TestViewLabelBox {
   private JPanel mainPanel = new JPanel();
   private List<JLabel> labelList = new ArrayList<>();

   public TestViewLabelBox(int count) {
      mainPanel.setBorder(BorderFactory.createLineBorder(Color.black));
      mainPanel.setLayout(new GridLayout(1, 0, 5, 0));
      for (int i = 0; i < count; i++) {
         JLabel label = new JLabel(String.valueOf(i + 1), SwingConstants.CENTER);
         labelList.add(label);
         mainPanel.add(label);
      }
   }

   public void setLabelVisible(int index, boolean visible) {
      if (index < 0 || index >= labelList.size()) {
         throw new ArrayIndexOutOfBoundsException(index);
      }
      String text = visible ? String.valueOf(index + 1) : "";
      labelList.get(index).setText(text);
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

}

class TestViewCheckBoxBox {
   private JPanel mainPanel = new JPanel();
   private List<JCheckBox> checkBoxList = new ArrayList<>();

   public TestViewCheckBoxBox(int count) {
      mainPanel.setBorder(BorderFactory.createLineBorder(Color.black));
      mainPanel.setLayout(new GridLayout(1, 0, 5, 0));
      for (int i = 0; i < count; i++) {
         JCheckBox checkBox = new JCheckBox("", true);
         checkBoxList.add(checkBox);
         mainPanel.add(checkBox);
      }
   }

   public void addCheckBoxItemListener(int index, ItemListener itemListener) {
      if (index < 0 || index >= checkBoxList.size()) {
         throw new ArrayIndexOutOfBoundsException(index);
      }
      checkBoxList.get(index).addItemListener(itemListener);
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }
}

class TestModel {
   public static final String VALUE = "value";
   private List<Boolean> values = new ArrayList<>();
   private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
         this);

   public TestModel(int size) {
      for (int i = 0; i < size; i++) {
         values.add(Boolean.TRUE);
      }
   }

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.addPropertyChangeListener(listener);
   }

   public int getSize() {
      return values.size();
   }

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcSupport.removePropertyChangeListener(listener);
   }

   public boolean getValue(int index) {
      if (index < 0 || index >= values.size()) {
         throw new ArrayIndexOutOfBoundsException(index);
      }
      return values.get(index);
   }

   public void setValue(int index, boolean value) {
      if (index < 0 || index >= values.size()) {
         throw new ArrayIndexOutOfBoundsException(index);
      }
      boolean oldValue = getValue(index);
      boolean newValue = value;
      values.set(index, value);
      pcSupport.fireIndexedPropertyChange(VALUE, index, oldValue, newValue);
   }
}
private PanelOfLabel[] PanelOfLabels = new PanelOfLabel[5];

Here you're creating an array of PanelOfLabel, containing null elements. 在这里,您将创建一个PanelOfLabel数组,其中包含空元素。

checkBoxs[i].addItemListener(new MyListener(PanelOfLabels[i]));

and here you add a listener to your checkboxes, and pass one of the null elements to the listener. 然后在此处将侦听器添加到您的复选框,并将null元素之一传递给侦听器。

First decide what you want to make visible/invisible in your ItemListener. 首先确定要在ItemListener中显示/隐藏的内容。 Is it one of your JLabels, or is it the only PanelOfLabel instance created in the main class? 它是您的JLabel之一,还是在主类中创建的唯一的PanelOfLabel实例? My guess is that it's the labels. 我的猜测是标签。 So the listener should be identical to the one you have in your working example. 因此,侦听器应与工作示例中的侦听器相同。 But you have to make sure that the labels passed to the listener are the ones created and added in PanelOfLabel. 但是您必须确保传递给侦听器的标签是在PanelOfLabel中创建并添加的标签。

Side note: you're confusing yourself, and us, by not respecting the Java naming conventions. 旁注:不遵守Java命名约定会使您和我们感到困惑。 Variables start with a lowercase letter. 变量以小写字母开头。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM