Hello,
me again :-). This time I need to build a small calculator-like GUI, like this:
3c9bdedf8ee9380da461586266ce3130
This time I thought I'd ask a few questions before I start building it!
1)In terms of layout, I was thinking to use the GridLayout again: one for the text field and one for the buttons. Now, do I need a to include a FlowLayout as well or can I leave it out?
2)the buttons: it seems to me to be a bit tedious to add 16 different JButton variables, each of them for a different button as required. So, would it be doable to have an array of buttons and insert them in the panel with a loop perhaps? The only thing is, how would I assign the correct labels to the button if I add them in a loop?!
thanks

Recommended Answers

All 18 Replies

Yes, and I would place the buttons as a GridLayout inside a JPanel, so the JFrame has a text field and a JPanel, one above the other.

A loop to create the buttons is a good idea. There's no need to have an array of buttons - once created and an action listener added there's no need to reference the buttons any more. (In the action listener you can just getText for the event source to see which button was pressed (there are better ways, but that's the easiest).) You could define a String array with the labels, which makes it easy to add the right label to each button.

labels = {"7","8"..."=","+")
for i = 0 to 15 {
   create new button with its text = labels[i]
   add it to the JPanel
   set its action listener
}
...
wait for user to press one!

thanks, although the exercise doesn't require the acton listener, which is a good idea because I can concentrate on the layout. I have found an exercise which involves action listeners and it is a bit more complicated, so I will do that at a later stage.
I will keep the thread open in case I get stuck when I build the calculator.
thanks

Right, I think I am a bit confused and ended up with the below:

I think I need to get this all GUI thing cleared in my head. Let's start with my code perhaps.
In the calculator program I have created created 2 jpanels, one for the keys and one for the text field. The keys are in a GridLayout so that I can add columns and rows. The textfield is not in a GridLayout, because I thought uit's not necessary, but seeing the results perhaps it needs to be?
Here is the code:

/*CalculatorLayout.java
ex 14.9 p 662
*/
import java.awt.FlowLayout;//arrange the components
import java.awt.GridLayout;//layout for controller
import javax.swing.JFrame;//provides basic window feature
import javax.swing.JPanel;//for the panels
import javax.swing.JTextField;//for the txt field
import javax.swing.JButton;//for the keypad

public class CalculatorLayout extends JFrame{
private FlowLayout layout;//layout object. Do I need a flowlayout at all?
private JPanel numberKeysPanel;//contains the number keys panel
private JPanel calculationAreaPanel;//contains the calculation panel
private GridLayout numberKeysGrid;//contains the number keys
private JTextField calculationArea;//text field where numbers are displayed
private JButton numberKey;//symbols
private String[] labels;//hold the labels

//constructor
public CalculatorLayout(){
super( "Calculator" );
layout = new FlowLayout();//create FlowLayout. Do I need a flowlayout at all?
setLayout( layout );
calculationAreaPanel = new JPanel();
calculationArea = new JTextField( "", 20 );//created empty display
calculationAreaPanel.add( calculationArea ); //add the text field to the jpanel

numberKeysPanel = new JPanel();

String[] labels = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+" };
numberKeysGrid = new GridLayout(4, 4);//create grid layout

for( int counter = 0; counter < labels.length; counter++ ){
numberKey = new JButton( labels[ counter ] );//create button with apppropriate label
numberKeysPanel.add( numberKey );//add buttons to panel
}//end of loop
numberKeysPanel.setLayout( numberKeysGrid );
//set up GridLayout manager

//numberKeysPanel.add( numberKeysGrid );//add grid to jpanel
add( calculationAreaPanel );//add calc area jpanel to jframe
add( numberKeysPanel );//add jpanel to the jframe
}//end of constructor

}//end of CalculatorLayout class

and

/*CalculatorLayoutTest.java
Testing CalculatorLayout class
*/
import javax.swing.JFrame;
public class CalculatorLayoutTest{
public static void main( String[] args ){
CalculatorLayout calculatorLayoutTest = new CalculatorLayout();
calculatorLayoutTest.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
//calculatorLayoutTest.setSize( 400, 200 );
calculatorLayoutTest.setVisible( true );
calculatorLayoutTest.pack();
}//end of main

}//end of CalculatorLayoutTest class

On a more general note, I think there are a few things that I would love if somebody can clarify for me please:
1)Steps when creating a GUI (take for example my calculator program):
-Create a class that extends JFrame
-choose layout: (flowLayout, dorderLayout, GridLayout etc)
-create the various panels (JPanels if needed)
-create the components (textfields etc)
-attach the components to the Jpanel using add()
-set up the layout (in my case the GridLayout) by creating a GridLayout object and by using setLayout()
-add the jpanels created to the JFrame by using add()

2)If I decide to use a GridLayout like I have done in the above program and in the other exercise (http://www.daniweb.com/software-development/java/threads/470792/layout-manager-which-one), do I need to have a flowLayout as well? I take I can use the two together, meaning have an overarching flowLayout, then a few JPanels with a GridLayout. Correct?
thanks

Each container (JFrame, JPanel etc) has its own layout manager, so eg you could have a flowlayout for the frame, add a panel to that, and have a grid layout for the panel. You can't have 2 layout managers for the same container.

In this case, there's no need a panel to hold the entry field, since it's just one component. The default layout manager for a JFrame (strictly speaking, for its content pane) is a BorderLayout, which is all you need here. The entry field can go at the top ("PAGE_START"), and the panel with the button grid can go in the center ("CENTER")

ahhhhh, OK, now things are becoming clearer.
Done and works:

/*CalculatorLayout.java
ex 14.9 p 662
*/
import java.awt.BorderLayout;//arrange the components
import java.awt.GridLayout;//layout for controller
import javax.swing.JFrame;//provides basic window feature
import javax.swing.JPanel;//for the panels
import javax.swing.JTextField;//for the txt field
import javax.swing.JButton;//for the keypad

public class CalculatorLayout extends JFrame{
    private BorderLayout layout;//layout object. Do I need a flowlayout at all?
    private JPanel numberKeysPanel;//contains the number keys panel
    //private JPanel calculationAreaPanel;//contains the calculation panel
    private GridLayout numberKeysGrid;//contains the number keys
    private JTextField calculationArea;//text field where numbers are displayed
    private JButton numberKey;//symbols
    private String[] labels;//hold the labels

    //constructor
    public CalculatorLayout(){
        super( "Calculator" );
        layout = new BorderLayout( 0, 5 );//create FlowLayout. Do I need a flowlayout at all?
        setLayout( layout );
    //  calculationAreaPanel = new JPanel();
        calculationArea = new JTextField( "", 30 );//created empty display
        //calculationAreaPanel.add( calculationArea ); //add the text field to the jpanel

        numberKeysPanel = new JPanel();

        String[] labels = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+" };
        numberKeysGrid = new GridLayout( 4, 4, 5, 5 );//create grid layout

        for( int counter = 0; counter < labels.length; counter++ ){
            numberKey = new JButton( labels[ counter ] );//create button with apppropriate label
            numberKeysPanel.add( numberKey );//add buttons to panel
        }//end of loop
        numberKeysPanel.setLayout( numberKeysGrid );
        //set up GridLayout manager

        //numberKeysPanel.add( numberKeysGrid );//add grid to jpanel
        add( calculationArea, BorderLayout.PAGE_START );//add calc area jpanel to jframe
        add( numberKeysPanel, BorderLayout.CENTER );//add jpanel to the jframe
    }//end of constructor

}//end of CalculatorLayout class

And I couldn't resist it and added some dimensions:

/*CalculatorLayoutTest.java
Testing CalculatorLayout class
*/
import javax.swing.JFrame;
import java.awt.Dimension;//to sort specify the dimension
public class CalculatorLayoutTest{
    public static void main( String[] args ){
        CalculatorLayout calculatorLayoutTest = new CalculatorLayout();
        calculatorLayoutTest.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        //calculatorLayoutTest.setSize( 400, 200 );     
        calculatorLayoutTest.setVisible( true );

        Dimension minimumSize = new Dimension(400, 200);//specify dimensions
        calculatorLayoutTest.setMinimumSize( minimumSize );//set dimensions

        calculatorLayoutTest.pack();
    }//end of main

}//end of CalculatorLayoutTest class

643543bca3672cc83799c9cdd23c699c

Excellent!
One small point - always set the layout manager before adding anything to a container as the parameters on the add method are interpreted diferently by different layout managers and results may be unpredictable.

ps Have you tried re-sizing your window with the mouse?

Brilliant, I will bear that in mind.
Yes I did try to resize it and - I don't know whether this is desiderable or not - the keys and the text field grow/shrink with the window, becoming excessively big/small...

whether it is desirable or not, is for you to decide (or your client/professor/employer)

It should respect the minimum size you specified, but you may have less luck trying to set a max size. One thing can do is add a listener for the frame being re-sized and forcing it back when it goes out of the "desirable" range. (Probably not worth worrying about for this exercise.)

or just making sure it can't be resized.

thanks guys. I am not too worried about this, but I have decided to do what stultuske suggested (I have tried to set a maximum size adding these lines

Dimension maximumSize = new Dimension(900, 600);
calculatorLayoutTest.setMaximumSize( maximumSize );//set dimensions

but as JamesCherrill said no joy!) so I eventually found a way to disable resizing altogether adding setResizable(false); (I found this solution on the net). That seems to do the trick :-)!

