1

I wrote a program to compose a GUI using swing/awt framework for my assignment. So far, I am able to get the pieces working together, but when I put them all into a JFrame, they are not coming out as expected.

I have recently started working on Java GUI framework, and not sure what is missing in my code. How can I get this working properly?

I am also attaching the screen shots (see at the bottom) of the output I am getting.

public class MainFrame extends JFrame {

    public MainFrame() {
    addComponentsToPane(this.getContentPane());
    }

    private void addComponentsToPane(Container pane) {

        // Set layout
        GridBagConstraints gbc = new GridBagConstraints();
        this.setTitle("Test tool");
        this.setSize(600, 650);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new GridLayout(2, 1));

        // Add video JComponent
        mMainPanel = new MainPanel();
        pane.add(mMainPanel, 0);

        // Add conference screen panel
        mFeedPanel = new FeedPanel();
        pane.add(mFeedPanel, 1);

        // Add a button panel
        mButtonPanel = new ButtonPanel();
        pane.add(mButtonPanel, 2);

        this.setResizable(true);
        this.setVisible(true);
        this.pack();
    }
}

// In actual output, there is 1 screen in this panel. 
// mScreen1 is derived from JComponent object.
public class MainPanel() extends JPanel {

    public MainPanel() {
    addMainPanelComponents();
    }

    private void addMainPanelComponents() {
        this.setSize(352, 240);
        setBackground(Color.yellow);
        setLayout(new GridLayout(1, 2));
        add(mScreen);
        setVisible(true);
    }
}

// In actual output, there are 3 screens in this panel. I have shown code for 1 screen only
// mScreen1 is derived from JComponent object.
public class FeedPanel extends JPanel {

    public FeedPanel() {
    addFeedPanelComponents();
    }

    private void addFeedPanelComponents() {

        String img1 = "images/screen1.png";

        setSize(352, 150);
        setBackground(Color.yellow);
        setLayout(new GridLayout(1, 3));                

        Image image1 = ImageIO.read(new File(img1));
        mScreen1.setImage(image1);
        add(mScreen1);
        setVisible(true);
    }
}

public class ButtonPanel extends JPanel {

    public ButtonPanel() {
    addButtonPanelComponents();
    }

    private void addButtonPanelComponents() {

        this.setSize(352, 150);
        this.setBackground(Color.yellow);
        this.setLayout(new GridLayout(1, 
                                      5));

        // Add Button to panel
        mStartButton = new JButton("Start");
        this.add(mStartButton);
        mStartButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                StartButtonActionListener(ae);
            }
        });

        mStopButton = new JButton("Stop");
        this.add(mStopButton);
        mStopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                StopButtonActionListener(ae);
            }
        });
        setVisible(true);
    }
}

This comes by default on running the code.

enter image description here

This comes after manually resizing the frame. enter image description here

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
AnilJ
  • 1,951
  • 2
  • 33
  • 60
  • Are you sure the frame size you specified is correct? As much as I see, the image size is more than 75% of the frame size you specified. – Total Anime Immersion Jul 02 '14 at 19:32
  • Just added the actual frame size I am using to the code, but still the same results. The FeedPanel contains 3 images in its grid layout. So does this mean the frame width should be 3 times the image size? – AnilJ Jul 02 '14 at 19:49
  • May I ask why you aren't using GridLayout and making the code less complex by making a few changes? – Total Anime Immersion Jul 02 '14 at 19:51
  • Also I'm adding buttons to its own panel before adding the ButtonPanel to the Mainframe (JFrame). Yet, upon resizing the window, the buttons are also getting resized. – AnilJ Jul 02 '14 at 19:54
  • I am using GridLayout for MainFrame. See this line if you missed it. this.setLayout(new GridLayout(2, 1)); – AnilJ Jul 02 '14 at 19:55
  • Can you attach the layout you wish to get. Perhaps i can help you with the code then. – Total Anime Immersion Jul 02 '14 at 19:55
  • "attach the layout" .. you mean add the actual code? Or the layout I am looking for is in that expanded image where I want the top image at the centre, three images at the middle, and those couple of buttons at the bottom in their natural size. – AnilJ Jul 02 '14 at 19:56
  • No, I mean, how you want the components to show up on your frame. – Total Anime Immersion Jul 02 '14 at 19:58
  • Just updated my earlier comment. I also want to keep the same JPanel based design so that I can add more to it if required. Putting everything directly into JFrame - I want to avoid. – AnilJ Jul 02 '14 at 19:59
  • I believe pack() is your issue. Either remove pack() and stick to setSize(w,h) or use pack, but use it properly. i.e. use setPreferredSize instead of setSize. See http://docs.oracle.com/javase/7/docs/api/java/awt/Window.html#pack%28%29 – BlackBox Jul 02 '14 at 20:06
  • Ok. removing the pack() did solve the problem to an extent that my screens are now coming out correct by default. However ButtonPanel is still of big size. – AnilJ Jul 02 '14 at 20:30

2 Answers2

3

