【问题标题】:java delete a componentjava删除一个组件
【发布时间】:2011-11-02 07:05:46
【问题描述】:

当前我可以通过按“添加”JButton 将一堆自定义组件对象添加到 JPanel。我还有一个“删除”JButton,我希望与“添加”相反。

我的意图是我可以用鼠标选择一个组件,然后单击删除按钮并按下!,该组件就消失了。

我将 MouseListener 连接到面板,并使用 MouseEvent,e.getComponent() 来获取鼠标单击的当前组件。因此,如果它返回一个自定义组件,那么一个变量“private myComponent current”(已经设置为 null)将指向该组件。然后我可以单击“删除”按钮将其删除。已在“删除”按钮中添加了一个 actionListener,并在主体中调用 this.remove(current)(如果 current 不为 null)。

但是,这不起作用,因为我无法删除组件!有指针吗?

如果有管理添加/删除组件的优雅方法,请提出建议!

public class MainDisplayPanel extends JPanel implements ActionListener, MouseListener{

private JButton newClassButton;
private JButton deleteButton;
private Resizable current;
private Resizable resizer;
public MainDisplayPanel(LayoutManager layout) {
    super(layout);

    newClassButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
            addResizer();
     }          
    });

    deleteButton = new JButton("Delete");
    deleteButton.addActionListener(this);
    this.addMouseListener(this);
    this.add(newClassButton);
    this.add(deleteButton);

}
public void addResizer() {
    //JPanel panel = new JPanel();
    //panel.setBackground(Color.white);
     resizer = new Resizable( new ClassBox());
    this.add(resizer);
    this.revalidate();
    this.repaint();
}

public void actionPerformed(ActionEvent e) {
          if(current!=null)
          {
              this.remove(current);
              this.revalidate();
              this.repaint();

          }
}

public void mouseClicked(MouseEvent e) {
    System.out.println(e);
            Component component = e.getComponent();

            if(component instanceof Resizable)
                current= (Resizable) e.getComponent();

}


    public static void main(String[] args) {
    JFrame jframe = new JFrame();
    jframe.add(new MainDisplayPanel(null));
    jframe.setSize(new Dimension(600,400));
    jframe.setVisible(true);
    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

} 呵呵!

现在,在 addResizer() 方法中。每次我按下添加按钮添加一个新的 Resizable 对象时,之前添加的对象会发生什么?我确定它们变为 null 因为 resizer 变量不再引用它们???即使是这种情况,它们仍然显示在面板上......如果我按下删除,只有新添加的 Resizable 对象会被删除。那么我是不是在正确的轨道上?

编辑:总结一下我的问题,我将 MouseListener 挂到了错误的对象上。它应该是 Resizable 对象而不是面板。因此,可变电流始终为空。

【问题讨论】:

  • 如果没有您的一些代码,很难说出确切的问题,但我的猜测是某种范围问题(尤其是对于任何匿名听众)。否则,我想这大概也是我会尝试的……
  • 是的,我使用匿名监听器。也添加了一些代码。

标签: java swing


【解决方案1】:

你的问题是你的 MouseLisetener。您正在收听 MainDisplayPanel,因此当您单击 JPanel 时,mousePressed 方法中返回的 MouseEvent#getComponent 方法将返回 MainDisplayPanel 实例,因为这是正在收听的内容,而不是 Resizable 实例在鼠标下方。

解决方案包括:

  • 创建一个 MouseListener 对象并将这个相同的对象添加到每个 Resizable 作为 Resizable 的 MouseListener,或者
  • 使用当前设置,但将 Resizable 保存在 ArrayList 中,然后在 mousePressed 方法中遍历数组列表,以查看是否使用 componentAt(...) 方法单击了任何 Resizable。

请注意,我必须创建自己的 SSCCE 来解决这个问题。以后再一次,请帮我们大家一个忙,为我们做这件事,因为这确实符合您和我们的最大利益,并表明您尊重我们的时间和我们的帮助。

编辑 1
我的SSCCE:

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.*;

@SuppressWarnings("serial")
public class MainDisplayPanel extends JPanel {
   private static final int RESIZABLE_COUNT = 40;
   private JButton deleteButton;
   private Resizable current;
   private Resizable resizer;
   private List<Resizable> resizableList = new ArrayList<Resizable>();

   public MainDisplayPanel(LayoutManager layout) {
      super(layout);

      deleteButton = new JButton("Delete");
      deleteButton.addActionListener(new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            deleteButtonActionPerformed(e);
         }
      });
      this.addMouseListener(new MyMouseAdapter());
      this.add(deleteButton);

      for (int i = 0; i < RESIZABLE_COUNT; i++) {
         addResizer();
      }
   }

   private void deleteButtonActionPerformed(ActionEvent e) {
      if (current != null) {
         this.remove(current);
         resizableList.remove(current);
         current = null;
         this.revalidate();
         this.repaint();
      }
   }

   public void addResizer() {
      resizer = new Resizable();
      this.add(resizer);
      resizableList.add(resizer);
      this.revalidate();
      this.repaint();
   }

   private class MyMouseAdapter extends MouseAdapter {

      @Override
      public void mousePressed(MouseEvent e) {
         current = null;
         Component c = getComponentAt(e.getPoint());
         for (Resizable resizable : resizableList) {
            if (resizable == c) {
               current = resizable;
               resizable.setFill(true);
            } else {
               resizable.setFill(false);
            }
         }
      }
   }

   public static void main(String[] args) {
      JFrame jframe = new JFrame();
      // !! jframe.add(new MainDisplayPanel(null));
      jframe.add(new MainDisplayPanel(new FlowLayout()));
      jframe.setSize(new Dimension(600, 400));
      jframe.setVisible(true);
      jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }

}

