2

I have tried every method to insert scroll pane inside the textarea but everytime it failed to show the scroll pane. Here is the full code :

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.SwingConstants.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.text.DecimalFormat;

public class Cart extends JFrame {
    private JPanel contentPane;
    BufferedReader in1 = null;
    PrintWriter itemList = null;
    String itemName, size, category;
    int quantity;
    double totalPrice, total = 0.00;
    DecimalFormat formatter = new DecimalFormat("#, ##0.00");

    public Cart() {
        setBounds(100, 100, 629, 439);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel lblCart = new JLabel("CART");
        lblCart.setHorizontalAlignment(SwingConstants.CENTER);
        lblCart.setFont(new Font("Sinhala Sangam MN", Font.BOLD, 23));
        lblCart.setBounds(6, 6, 617, 35);
        contentPane.add(lblCart);

        JButton btnConfirm = new JButton("Confirm");
        btnConfirm.setBounds(494, 382, 117, 29);
        contentPane.add(btnConfirm);

        JButton btnBack = new JButton("Continue Shopping");
        btnBack.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new MenuPage();
                dispose();
            }
        });
        btnBack.setBounds(345, 382, 148, 29);
        contentPane.add(btnBack);

        JButton btnDelete = new JButton("Delete");
        btnDelete.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "Need to remove item? Please resubmit your item from the menu page", "Delete Item?", JOptionPane.INFORMATION_MESSAGE);
            }
        });
        btnDelete.setBounds(16, 382, 117, 29);
        contentPane.add(btnDelete);

        JTextArea itemArea = new JTextArea();
        itemArea.setBackground(new Color(230, 230, 250));
        itemArea.setBounds(16, 53, 595, 308);
        itemArea.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
        JScrollPane scroll = new JScrollPane(itemArea);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        contentPane.add(itemArea);
        contentPane.add(scroll);

        try {
            in1 = new BufferedReader(new FileReader("G2L.txt"));
            itemList = new PrintWriter(new FileWriter("CartList.txt"));

            String indata = null;

            while ((indata = in1.readLine()) != null) {
                StringTokenizer st = new StringTokenizer(indata, ";");

                itemName = st.nextToken();
                quantity = Integer.parseInt(st.nextToken());
                size = st.nextToken();
                totalPrice = Double.parseDouble(st.nextToken());
                category = st.nextToken();

                itemList.println("Item : " + itemName + "\nQuantity : " + quantity + "\nSize : "
                        + size + "\nCategory : " + category + "\nTotal : MYR " + formatter.format(totalPrice) + "\n");

                total = total + totalPrice;
            }
            in1.close();
            itemList.close();

            itemArea.read(new BufferedReader(new FileReader("CartList.txt")), null);
        } catch (FileNotFoundException fnfe) {
            System.out.println("File not found");
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
        }

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

    public static void main(String args[]) {
        Cart c = new Cart();
    }
}

The data in the textfile G2L.txt is :

Ocean Blue;3;XXL;270.00 ;Formal Shirt
Peach Pink;2;XL;211.00 ;Formal Shirt
Grayed Out;1;M;88.50 ;Formal Shirt
Black Slack;2;XL;211.00 ;Formal Shirt

Am I missing something here? Any help would be appreciated. Thank you.

Slava Vedenin
  • 58,326
  • 13
  • 40
  • 59
Nazhirin Imran
  • 129
  • 1
  • 11

1 Answers1

2

You're shooting yourself in the foot by using null layouts and setBounds.

While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.

If you set the bounds of a JTextArea, you completely prevent it from expanding, preventing your scrollpanes from working. Instead, set the column and row properties of the JTextArea, get rid of null layouts, and use layout managers to create beautiful and easy to debug GUI's.

e.g.,

import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.*;

public class CartEg extends JPanel {
   private static final long serialVersionUID = 1L;
   private static final int GAP = 10;
   private static final String TITLE_TEXT = "Some Great Title";
   private JTextArea itemArea = new JTextArea(25, 60);