/*CalculatorLayoutTest.java
Testing CalculatorLayout class
*/
import javax.swing.JFrame;
import java.awt.Dimension;//to sort specify the dimension
public class CalculatorLayoutTest{
    public static void main( String[] args ){
        CalculatorLayout calculatorLayoutTest = new CalculatorLayout();
        calculatorLayoutTest.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        //calculatorLayoutTest.setSize( 400, 200 );     
        calculatorLayoutTest.setVisible( true );


        Dimension minimumSize = new Dimension(400, 200);//specify dimensions
        calculatorLayoutTest.setMinimumSize( minimumSize );//set dimensions
        calculatorLayoutTest.setResizable( false );

        /*Dimension maximumSize = new Dimension(900, 600);
        calculatorLayoutTest.setMaximumSize( maximumSize );//set dimensions */

        calculatorLayoutTest.pack();
    }//end of main

}//end of CalculatorLayoutTest class

which is actually what I was talking about :)
resizing it might make your layout manager(s) to fill up the newly added "free space", which setting your JFrame to non-resizable should be able to deal with.

I would have thought that by using setResizable( false ); I could have still changed the size of the main window without changing the size of the content pane but instead I noticed that I can't even resize the java window anymore. I guess this is what it does :-)

if you set it on the main JFrame, indeed you can't. it's (as far as I've known) the only guaranteed way to keep your components in the location/order you designed them to be when using layoutmanagers, but then again I haven't used Swing that much, might be my knowledge here is a bit limited :)

if you set Dimensions, that's basically the 'starting size' of your JFrame, but you can still make it smaller (you'll see that your buttons are not set smaller with the JFrame, they're just outside the range of the JFrame (until you widen it again), or you can make it larger, giving the components extra space you hadn't forseen, which both may cause layout issues.

The behaviour of the components when the window is resized is controlled by the layout manager. Most try to resize some or all of the components to fit the window - you have to look at each layout manger separately for details.
Once again, if you get very specific about the behaviour you want then GridBagLayout is probably going to be necessary.

OK, thanks for that :-)

Hi

May I ask what book are you using to learn Java!?

please open another thread faizlo.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.