2

I have created a setup of buttons using Box.

The problem is there are gaps between all the buttons.

Below is an MCVE version of my code. What I want to achieve is that the buttons "ONE" and "TWO" are touching side by side, with no gap, and buttons "ONE and "ONE" are touching top to bottom with no gap, and for this to continue throughout the setup.

I have read about glue and have tried to use it, but I have not been able to work it out. I am not able to use another layout other than Box as it will not fit in with the rest of my project.

public class Customers {

     public static JFrame frame = new JFrame();

     public static void frameGui(JPanel panel, String name){             
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            
            frame.setContentPane(panel);    
            frame.setSize(1200,500);         
            frame.setVisible(true);
     }

     public static void ScrollCustomersGui(){               
            Box box = Box.createVerticalBox();              
            box.add(customersTableHeadings(box));
            box.add(customersTableHeadings(box));
            box.add(customersTableHeadings(box));
            box.add(customersTableHeadings(box));               
            JScrollPane scroll = new JScrollPane(box);              
            JPanel All = new JPanel(new BorderLayout());
            All.add(scroll);                
            frameGui(All, "Customers");
        }       

    public static JPanel customersTableHeadings(Box panel){                  
         Font font = new Font("Courier", Font.BOLD,12);         
         JPanel customersTable = new JPanel();           
         JButton custid = new JButton("ONE");            
         JButton surname = new JButton("TWO");          
         customersTable.add(custid);
         customersTable.add(surname);            
         return customersTable;         
    }
}
  • *"Below is an MCVE version.."* It is not **Complete** without imports and a `main(String[])` to run it. – Andrew Thompson Nov 09 '14 at 08:08
  • Please learn common Java nomeclature (naming conventions - e.g. `EachWordUpperCaseClass`, `firstWordLowerCaseMethod()`, `firstWordLowerCaseAttribute` unless it is a `CONSTANT`) and use it consistently. – Andrew Thompson Nov 09 '14 at 08:09
  • @AndrewThompson I have added in the imports and main, and will in future ensure I conform to the Java nomeclature –  Nov 09 '14 at 10:19

2 Answers2

2

BoxLayout is designed to distribute unused space among components; struts, glue and filler won't change this. You can use the approach suggested here and here to alter the preferred size of the enclosing scroll pane. More generally, you can implement the scrollable interface. In addition, Swing GUI objects should be constructed and manipulated only on the event dispatch thread.

image

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/** @se https://stackoverflow.com/a/26829171/230513 */
public class Customers {

    private static final int N = 16;

    private void display() {
        Box box = Box.createVerticalBox();
        for (int i = 0; i < N; i++) {
            box.add(customersTableHeadings());
        }

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(box) {
            int w = box.getPreferredSize().width;
            int h = box.getPreferredSize().height;

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(9 * w / 8, h / 3);
            }
        });
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JPanel customersTableHeadings() {
        JPanel customersTable = new JPanel();
        JButton custid = new JButton("ONE");
        JButton surname = new JButton("TWO");
        customersTable.add(custid);
        customersTable.add(surname);
        return customersTable;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new Customers().display();
        });
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Note that you can combine this with the approach shown [here](http://stackoverflow.com/a/26836078/230513). – trashgod Nov 12 '14 at 13:18
1

I found the answer myself. By adding the horizontal and vertical inside the same loop, and by enclosing this in a JApplet it closes the gap.

Below is a full working version of the code:

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.Box;
import javax.swing.JApplet;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;


public class Box1 extends JApplet {

    public void init() {

    Box bv = Box.createVerticalBox();

    box(bv);    

    JScrollPane scroll = new JScrollPane(bv);

    JPanel All = new JPanel(new BorderLayout());
    All.add(scroll);

    Container cp = getContentPane();
    cp.add(All);
  }


  public static void main(String[] args) {
    frameGui(new Box1(), "Customers");
  }

  public static void frameGui (JApplet applet, String name) {
      JFrame frame = new JFrame();
    frame.getContentPane().removeAll(); 
    frame.setTitle(name);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
    frame.getContentPane().add(applet);
    frame.setSize(1200, 500);
    applet.init();
    applet.start();
    frame.setVisible(true);

  }



  public static Box box(Box boxvert){

      for (int i = 0; i < 50; i++){ 

             JTextField one = new JTextField("ONE");
             one.setMaximumSize(new Dimension (150,20));

             JTextField two = new JTextField("TWO");
             two.setMaximumSize(new Dimension (150,20));            

             Box horizontalBox = Box.createHorizontalBox();

             horizontalBox.add(one);
             horizontalBox.add(two);          

             boxvert.add(horizontalBox);

        }

      return boxvert;

  }



}
  • Swing applets need [`invokeLater()`](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html), too. – trashgod Nov 11 '14 at 17:45
  • @trashgod thank you for your answer. I tried to run your example-which seems to be basically the same as mine, but I could not run it because of the invokeLater() line. The code I posted works as it is, but I would be very interested to understand what invokeLater() is? –  Nov 11 '14 at 19:06
  • There's nothing wrong with your layout approach, but Swing GUI objects should be constructed and manipulated _only_ on the [event dispatch thread](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). "In an applet, the GUI-creation task must be launched from the init method using `EventQueue.invokeAndWait()`." – trashgod Nov 11 '14 at 22:25