   public CartEg() {
      // create centered title JLabel
      JLabel titleLabel = new JLabel(TITLE_TEXT, SwingConstants.CENTER);
      // make it big and bold
      titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 42f));

      itemArea.setWrapStyleWord(true);
      itemArea.setLineWrap(true);
      JScrollPane scrollPane = new JScrollPane(itemArea);

      JPanel bottomButtonPanel = new JPanel(); // panel to hold JButtons
      bottomButtonPanel.setLayout(new BoxLayout(bottomButtonPanel, BoxLayout.LINE_AXIS));
      bottomButtonPanel.add(new JButton("Left Button"));
      bottomButtonPanel.add(Box.createHorizontalGlue());
      bottomButtonPanel.add(new JButton("Right Button 1"));
      bottomButtonPanel.add(new JButton("Right Button 2"));

      // create some empty space around our components
      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      // use a BorderLayout for the main JPanel
      setLayout(new BorderLayout(GAP, GAP));

      // add JScrollPane to the BorderLayout.CENTER position
      // add your JPanel that holds buttons to the BorderLayout.PAGE_END
      // and add your title JLabel to the BorderLayout.PAGE_START position

      add(scrollPane, BorderLayout.CENTER);
      add(titleLabel, BorderLayout.PAGE_START);
      add(bottomButtonPanel, BorderLayout.PAGE_END);


   }

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

      JFrame frame = new JFrame("Cart Example");
      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();
         }
      });
   }
}

Note that I create a JTextArea with row and column numbers passed into its constructor. I then set up the JTextArea to wrap words. I add it to a JScrollPane and then add the JScrollPane to the BorderLayout.CENTER position of a BorderLayout using container.


Edited example that now uses an AbstractAction, DisposeAction, and uses the same Action in both a JButton and a JMenuItem. This allows in-line creation of the JButton if desired.

create DisposeAction variable and initialize it:

// create an Action that can be added to a JButton or a JMenuItem
private Action disposeAction = new DisposeAction("Exit", KeyEvent.VK_X);

Create button that uses action and add to GUI at same time:

  // create jbutton that uses our dispose Action
  bottomButtonPanel.add(new JButton(disposeAction));

Create JMenuItem that uses action and add to JMenu at same time:

  // add a JMenuItem that uses the same disposeAction
  fileMenu.add(new JMenuItem(disposeAction));

Here's the code for the DisposeAction private inner class. It's a little convoluted so that it will work for both JButtons and JMenuItems. Note that this could be standalone if desired, and it would work just fine:

private class DisposeAction extends AbstractAction {
  private static final long serialVersionUID = 1L;
  public DisposeAction(String name, int mnemonic) {
     super(name); // set button's text
     putValue(MNEMONIC_KEY, mnemonic); // set it's mnemonic key
  }

  @Override
  public void actionPerformed(ActionEvent e) {
     // get the button that caused this action
     Object source = e.getSource();
     if (source instanceof AbstractButton) {
        AbstractButton exitButton = (AbstractButton) source;

        // get the parent top level window
        Window topWindow = SwingUtilities.getWindowAncestor(exitButton);
        if (topWindow == null) { // if null, then likely in a JMenuItem
           // so we have to get its jpopupmenu parent
           Container parent = exitButton.getParent();
           if (parent instanceof JPopupMenu) {
              JPopupMenu popupMenu = (JPopupMenu) parent;

              // get the invoker for the pop up menu
              Component invoker = popupMenu.getInvoker();
              if (invoker != null) {
                 // and get *its* top level window
                 topWindow = SwingUtilities.getWindowAncestor(invoker);
              }
           }
        }
        if (topWindow != null) {
           // dispose of the top-level window
           topWindow.dispose();
        }
     }
  }
}

Full example:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

public class CartEg extends JPanel {
   private static final long serialVersionUID = 1L;
   private static final int GAP = 10;
   private static final String TITLE_TEXT = "Some Great Title";
   private JTextArea itemArea = new JTextArea(25, 60);

   // create an Action that can be added to a JButton or a JMenuItem
   private Action disposeAction = new DisposeAction("Exit", KeyEvent.VK_X);
   private JMenuBar menuBar = new JMenuBar();  // menu bar for GUI

