JTable如何手动对齐、改变大小、添加滚动面板?

How to manually align, change size, and add scroll pane of JTable?

我正在 Netbeans 中创建一个 JTable,我遇到了三个关于结构的小问题。

  1. 我似乎无法将我的 table 对准我想要的方向(比如北、东、南或西),现在它在我的 JButton 上徘徊令人讨厌。
  2. 如果我更改变量,我为设置 JTable 的尺寸而编写的代码不会执行任何操作。
  3. 我编写的用于添加 JScrollPane 的代码在我 运行 时没有显示。

我知道如果你不能解决所有三个问题,但我想我会把它们全部放在一个而不是三个不同的问题中,所以任何解决问题的帮助都将不胜感激!

**另请注意,忽略 ActionListener 之后的所有内容。我最终将使代码读取文本文件并将该数据排序为 ArrayList。然后以某种方式进入 table 而不是我在此示例中如何手动设置它。

这是我的代码(问题区域在评论中以粗体大写字体标记):

主要:

package libraryinventory;
 
import javax.swing.JFrame;
import java.io.*;

public class MainClass {

    static String[] bookArray;
        
    public static void main(String[] args) {
        
        GUICommandFunctions guiDemo = new GUICommandFunctions();
        //What to do when window closes
        guiDemo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // size of window in pixels
        guiDemo.setSize(1000, 720); 
        //make window visible
        guiDemo.setVisible(true);
        
    }
        
}

图形界面 Class:

package libraryinventory;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.*;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import static javax.swing.Box.createHorizontalBox;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;


public class GUICommandFunctions extends JFrame {
    
    private JButton ButtonOne;
    private JTable jt;
    
    public GUICommandFunctions() { 
        
        this.setTitle("Library Inventory"); //Name of window
     
        JPanel panel = new JPanel();  
        this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

        ButtonOne = LibraryContentButton();
        panel.add(ButtonOne); //adding panel to JFrame

        
        String[] columns = {"Title", "Author/Language", "Publisher", "Page Count", "Version Number/Genre/Topic", "Part of a series/Illustrator"}; //columns of the JTable
        String[][] data = {{"The Keto Cookbook", "Chronicle Books", "304", "English", "Keto Cooking", "null"}, //data under the columns
                           {"The Hitchhiker's Guide to the Galaxy", "Del Rey", "224", "Douglas Adams", "Fantasy", "Y"}      
        };
        
        jt = new JTable(data, columns){ //Makes it so can't edit data inside table once ran
            public boolean isCellEditable(int data, int columns) {
                    return false;
            }
        };
        
        jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
        jt.setFillsViewportHeight(true); //Set visible
        jt.setVerticalAlignment(JTable.BOTTOM_ALIGNMENT); //**HERE IS PROBLEM #1**
        
        JScrollPane jps = new JScrollPane(jt); //add scroll **HERE IS PROBLEM #3**
        add(jps);
        
    }
    
