将矢量打印到 JTextArea 时出现间距错误

Spacing errors while printing vector to JTextArea

所以我正在努力制作一个建立在 Java Swing GUI 之上的数据库系统...我有一个按钮可以将 person/thing 添加到矢量(在此case 数据库):

// Database
Vector<String> db = new Vector<String>();

这是要添加的按钮的动作侦听器:

new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        String newStudent = student.getText();
        db.addElement(newStudent);

这部分似乎工作正常,但是,当我使用字符串缓冲区在 JTextArea 上打印矢量时,JTextArea 上的文本存在奇怪的间距问题

这是 StringBuffer 和我将向量打印到 JTextArea 的部分:

StringBuffer dbb = new StringBuffer();
for (int i = 0; i < db.size(); i++) {
    dbb.append(db.get(i) + '\n');
}
// printDB is the JTextArea
printDB.setText(dbb.toString());
    add(printDB);

间距问题截图: Screenshot

关于可能导致此问题的任何想法?间距似乎也是线性的(1spaces、2spaces、3spaces...)

代码:

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.*;
import java.util.Vector.*;
import javax.swing.*;

public class Database extends JFrame implements ActionListener, EventListener {

   // Database
   Vector<String> db = new Vector<String>();

   // Main Menu Buttons:
   JButton addStudent = new JButton("Add Student");
   JButton deleteStudent = new JButton("Delete Button");
   JButton deleteAll = new JButton("Delete All Students");
   JButton printAll = new JButton("Print Database");
   JTextArea welcome = new JTextArea("Welcome!");

   // Add Student Menu:
   JTextField student = new JTextField();
   JButton submit = new JButton("Add Student");

   // Print Students
   JTextArea printDB = new JTextArea();
   JButton returnMenu = new JButton("Return to Menu");

   public Database() {
      super("DatabaseGUI");
      setSize(800, 600);

      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setLayout(null);
      setResizable(false);
      welcome.setBackground(this.getForeground());
      add(welcome);
      welcome.setSize(60, 15);
      welcome.setLocation(386, 300);
      add(addStudent);
      addStudent.setSize(150, 50);
      addStudent.setLocation(25, 100);
      add(deleteStudent);
      deleteStudent.setSize(150, 50);
      deleteStudent.setLocation(625, 100);
      add(deleteAll);
      deleteAll.setLocation(225, 100);
      deleteAll.setSize(150, 50);
      add(printAll);
      printAll.setLocation(425, 100);
      printAll.setSize(150, 50);
      addStudent.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            welcome.setVisible(false);
            addStudent.setVisible(false);
            deleteStudent.setVisible(false);
            deleteAll.setVisible(false);
            printAll.setVisible(false);
            add(student);
            add(submit);
            submit.setVisible(true);
            submit.setSize(150, 30);
            submit.setLocation(425, 250);
            student.setVisible(true);
            student.setSize(150, 30);
            student.setLocation(275, 250);
            submit.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                  String newStudent = student.getText();
                  db.addElement(newStudent);
                  student.setText(null);
                  student.setVisible(false);
                  submit.setVisible(false);
                  welcome.setVisible(true);
                  addStudent.setVisible(true);
                  deleteStudent.setVisible(true);
                  deleteAll.setVisible(true);
                  printAll.setVisible(true);
               }
            });
         }
      });
      printAll.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            welcome.setVisible(false);
            addStudent.setVisible(false);
            deleteStudent.setVisible(false);
            deleteAll.setVisible(false);
            printAll.setVisible(false);
            StringBuffer dbb = new StringBuffer();
            for (int i = 0; i < db.size(); i++) {
               dbb.append(db.get(i) + '\n');
            }
            printDB.setText(dbb.toString());
            add(printDB);
            printDB.setSize(300, 400);
            printDB.setEditable(false);
            printDB.setLocation(100, 100);
            printDB.setVisible(true);
            add(returnMenu);
            returnMenu.setVisible(true);
            returnMenu.setSize(200, 30);
            returnMenu.setLocation(500, 400);
            returnMenu.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                  returnMenu.setVisible(false);
                  printDB.setVisible(false);
                  welcome.setVisible(true);
                  addStudent.setVisible(true);
                  deleteStudent.setVisible(true);
                  deleteAll.setVisible(true);
                  printAll.setVisible(true);
               }
            });
         }
      });
      setVisible(true);
   }

   public static void main(String[] args) {
      Database student = new Database();
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // TODO Auto-generated method stub

   }

}

您正在向 addStudent ActionListener 中的提交按钮重复添加一个 ActionListener,这意味着当按下 addStudent 时,将添加越来越多的 ActionListener 以提交,这不是您想要的。