   public CartEg() {
      // create centered title JLabel
      JLabel titleLabel = new JLabel(TITLE_TEXT, SwingConstants.CENTER);
      // make it big and bold
      titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 42f));

      itemArea.setWrapStyleWord(true);
      itemArea.setLineWrap(true);
      JScrollPane scrollPane = new JScrollPane(itemArea);

      JPanel bottomButtonPanel = new JPanel(); // panel to hold JButtons
      bottomButtonPanel.setLayout(new BoxLayout(bottomButtonPanel, BoxLayout.LINE_AXIS));
      bottomButtonPanel.add(new JButton("Left Button"));
      bottomButtonPanel.add(Box.createHorizontalGlue());
      bottomButtonPanel.add(new JButton("Right Button 1"));
      bottomButtonPanel.add(new JButton("Right Button 2"));

      // create jbutton that uses our dispose Action
      bottomButtonPanel.add(new JButton(disposeAction));

      // create some empty space around our components
      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      // use a BorderLayout for the main JPanel
      setLayout(new BorderLayout(GAP, GAP));

      // add JScrollPane to the BorderLayout.CENTER position
      // add your JPanel that holds buttons to the BorderLayout.PAGE_END
      // and add your title JLabel to the BorderLayout.PAGE_START position

      add(scrollPane, BorderLayout.CENTER);
      add(titleLabel, BorderLayout.PAGE_START);
      add(bottomButtonPanel, BorderLayout.PAGE_END);

      // flesh out our jmenubar with a JMenu
      JMenu fileMenu = new JMenu("File");
      fileMenu.setMnemonic(KeyEvent.VK_F); // alt-F to invoke it

      // add a JMenuItem that uses the same disposeAction
      fileMenu.add(new JMenuItem(disposeAction));
      menuBar.add(fileMenu);
   }

   // expose the JMenuBar to the world
   public JMenuBar getMenuBar() {
      return menuBar;
   }

   private class DisposeAction extends AbstractAction {
      private static final long serialVersionUID = 1L;
      public DisposeAction(String name, int mnemonic) {
         super(name); // set button's text
         putValue(MNEMONIC_KEY, mnemonic); // set it's mnemonic key
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         // get the button that caused this action
         Object source = e.getSource();
         if (source instanceof AbstractButton) {
            AbstractButton exitButton = (AbstractButton) source;

            // get the parent top level window
            Window topWindow = SwingUtilities.getWindowAncestor(exitButton);
            if (topWindow == null) { // if null, then likely in a JMenuItem
               // so we have to get its jpopupmenu parent
               Container parent = exitButton.getParent();
               if (parent instanceof JPopupMenu) {
                  JPopupMenu popupMenu = (JPopupMenu) parent;

                  // get the invoker for the pop up menu
                  Component invoker = popupMenu.getInvoker();
                  if (invoker != null) {
                     // and get *its* top level window
                     topWindow = SwingUtilities.getWindowAncestor(invoker);
                  }
               }
            }
            if (topWindow != null) {
               // dispose of the top-level window
               topWindow.dispose();
            }
         }
      }
   }

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

      JFrame frame = new JFrame("Cart Example");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.setJMenuBar(mainPanel.getMenuBar());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thanks for having your time "rebuilding" the frame, really appreciate it. By the way, how do you add action listener to the button? – Nazhirin Imran May 10 '15 at 14:21
  • @NazhirinImran: same way you add the ActionListener to any button. My code was just for demonstration purposes to show the GUI. If you wanted functional JButtons, you'd have to have more code to allow this to occur. Note that I usually try to set a JButton's Action rather than add an ActionListener. Thus I would use an inner class that extends AbstractAction, and pass that into the button's constructor. – Hovercraft Full Of Eels May 10 '15 at 14:25
  • I have another problem, I have a button in a JFrame(another frame) which when the user clicked will open up the cart, but it seems like when I click on it, it does nothing. The `new CartEg()` seems not working when used in the button inside the another frame – Nazhirin Imran May 10 '15 at 15:09
  • @NazhirinImran: if you have a new problem, then you should ask a new question. But before you to so, consider creating and posting a [minimal example program](http://sscce.org) with your question. Also read this link about [Multiple JFrames](http://stackoverflow.com/questions/9554636/the-use-of-multiple-jframes-good-bad-practice). You probably want to use a JDialog and not another JFrame if you're displaying a dependent window. – Hovercraft Full Of Eels May 10 '15 at 15:17
  • @NazhirinImran: example of using an AbstractAction class instead of an ActionListener. – Hovercraft Full Of Eels May 10 '15 at 15:29