java - JScrollPane 不会显示在 JTextArea 中

标签 java swing

我尝试了各种方法在文本区域内插入滚动 Pane ,但每次都无法显示滚动 Pane 。这是完整的代码:

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();
    }
}

文本文件G2L.txt中的数据是:

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

我在这里遗漏了什么吗?任何帮助,将不胜感激。谢谢。

最佳答案

使用 null 布局和 setBounds 是在搬起石头砸自己的脚。

虽然 null 布局和 setBounds() 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单、最好的方法,但您创建的 Swing GUI 越多,使用它们时遇到的困难就越严重。当 GUI 调整大小时,它们不会调整组件的大小,它们是增强或维护的皇家女巫,放置在滚动 Pane 中时它们完全失败,在所有平台或与原始分辨率不同的屏幕分辨率上查看时,它们看起来非常糟糕.

如果设置 JTextArea 的边界,则完全阻止它扩展,从而阻止滚动 Pane 工作。相反,设置 JTextArea 的列和行属性,摆脱 null 布局,并使用布局管理器创建美观且易于调试的 GUI。

例如,

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();
         }
      });
   }
}

请注意,我创建了一个 JTextArea,并将行号和列号传递到其构造函数中。然后我设置 JTextArea 来换行。我将其添加到 JScrollPane,然后使用容器将 JScrollPane 添加到 BorderLayout 的 BorderLayout.CENTER 位置。


编辑后的示例现在使用 AbstractAction、DisposeAction,并在 JButton 和 JMenuItem 中使用相同的 Action。如果需要,这允许内联创建 JButton。

创建 DisposeAction 变量并初始化它:

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

创建使用操作的按钮并同时添加到 GUI:

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

创建使用action的JMenuItem并同时添加到JMenu:

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

这是 DisposeAction 私有(private)内部类的代码。它有点复杂,因此它适用于 JButtons 和 JMenuItems。请注意,如果需要,这可以是独立的,并且它可以正常工作:

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();
        }
     }
  }
}

完整示例:

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();
         }
      });
   }
}

关于java - JScrollPane 不会显示在 JTextArea 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30152080/

相关文章:

java - 如何升级org.jboss.as.jmx :main in WildFly10

java - java中OraclePreparedStatement方法setStringForClob

java - 我可以修改 char 数组中的一个元素,但无法修改另一个元素

JButton 中的 Java 图标大小

java - 如何将字符串从工作线程发送到文本区域?

java - 使用 Appium 和 Gradle 进行 Android 测试

java - 多线程网络服务器

java - JButton 仅在我将鼠标悬停在其上后才出现?

Java:点击按钮后JPanel无法接收按键事件(没有注册的事件监听器)?

java - 如何在其他按钮上创建此按钮?