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) 如果您将Container
与AbsoluteLayout
放在一起,那应该是最好的,但问题是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 中,通过编辑器删除另一个组件时,如何通过脚本删除一个组件?