当前我可以通过按“添加”JButton将一堆自定义组件对象添加到JPanel。我还有一个“删除”JButton,我希望与“添加”相反。
我的意图是我可以用鼠标选择一个组件,然后单击删除按钮和pressto !,组件就消失了。
我将MouseListener挂钩到面板,并使用MouseEvent,e.getComponent()获取鼠标单击的w / e当前组件。因此,如果它返回自定义组件,则变量“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对象而不是面板。因此,可变电流始终为空。
答案 0 :(得分:3)
这是非常疯狂的想法,但一切皆有可能,但
1)如果您使用JComponent
部分LayoutManager
进行了展示,则可以从JComponents
删除Container
,然后您必须/必须致电{{1} } + revalidate()
,但此操作有副作用 - > repaint()
然后Container的内容可能看起来非常ReLayout Container
2)如果您使用***
放置Container
,那应该是最好的但问题是AbsoluteLayout
有很简单的方法,您需要将Container
添加到JPopupMenu
,
Container
上您必须在RightMouseClick
JComponent
然后致电MouseCursor
,之后您必须致电Container#remove(myComponent)
+ revalidate()
进行刷新GUI
或对我来说是一样的
调用repaint()
,没有重新布局,没有重新验证+重绘,JComponent在同一个地方等待(最终)重用
关于如何LayoutManagers add/remove JComponents + revalidate + repaint
答案 1 :(得分:3)
你的问题是你的MouseLisetener。您正在侦听MainDisplayPanel,因此当您单击JPanel时,您在mousePressed方法中返回的MouseEvent#getComponent方法将返回MainDisplayPanel实例,因为这是正在被侦听的内容,而不是Resizable实例。在老鼠的手下。
解决方案包括:
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();
}
}
答案 2 :(得分:2)
我认为问题是您需要强制Swing在删除组件后再次布局组件。删除(当前)后,调用revalidate()。