Try this :

    public class Main{

    private JFrame f;
    private JLabel l1, l2, l3,l4;
    private JPanel p1, p2, p3;
    private JButton b1, b2, b3;

    public Main(){

    this.f = new JFrame();
    this.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.f.setLayout(new GridLayout(3,1));

    this.p1 = new JPanel();
    this.p1.setLayout(null)
    this.p1.setSize(yoursize);

    this.l1 = new JLabel();
    this.l1.setBounds(x,y,xspan,yspan);

    this.p1.add(l1);

    this.p2 = new JPanel();
    this.p2.setLayout(new GridLayout(1,3));

    this.l2 = new JLabel();
    this.l3 = new JLabel();
    this.l4 = new JLabel();

    this.p2.add(l2);
    this.p2.add(l3);
    this.p2.add(l4);

    this.p3 = new JPanel();
    this.p3.setLayout(new GridLayout(1,3));

    this.b1 = new JButton();
    this.b2 = new JButton();  
    this.b3 = new JButton();

    this.p3.add(b1);       
    this.p3.add(b2);
    this.p3.add(b3);

    this.f.add(p1);
    this.f.add(p2);
    this.f.add(p3);

    this.f.pack();
    this.f.setResizeable(false)
    }}

Add your video components instead of labels and you can change the color of the components as you wish. Also if you want more control over the size and position of the components, use null layout and place them individually using setBounds() function as once shown in the program above. It is surely time consuming but makes the layout perfect.

  • Thanks. Let me try this out, and will let you know if I face any other difficulty. – AnilJ Jul 02 '14 at 20:31
  • Welcome. Also, as i mentioned, if u want the button size to be adjustable, use null layout instead and manually set the size that fits your choice. – Total Anime Immersion Jul 02 '14 at 20:33
  • I got most of the things in place except that the ButtonPanel size is not able to control neither it is adjusting by itself as per the height of the buttons. I observe that all three panels (I have given different colour to them) are of same size. I am not sure if this is because I am using GridLayout() in JFrame. – AnilJ Jul 02 '14 at 22:56
  • You need to set the layout of the JPanel consisting of the button as null and manually set the size and position using the setBounds function. In case that doesn't work, you will need to set the layout of the JFrame itself as null and manually set the positions of all the components. And as I mentioned earlier, the layout managers aren't perfect, hence if you want a customized layout to make your software look perfect, you need to either create your own layout manager or manually set them as I have shown. – Total Anime Immersion Jul 03 '14 at 05:45
3

The combination of BorderLayout , GirdLayout and BoxLayout can do this for you(Actually it's not the only choice).

Here is the code:

import java.awt.BorderLayout;
import java.awt.GridLayout;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class GridLayoutTest {
    public void createUI(){
        JFrame frame = new JFrame();

        JPanel topPanel = new TopPanel();
        JPanel buttomPanel = new ButtomPanel();


        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(topPanel,BorderLayout.CENTER);
        mainPanel.add(buttomPanel,BorderLayout.SOUTH);
        frame.add(mainPanel,BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        GridLayoutTest test = new GridLayoutTest();
        test.createUI();
    }

    @SuppressWarnings("serial")
    class TopPanel extends JPanel{
        public TopPanel(){
            setLayout(new GridLayout(2, 3));
            ImageIcon icon = new ImageIcon("capture.png");
            JLabel label1 = new JLabel(icon);
            label1.setVisible(false);
            JLabel label2 = new JLabel(icon);
            JLabel label3 = new JLabel(icon);
            label3.setVisible(false);
            JLabel label4 = new JLabel(icon);
            JLabel label5 = new JLabel(icon);
            JLabel label6 = new JLabel(icon);
            add(label1);
            add(label2);
            add(label3);
            add(label4);
            add(label5);
            add(label6);
        }
    }

    @SuppressWarnings("serial")
    class ButtomPanel extends JPanel{
        public ButtomPanel(){
            JButton startButton = new JButton("start");
            JButton stopButton = new JButton("stop");
            JButton recordButton = new JButton("record");

            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
            add(Box.createHorizontalGlue());
            add(startButton);
            add(Box.createHorizontalStrut(10));
            add(stopButton);
            add(Box.createHorizontalStrut(10));
            add(recordButton);
            add(Box.createHorizontalGlue());
        }
    }
}

BoxLayout is so good too provide white space and help you to center the component.

    setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    add(Box.createHorizontalGlue());
    add(startButton);
    add(Box.createHorizontalStrut(10));
    add(stopButton);
    add(Box.createHorizontalStrut(10));
    add(recordButton);
    add(Box.createHorizontalGlue());

Add Glue before the first component and after the last component will help you too center the component and add strut can help you to provide white space you want. you can refer to https://stackoverflow.com/a/22525005/3378204 for more details.

Here is the effect:

enter image description here

enter image description here

enter image description here

The BoxLayout won't affect your component's size. Hope it can help you.

Community
  • 1
  • 1
Eugene
  • 10,627
  • 5
  • 49
  • 67