0

I am having trouble making the layout of a simple Calculator. What is happening is that everything appears fine except that my subtract button stays as the background and I have to guess where my other buttons are to be able to click them. When I click them I am able to see them until I unclick them. is there anyway to fix this? I'm not posting the math algorithm a it is not needed for this question.

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

public class GUIcalc extends JFrame implements ActionListener {

    private JPanel panel;
    private JPanel buttonpanel;
    private JPanel text;
    private JLabel sumfield;
    private BorderLayout layout;
    private GridLayout grid;
    private Container container;
    private boolean toggle=true;
    private float sum;
    private int num1;
    private int num2;
    JButton one = new JButton("1");
    JButton two = new JButton("2");
    JButton three = new JButton("3");
    JButton four = new JButton("4");
    JButton five = new JButton("5");
    JButton six = new JButton("6");
    JButton seven = new JButton("7");
    JButton eight = new JButton("8");
    JButton nine = new JButton("9");
    JButton zero = new JButton("0");
    JButton multi = new JButton("*");
    JButton divide = new JButton("/");
    JButton equal = new JButton("=");
    JButton add = new JButton("+");
    JButton subtract = new JButton("-");
    JButton deci = new JButton("."); 
    private final Font number= new Font("monspaced", Font.ITALIC, 20);
    JFrame guiFrame;
    private int counter;

