java删除一个组件

Posted

技术标签:

【中文标题】java删除一个组件【英文标题】:java delete a component 【发布时间】: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 对象而不是面板。因此,可变电流始终为空。

【问题讨论】:

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

或者对我来说是一样的

调用myComponent.setVisible(false),不重新布局,不重新验证+重新绘制,JComponent 在同一个地方等待(最终)重用

关于如何LayoutManagers add/remove JComponents + revalidate + repaint的优秀主题

【讨论】:

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

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

【讨论】:

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

以上是关于java删除一个组件的主要内容,如果未能解决你的问题,请参考以下文章

SAP中怎么删除BOM组件中的其中一个组件,点删除显示已被分配给任务清单删除不了怎么办?

在 Unity 中,通过编辑器删除另一个组件时,如何通过脚本删除一个组件?

如何在 p:tabView 组件中动态添加和删除选项卡

Java并发编程- J.U.C组件拓展

《我的世界》游戏组件冲突或游戏路径配置异常,导致无法启动游戏怎么办?

从角度 2 中的历史记录中删除一个组件