@SuppressWarnings("serial")
class Resizable extends JPanel {

   private static final int RESIZE_WIDTH = 50;
   private static final int RESIZE_HEIGHT = 40;
   private static final int THICKNESS = 5;
   private static final Color FILL_COLOR = Color.pink;

   public Resizable() {
      Random rand = new Random();

      // different color border so we can see that it was the clicked one that was deleted.
      Color color = new Color(
               rand.nextInt(255), 
               rand.nextInt(255), 
               rand.nextInt(255));
      setBorder(BorderFactory.createLineBorder(color, THICKNESS));
   }

   @Override // so we can see it
   public Dimension getPreferredSize() {
      return new Dimension(RESIZE_WIDTH, RESIZE_HEIGHT);
   }

   public void setFill(boolean fill) {
      Color fillColor = fill ? FILL_COLOR : null;
      setBackground(fillColor);
      repaint();
   }

}

【讨论】:

  • 谢谢气垫船!我在 addResizer() 中为 resizer 变量添加了一个 MouseListener,所以每次单击鼠标时,它都会将 current 设置为 resizer 并且它可以工作!我没有发布EECS的原因是我承认我很懒惰。但原因是我没有考虑将 Resizer 缩减为单个 JPanel 类。发生的情况是 Resizer 构造函数接受一个对象,而该对象包含其他对象,这些对象又接受另一个对象,其中包含一组带有 ActionListener 和 MouseListener 的自定义组件。有些代码使用了FactoryMethod,所以整个代码很长。
  • 我知道这个问题非常微妙,我需要提前发布 EECS。在我看到你之前提到的错误的帖子后,我更仔细地查看了代码,但显然我无法发现监听器问题,因为我一开始就没有想到我将监听器连接到错误的对象。我正式注意到发布 EECS。将来,如果我发布任何代码,我会在发布之前更加努力地考虑减少代码。我很感谢您和其他所有人花费时间和精力来查看和指导我的问题。再次感谢!
【解决方案2】:

这个想法很疯狂,但一切皆有可能,但是

1) 如果您使用 LayoutManager 中的某些 JComponent 铺设了 JComponents,则可以从 Container 中删除 JComponents,然后您必须/必须调用 revalidate() + repaint(),但此操作有副作用 -> ReLayout Container 然后 Container 的内容可能看起来很 ***

2) 如果您将ContainerAbsoluteLayout 放在一起,那应该是最好的,但问题是Container 内的空白空间是什么

有很简单的方法,你需要将JPopupMenu添加到Container

  • RightMouseClick 上,您必须在MouseCursor 下找到JComponent

  • 然后调用Container#remove(myComponent),然后你必须调用revalidate() + repaint()刷新GUI

或者对我来说是一样的

【讨论】:

  • bigPane 包含 2 个其他 JPanel,mainDisplayPane 是其中之一,并使用 null LayoutManager 进行初始化,因为我的自定义组件可以在任何地方拖动和调整大小。其他窗格仅用于工具栏。我会尝试弹出菜单,看看是否有帮助。
  • @bili then result is here stackoverflow.com/questions/7062154/… @dacwe 关于Component component = SwingUtilities.getDeepestComponentAt(...) 的最后一个代码应该可以解决这个问题
  • 该链接中的代码对我来说看起来很可怕。如果我真的不能用任何其他方式解决这个问题,我会尽量不诉诸它。谢谢!
【解决方案3】:

我认为问题是您需要在移除组件后强制 Swing 重新布局组件。删除(当前)后,调用 revalidate()。

【讨论】:

  • revalidate 然后repaint 后者尤其是在移除组件时。
  • 是的,我确实使用过它们,但问题似乎是一开始就没有任何东西被删除。
  • 那么你有一个错误,可能是一个放错位置的引用——因为你试图删除的 JPanel 不是最初添加的那个,但是谁知道因为我们可以'不要编译或运行你的代码。我建议您创建并发布SSCCE(请单击并查看链接),我们将处于更好的位置,能够为您提供真正的帮助,而不是愚蠢的疯狂@ssed 猜测。
  • @Hovercraft:对不起,我错过了你之前的评论。我想我已经无法解决这个问题了,这对我来说很有趣。请查看我原始帖子中的新编辑。我正在 MainDisplayPanel 上进行测试,因此不涉及其他 JPanel。如果我仍然无法解决这个问题,我将发布一个 SSCCE。谢谢。
  • @bili:这真的不公平。为了让我们帮助您,我们必须获取您的代码并自己制作 SSCCE,因为您出于某种原因不愿意这样做(我不确定为什么,希望不是因为您太懒了)。这样我们就可以运行、测试和修改它。但是您是请求帮助的人,因此您应该是这样做的人,而不是我们。请纠正这种情况。
猜你喜欢
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 2020-12-07
  • 2011-11-05
  • 2022-01-08
  • 1970-01-01
  • 2020-07-04
相关资源
最近更新 更多