    /**
     * @param args
     */
    public GUIcalc() {

        super("Calculator");    
        sumfield = new JLabel(""+sum);
        sumfield.setLocation(0, 0);
        sumfield.setSize(245, 45);
         add(sumfield);
        seven=new JButton("7");
        seven.setLocation(0,50);
        seven.setSize(50, 50);
        seven.addActionListener(this);
        add(seven);
        eight=new JButton("8");
        eight.setLocation(55,50);
        eight.setSize(50, 50);
        eight.addActionListener(this);
        add(eight);
        nine=new JButton("9");
        nine.setLocation(110,50);
        nine.setSize(50, 50);
        nine.addActionListener(this);
        add(nine);
        divide=new JButton("/");
        divide.setLocation(165,50);
        divide.setSize(50, 50);
        divide.addActionListener(this);
        add(divide);
        six=new JButton("6");
        six.setLocation(0,105);
        six.setSize(50, 50);
        six.addActionListener(this);
        add(six);
        five=new JButton("5");
        five.setLocation(55,105);
        five.setSize(50, 50);
        five.addActionListener(this);
        add(five);  
        four=new JButton("4");
        four.setLocation(110,105);
        four.setSize(50, 50);
        four.addActionListener(this);
        add(four);
        multi=new JButton("*");
        multi.setLocation(165,105);
        multi.setSize(50, 50);
        multi.addActionListener(this);
        add(multi);
        three=new JButton("3");
        three.setLocation(0,165);
        three.setSize(50, 50);
        three.addActionListener(this);
        add(three);
        two=new JButton("2");
        two.setLocation(55,165);
        two.setSize(50, 50);
        two.addActionListener(this);
        add(two);
        one=new JButton("1");
        one.setLocation(110,165);
        one.setSize(50, 50);
        one.addActionListener(this);
        add(one);
        add=new JButton("+");
        add.setLocation(165,165);
        add.setSize(50, 50);
        add.addActionListener(this);
        add(add);
        zero=new JButton("0");
        zero.setLocation(0,220);
        zero.setSize(50, 50);
        zero.addActionListener(this);
        add(zero);      
        deci=new JButton(".");
        deci.setLocation(55,220);
        deci.setSize(50, 50);
        deci.addActionListener(this);
        add(deci);
        equal=new JButton("=");
        equal.setLocation(110,220);
        equal.setSize(50, 50);
        equal.addActionListener(this);
        add(equal);
        subtract=new JButton("-");
        subtract.setLocation(165,220);
        subtract.setSize(50, 50);
        subtract.addActionListener(this);
        add(subtract);
   }
rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • 1
    Java GUIs have to work on different OS', screen size, screen resolution etc. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Sep 20 '14 at 04:14
  • 1
    `private final Font number= new Font("monspaced", Font.ITALIC, 20);` That will fail (it is spelled wrong). Better to use `..new Font(Font.MONOSPACED, Font.ITALIC, 20);` – Andrew Thompson Sep 20 '14 at 04:18

1 Answers1

3

You're problem is that you're trying to set the absolute location and size of components in a container that uses BorderLayout (the JFrame's contentPane). The quick and easy solution is to make the JFrame contentPane's layout null via setLayout(null)

While this is quick and easy, and it works, it's also wrong because it forces you to create rigid GUI's that might look good on one platform at a certain screen resolution, it looks terrible at other resolutions or on other platforms and is near impossible to modify as needed. A better solution is to use the layout managers to your advantage. Hold on for an example of this....


Edit
For example what if...

  • Your main GUI used a BorderLayout
  • You added your JTextField that displays the numbers to the main GUI BorderLayout.NORTH also known as BorderLayout.PAGE_START
  • Create a JPanel for the buttons, say called btnPanel, and add it to the main GUI BorderLayout.CENTER.
  • Give the btnPanel a GridLayout sized to accept all the buttons.
  • Add the JButtons to the btnPanel as you create them.
  • Rather than setting the sizes of the JButtons, why not instead set the font larger, and let the buttons and the GUI size themselves to accommodate the larger fonts.

For example, code done this way would look like:

enter image description here

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

import javax.swing.*;

public class GUIcalc2 extends JPanel {
   private static final String[][] BTN_TEXTS = { 
      { "7", "8", "9", "/" },
      { "6", "5", "4", "*" }, 
      { "3", "2", "1", "+" }, 
      { "0", ".", "=", "-" } };
   private static final int GAP = 3;
   private static final float TF_SIZE = 18f;
   private static final float BTN_SIZE = 24f;
   private JButton[][] buttons = new JButton[BTN_TEXTS.length][BTN_TEXTS[0].length];
   private JTextField textField = new JTextField(10);

   public GUIcalc2() {
      textField.setFont(textField.getFont().deriveFont(TF_SIZE));
      JPanel btnPanel = new JPanel(new GridLayout(BTN_TEXTS.length, 
            BTN_TEXTS[0].length, GAP, GAP));
      for (int row = 0; row < BTN_TEXTS.length; row++) {
         for (int col = 0; col < BTN_TEXTS[0].length; col++) {
            JButton btn = new JButton(BTN_TEXTS[row][col]);
            // add ActionLIstener here
            btn.setFont(btn.getFont().deriveFont(Font.BOLD, BTN_SIZE));
            btnPanel.add(btn);

            buttons[row][col] = btn;
         }
      }

      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      setLayout(new BorderLayout(GAP, GAP));
      add(textField, BorderLayout.PAGE_START);
      add(btnPanel, BorderLayout.CENTER);
   }

   private static void createAndShowGui() {
      GUIcalc2 mainPanel = new GUIcalc2();

      JFrame frame = new JFrame("Calc");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Now for the beauty of code that uses layout managers, say you now want to add a row of buttons at the top that does memory functions such as memory clear, memory replace, memory add to,... all you need to do (from the GUI view standpoint) is to add another row of String constants:

private static final String[][] BTN_TEXTS = { 
   {"MC", "MR", "MS", "M+"},  // new line !
   { "7", "8", "9", "/" },
   { "6", "5", "4", "*" }, 
   { "3", "2", "1", "+" }, 
   { "0", ".", "=", "-" } };

Do this and the GUI chances to:

enter image description here

And notice that all the buttons resize to allow for the larger text Strings contained in the top row, and they do this without having to write any additional code to do this.

Try to do something similar with your code, and notice that you'll have to change the positions of all components that are under or to the right of the added components, and the risks of errors and bugs multiply.

Of course you still need to add the logic code, but that's the subject of another discussion.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373