java java删除一个组件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7167282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 18:56:08  来源:igfitidea点击:

java delete a component

javaswing

提问by bili

Current I can add a bunch of customed component objects to the JPanel by pressing "add" JButton. I also got a "delete" JButton which I wish to do the opposite of "add".

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

My intention is that I can select a component with a mouse and click the delete button and pressto!, the component is gone.

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

I hook a MouseListener to the panel, and use MouseEvent, e.getComponent() to get w/e current component the mouse clicks on. So if it returns a custom component then a variable "private myComponent current" (already set to null) will point to that component. Then I can just click on "delete" button to remove it. An actionListener already added in "delete" button and in the body it calls this.remove(current) (if current is not null).

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

However, this doesn't work as I can't remove a component! Any pointer?

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

If there is an elegant way to managing add/remove components please suggest!

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

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);
}

} Doh!

哦!

Now, in the addResizer() method. Every time I press the add button to add a new Resizable object, what'd happen to the previously added objects? I'm certain that they become null because resizer variable no longer referring to it them??? Even if this is the case, they are still displayed on the panel...And if I pressed delete only the newly added Resizable object gets removed. So am I on the right track here?

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

Edit: to sum up my problem, I hooked the MouseListener to wrong object. It should be Resizable object instead of the panel. Therefore, variable current is always null.

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

回答by mKorbel

it very crazy idea, but everything is possible, but

这是一个非常疯狂的想法,但一切皆有可能,但是

1) in case that you Layed JComponentby using some of LayoutManageryou can remove JComponentsfrom Container, and thenafter you must/have to call revalidate()+ repaint(), but this actions has side effect -> ReLayout Containerand then Container's contents could be look very ***

1) 如果您JComponent通过使用中的一些来放置,则LayoutManager可以JComponents从中删除Container,然后您必须/必须调用revalidate()+ repaint(),但是此操作有副作用 ->ReLayout Container然后容器的内容可能看起来非常***

2) in case that you layed Containerwith AbsoluteLayout, that should be maybe nicest but question is what with emtpy space inside Container

2)如果你ContainerAbsoluteLayout,那应该是最好的,但问题是里面有什么空的空间Container

there is very easy way how to do it, you need to add JPopupMenuto the Container,

有很简单的方法来做,你需要添加JPopupMenuContainer

  • on RightMouseClickyou have to finding JComponentunder the MouseCursor

  • then call Container#remove(myComponent), thenafter you have to call revalidate()+ repaint()for refresh GUI

  • RightMouseClick你寻找JComponentMouseCursor

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

or is same for me

或者对我来说是一样的

回答by Hovercraft Full Of Eels

Your problem is your MouseLisetener. You are listening to the MainDisplayPanel, and so when you click on the JPanel, the MouseEvent#getComponent method returned by, e, in your mousePressed method will return the MainDisplayPanel instance since that is what is being listened to, not the Resizable instance that is under the mouse.

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

Solutions include:

解决方案包括:

  • creating one MouseListener object and adding this same object to each Resizable as a MouseListener for the Resizable, or
  • using your current set up, but hold your Resizable's in an ArrayList and then iterating through the array list in the mousePressed method to see if any Resizable has been clicked by using the componentAt(...)method.
  • 创建一个 MouseListener 对象并将这个相同的对象添加到每个 Resizable 作为 Resizable 的 MouseListener,或
  • 使用您当前的设置,但将您的 Resizable 放在一个 ArrayList 中,然后在 mousePressed 方法中遍历数组列表,以查看是否使用该componentAt(...)方法单击了任何 Resizable 。

Note that I had to create my own SSCCE to solve this. Again in the future, please do us all a favor and do this for us as it really is in your and our best interest, and shows that you respect our time and our help.

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

Edit 1
My 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();
   }

}

回答by antlersoft

I believe the problem is you need to force Swing to layout the components again after removing one. After you remove(current), call revalidate().

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