0

I'm trying to add a JButton to a JPanel programatically on click. I am able to add it in the panel, but I would like to add the succeeding buttons NOT ON TOP of the button but on the available space not occupied.

addButton.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseClicked(MouseEvent arg0) {
        JButton button = new JButton("Button");
        button.setBounds(50,20, 90,20);
        internalFrame.getContentPane().add(button);
        button.addMouseListener(drag);
        button.addMouseMotionListener(drag);
        repaint();
        System.out.println("Button added.");
    }
});
Reiion
  • 923
  • 3
  • 15
  • 33
  • 2
    Make use of an appropriate layout manager, `GridBagLayout` comes to mind – MadProgrammer Nov 03 '17 at 02:54
  • @MadProgrammer so this can't be done in absolute layout? I want to allow the user to move the button around after its location is set in the available space – Reiion Nov 03 '17 at 02:56
  • Yes, but you're going to have no end of issues, related to font metrics, DPI and hardware rendering differences between systems, that's kind of the point of a layout management system. Instead of setting the bounds to an absolute position, why not use the `MouseEvent` coordinates? Personally, I'd be inclined to investigate make your own layout manager which takes the absolute position and size the components to their base requirements – MadProgrammer Nov 03 '17 at 02:59
  • @MadProgrammer ah. so would it be better/possible if I use the point-click on location using the mouse to set location. I'll try that – Reiion Nov 03 '17 at 03:09
  • So, [this is one concept](https://stackoverflow.com/questions/11819669/absolute-positioning-graphic-jpanel-inside-jframe-blocked-by-blank-sections/11822601#11822601) where a custom layout manager could be used to translate between virtual and real word coordinate space – MadProgrammer Nov 03 '17 at 03:12
  • *"I want to allow the user to move the button around.."* ***.. Why?*** Is this intended to be a 'drag and drop' GUI designer? – Andrew Thompson Nov 03 '17 at 03:51
  • @AndrewThompson Yep exactly like that. It's just for a project to make a simple GUI designer nothing fancy. – Reiion Nov 03 '17 at 03:58
  • Spend your time dong something worth doing. This, is **not worth doing.** To expand on that, there are already a plethora of D'n'D GUI designers available, and unless they use layouts and the user understands *how* to use layouts, they produce fragile, crappy code. – Andrew Thompson Nov 03 '17 at 04:05
  • @AndrewThompson would be glad only if its not a requirement. anyway, being able to add it should be good enough at the moment. – Reiion Nov 03 '17 at 04:06

1 Answers1

0

Here is a demonstration of adding components with a mouse click, as well as basic dragging. Please note the comments:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.MouseInputAdapter;

public class DragDemo extends JFrame {

    private static int NAX_COMP_COUNT = 3;

    public DragDemo() {
        setTitle("Drag Demo");
        setLayout(new GridLayout(1,3));

        //demonstrates adding components to a null layout panel, with a button click
        JPanel panelA = new CustomPanel("Add components,Null layout");
        add(panelA);

        //adds drsg support to the above
        JPanel panelB = new CustomPanel("Add components,Null layout, Drag", true);
        add(panelB);

        //demonstrates adding components to a flow layout panel, with a button click
        //you can add drag support, but components will be auto-layout when repainted
        JPanel panelC = new CustomPanel("Add components, Flow layout", new FlowLayout());
        add(panelC);

        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String[] args) {    new DragDemo(); }

    private class CustomPanel extends JPanel {

        private final BevelBorder border =  new BevelBorder(BevelBorder.RAISED);
        private final int W =250, H = 200, GAP = 5;
        private int originX =10, originY = 10;
        private int compCounter = 0;
        private JPanel centerPane ;
        private LayoutManager layoutManager;
        private boolean isDragSupport = false;

        CustomPanel(String title) { this(title, null, false); }

        CustomPanel(String title, boolean isDragSupport ) {
            this(title,null, isDragSupport);
        }

        CustomPanel(String title, LayoutManager layoutManager) {
            this(title,layoutManager, false);
        }

        CustomPanel(String title, LayoutManager layoutManager, boolean isDragSupport) {

            this.layoutManager = layoutManager;
            this.isDragSupport = isDragSupport;
            TitledBorder tBorder = new TitledBorder(border, title);
            setBorder(tBorder);
            setLayout(new BorderLayout(GAP,GAP));
            JButton button = new JButton("Add Label");
            button.addActionListener( e-> addComponenet());
            add(button, BorderLayout.SOUTH);
            centerPane = new JPanel();
            centerPane.setPreferredSize(new Dimension(W, H));
            centerPane.setLayout(layoutManager);
            add(centerPane, BorderLayout.CENTER);
        }

        private void addComponenet() {
            if( ++ compCounter <= NAX_COMP_COUNT) {
                centerPane.add(getComponent());
                centerPane.getParent().revalidate();
                centerPane.repaint();
            }
        }

        private Component getComponent() {
            JLabel label = new JLabel(""+ compCounter, SwingConstants.CENTER);
            label.setBorder(border);
            if(isDragSupport) {
                DragListener drag = new DragListener();
                label.addMouseListener( drag );
                label.addMouseMotionListener( drag );
            }

            if(layoutManager == null) {//if no layout manger set bounds
                label.setBounds(originX, originY, W/5, H/5);
                originX +=W/5; originY += H/5; //update origin of next component
            }else {
                label.setPreferredSize(new Dimension(W/5, H/5));
            }
            return label;
        }
    }

    //source: https://tips4java.wordpress.com/2009/06/14/moving-windows/
    private class DragListener extends MouseInputAdapter    {

        Point location;
        MouseEvent pressed;

        @Override
        public void mousePressed(MouseEvent me) { pressed = me;  }

        @Override
        public void mouseDragged(MouseEvent me)    {
            Component component = me.getComponent();
            location = component.getLocation(location);
            int x = (location.x - pressed.getX()) + me.getX();
            int y = (location.y - pressed.getY()) + me.getY();
            component.setLocation(x, y);
         }
    }
}

For more control and auto-layout you may want to consider DragLayout.
Feel free to ask for any clarifications needed.

c0der
  • 18,467
  • 6
  • 33
  • 65