        private JButton LibraryContentButton() { //
            JButton content = new JButton("Click to view all content");
            content.setFocusable(false);
            content.setBackground(Color.DARK_GRAY);
            content.setForeground(Color.WHITE);
            content.setFont(new Font("Arial", Font.BOLD, 20));
            content.setToolTipText("Shows content of the entire library in a neatly ordered JTable");
            content.setMargin(new Insets(10, 10, 10, 10));
            content.setPreferredSize(new Dimension(300, 75));

            
            
            content.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(rootPane, "Eventually will make this button load up the JTable");              
                }
            });
            return content;
     
        }

    static {
    
        int arrayCount;
      
        FileReader fr = null;
        
        try {
            fr = new FileReader("C:\Users\Mark Case\Documents\NetBeansProjects\LibraryInventory\src\libraryinventory\library.txt"); //Reads in text file
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        BufferedReader reader = new BufferedReader(fr);       
        ArrayList<String> str = new ArrayList<>();
        String line = "";
        arrayCount = 0;
        try {
            while((line=reader.readLine())!=null) {
                str.add(line);
                arrayCount = arrayCount + 1;
                
            }
        } catch (IOException ex) {
            Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Here we would actually set the type to what the user wants (note: Set it to a "0" if the user wants all Books)
        String selType = "2";  
        
        // Call method to select Books by category type
        String methodResult = SelectType(str, arrayCount, selType);
        
    }  

    private static String SelectType (ArrayList<String> str, int arrayCount, String selType) {
        for (int i = 1; i < arrayCount; i++) {
           
            String buffer = str.get(i);
            String bookCat = buffer.substring(0,1);
            
            // Print books by Category - "0" type means print all Books
            if (selType.equals(bookCat)) {
                System.out.println(buffer);
            }          
            else if (selType.equals("0")) {
                System.out.println(buffer);
            }
        }
        return "0";   
    }



}

那么,让我们快速浏览一下构造函数...

public GUICommandFunctions() { 
    //...
    JPanel panel = new JPanel();  
    this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

    ButtonOne = LibraryContentButton();
    panel.add(ButtonOne); //adding panel to JFrame
    //...
    jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
    jt.setFillsViewportHeight(true); //Set visible
    jt.setVerticalAlignment(JTable.BOTTOM_ALIGNMENT); //**HERE IS PROBLEM #1**
    
    JScrollPane jps = new JScrollPane(jt); //add scroll **HERE IS PROBLEM #3**
    add(jps);
}

您将 panel 添加到 CENTER。由于您直接从 JFrame 扩展,布局已经 BorderLayout,所以这很好。

但随后您使用 add(jps); 添加 jps,这会将组件添加到布局默认位置,在 BorderLayout 的情况下是 CENTER。这是有问题的,因为 BorderLayout 只允许在每个位置管理一个组件,这解释了为什么 setPreferredScrollableViewportSize 不工作,因为 BorderLayout 忽略了它,并且使组件填充 CENTER

中可用的 space

所以,我修改了你的代码。首先,我从 JPanel 扩展而不是 JFrame。通常不鼓励直接从 JFrame 扩展,您不会向 class 添加任何新功能,将自己锁定在一个用例中,这通常只会让您生活更加困难。

其次,我把JScrollPane放在了BorderLayout

SOUTH位置

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new GUICommandFunctionsPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class GUICommandFunctionsPane extends JPanel {

        private JButton ButtonOne;
        private JTable jt;

        public GUICommandFunctionsPane() {
            setLayout(new BorderLayout());
            JPanel panel = new JPanel();
            this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

            ButtonOne = LibraryContentButton();
            panel.add(ButtonOne); //adding panel to JFrame

            String[] columns = {"Title", "Author/Language", "Publisher", "Page Count", "Version Number/Genre/Topic", "Part of a series/Illustrator"}; //columns of the JTable
            String[][] data = {{"The Keto Cookbook", "Chronicle Books", "304", "English", "Keto Cooking", "null"}, //data under the columns
            {"The Hitchhiker's Guide to the Galaxy", "Del Rey", "224", "Douglas Adams", "Fantasy", "Y"}
            };

            jt = new JTable(data, columns) { //Makes it so can't edit data inside table once ran
                public boolean isCellEditable(int data, int columns) {
                    return false;
                }
            };

            jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
            jt.setFillsViewportHeight(true); //Set visible

            JScrollPane jps = new JScrollPane(jt);
            add(jps, BorderLayout.SOUTH);

        }

        private JButton LibraryContentButton() { //
            JButton content = new JButton("Click to view all content");
            content.setFocusable(false);
            content.setBackground(Color.DARK_GRAY);
            content.setForeground(Color.WHITE);
            content.setFont(new Font("Arial", Font.BOLD, 20));
            content.setToolTipText("Shows content of the entire library in a neatly ordered JTable");
            content.setMargin(new Insets(10, 10, 10, 10));
            content.setPreferredSize(new Dimension(300, 75));

            content.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(GUICommandFunctionsPane.this, "Eventually will make this button load up the JTable");
                }
            });
            return content;

        }

//        static {
//
//            int arrayCount;
//
//            FileReader fr = null;
//
//            try {
//                fr = new FileReader("C:\Users\Mark Case\Documents\NetBeansProjects\LibraryInventory\src\libraryinventory\library.txt"); //Reads in text file
//            } catch (FileNotFoundException ex) {
//                Logger.getLogger(GUICommandFunctionsPane.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            BufferedReader reader = new BufferedReader(fr);
//            ArrayList<String> str = new ArrayList<>();
//            String line = "";
//            arrayCount = 0;
//            try {
//                while ((line = reader.readLine()) != null) {
//                    str.add(line);
//                    arrayCount = arrayCount + 1;
//
//                }
//            } catch (IOException ex) {
//                Logger.getLogger(GUICommandFunctionsPane.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            // Here we would actually set the type to what the user wants (note: Set it to a "0" if the user wants all Books)
//            String selType = "2";
//
//            // Call method to select Books by category type
//            String methodResult = SelectType(str, arrayCount, selType);
//
//        }
//
//        private static String SelectType(ArrayList<String> str, int arrayCount, String selType) {
//            for (int i = 1; i < arrayCount; i++) {
//
//                String buffer = str.get(i);
//                String bookCat = buffer.substring(0, 1);
//
//                // Print books by Category - "0" type means print all Books
//                if (selType.equals(bookCat)) {
//                    System.out.println(buffer);
//                } else if (selType.equals("0")) {
//                    System.out.println(buffer);
//                }
//            }
//            return "0";
//        }
    }
}

哦,我不鼓励你以这种方式使用 static 初始化程序,相反,这要么需要进入构造函数,要么你应该使用某种形式的依赖注入将信息传递给class