建议:

  • 只向您的 JButton 添加一次 ActionListener,而不是在可能被多次调用的其他事件侦听器中。考虑在 class 构造函数中添加所有 ActionListener。

附带建议:

  • 不要使用绝对定位和空布局。虽然空布局和 setBounds() 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,您在使用它们时就会 运行 遇到更严重的困难。它们不会在 GUI 调整大小时调整组件的大小,它们是皇家 来增强或维护的,当放置在滚动窗格中时它们会完全失败,当在所有平台或不同的屏幕分辨率上查看时它们看起来很糟糕从原来的。
  • 了解如何使用 CardLayout,然后使用 CardLayout 来让您干净、轻松地交换视图。

例如,

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class Database2 extends JPanel {
   // constants for the cards
   public static final String WELCOME = "welcome";
   public static final String ADD_STUDENT = "add student";
   public static final String DISPLAY_DATA = "display data";

   private JTextArea displayTextArea = new JTextArea(15, 20);
   private JTextField addStudentField = new JTextField(10);
   private CardLayout cardLayout = new CardLayout();
   private List<String> db = new ArrayList<>();

   public Database2() {
      // prepare JTextArea
      displayTextArea.setWrapStyleWord(true);
      displayTextArea.setLineWrap(true);
      displayTextArea.setFocusable(false);

      // set layout as CardLayout and add all JPanels with constants
      setLayout(cardLayout);
      add(createWelcomePanel(), WELCOME);
      add(createAddStudentPanel(), ADD_STUDENT);
      add(createDisplayDataPanel(), DISPLAY_DATA);
   }

   private JPanel createWelcomePanel() {
      ShowStudentPanelAction showStudentAction = new ShowStudentPanelAction("Add Student");
      DisplayDataAction displayDataAction = new DisplayDataAction("Display Data");
      JButton addStudentButton = new JButton(showStudentAction);
      JButton displayDataButton = new JButton(displayDataAction);

      JPanel topPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      topPanel.add(addStudentButton);
      topPanel.add(displayDataButton);
      topPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));

      JLabel welcomeLabel = new JLabel("Welcome", SwingConstants.CENTER);
      // make JLabel text bigger
      welcomeLabel.setFont(welcomeLabel.getFont().deriveFont(Font.BOLD, 42f));

      // and give it a border 30 points wide
      int ebGap = 30;
      welcomeLabel.setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap,
            ebGap, ebGap));

      JPanel welcomePanel = new JPanel(new BorderLayout());
      ebGap = 4;
      welcomePanel.setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
      welcomePanel.add(topPanel, BorderLayout.PAGE_START);
      welcomePanel.add(welcomeLabel, BorderLayout.CENTER);

      return welcomePanel;
   }

   private JPanel createAddStudentPanel() {
      AddStudentAction addStudentAction = new AddStudentAction("Add Student");
      addStudentField.setAction(addStudentAction);
      JPanel addStudentPanel = new JPanel();
      addStudentPanel.add(addStudentField);
      addStudentPanel.add(new JButton(addStudentAction)); 
      return addStudentPanel;
   }

   private JPanel createDisplayDataPanel() {
      JPanel displayDataPanel = new JPanel();
      JScrollPane scrollPane = new JScrollPane(displayTextArea);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      displayDataPanel.add(scrollPane);
      displayDataPanel.add(new JButton(new ReturnToWelcomeAction("Return")));
      return displayDataPanel;
   }

   private class ShowStudentPanelAction extends AbstractAction {
      public ShowStudentPanelAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardLayout.show(Database2.this, ADD_STUDENT);
         addStudentField.requestFocusInWindow();
         addStudentField.selectAll();
      }
   }

   private class DisplayDataAction extends AbstractAction {
      public DisplayDataAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         StringBuilder sb = new StringBuilder();
         for (String studentName : db) {
            sb.append(studentName + "\n");
         }
         displayTextArea.setText(sb.toString());
         cardLayout.show(Database2.this, DISPLAY_DATA);
      }
   }

   private class AddStudentAction extends AbstractAction {
      public AddStudentAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         String studentText = addStudentField.getText();
         db.add(studentText);
         cardLayout.show(Database2.this, WELCOME);
      }
   }

   private class ReturnToWelcomeAction extends AbstractAction {
      public ReturnToWelcomeAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         cardLayout.show(Database2.this, WELCOME);
      }
   }

   private class ExitAction extends AbstractAction {
      public ExitAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         Window window = SwingUtilities.getWindowAncestor(Database2.this);
         if (window != null) {
            window.dispose();
         }
      }
   }

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

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