Java JTable 列 header 使用 DefaultModel 未显示
Java JTable column header not showing using DefaultModel
正如标题所说,听众的名字没有出现。我尝试了很多选项,比如使用 JScrollPane。并在此论坛上提供了许多指南,但没有帮助。我真的很想自己解决问题,但我已经尝试了一切,但别无选择。
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.ScrollPane;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.awt.event.ActionEvent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.JScrollPane;
import javax.swing.JScrollBar;
public class Adminpage extends JPanel {
private JFrame frame;
static String ID[]={"name","Username","Password"};
static DefaultTableModel model;
private JTextField NametextField;
private JTextField UsertextField;
private JTextField PasstextField;
private JTable table;
private JScrollPane scroll;
/**
* Create the panel.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 497, 545);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel lblAdminstratorPortal = new JLabel("Adminstrator Portal");
lblAdminstratorPortal.setFont(new Font("Tahoma", Font.BOLD, 20));
lblAdminstratorPortal.setBounds(109, 26, 218, 25);
frame.getContentPane().add(lblAdminstratorPortal);
JButton btnNewButton = new JButton("Add Librarian");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//model= (DefaultTableModel)table.getModel();
//model.addColumn("name");
//model.addColumn("Username");
//model.addColumn("Password");
model.addRow(new Object[]{NametextField.getText(),UsertextField.getText(),PasstextField.getText()});
}
});
btnNewButton.setBounds(10, 62, 108, 35);
frame.getContentPane().add(btnNewButton);
JButton btnDelete = new JButton("Delete");
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
btnDelete.setBounds(130, 62, 108, 35);
frame.getContentPane().add(btnDelete);
JButton btnViewLibrarian = new JButton("View Librarian");
btnViewLibrarian.setBounds(245, 62, 108, 35);
frame.getContentPane().add(btnViewLibrarian);
JButton btnLogout = new JButton("Logout");
btnLogout.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.dispose();
}
});
btnLogout.setBounds(363, 62, 108, 35);
frame.getContentPane().add(btnLogout);
//model= (DefaultTableModel)table.getModel();
JLabel lblName = new JLabel("Name");
lblName.setBounds(21, 144, 60, 14);
frame.getContentPane().add(lblName);
JLabel lblUsername = new JLabel("Username");
lblUsername.setBounds(21, 195, 60, 14);
frame.getContentPane().add(lblUsername);
JLabel lblPassword = new JLabel("Password");
lblPassword.setBounds(21, 250, 60, 14);
frame.getContentPane().add(lblPassword);
NametextField = new JTextField();
NametextField.setBounds(119, 141, 119, 20);
frame.getContentPane().add(NametextField);
NametextField.setColumns(10);
UsertextField = new JTextField();
UsertextField.setColumns(10);
UsertextField.setBounds(119, 192, 119, 20);
frame.getContentPane().add(UsertextField);
PasstextField = new JTextField();
PasstextField.setColumns(10);
PasstextField.setBounds(119, 247, 119, 20);
frame.getContentPane().add(PasstextField);
table = new JTable();
table.setBounds(10, 304, 461, 189);
frame.getContentPane().add(table);
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Adminpage() {
database();
setLayout(null);
initialize();
model= (DefaultTableModel)table.getModel();
model.addColumn("name");
model.addColumn("Username");
model.addColumn("Password");
}
public void database(){
try {
Class.forName("sun.jdbc.odbc.JdbsOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:Games");
Statement st = con.createStatement();
String getquery = ("Select* from Games");
ResultSet rs= st.executeQuery(getquery);
while(rs.next()){
System.out.println(rs.getString(2));
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
您正在将 JTable 直接添加到 GUI。相反,是的,您需要将 JTable 嵌入到 JScrollPane 的视口中,然后将 JScrollPane 添加到 GUI。
例如:
table = new JTable();
JScrollPane scrollPane = new JScrollPane(table);
// table.setBounds(10, 304, 461, 189);
scrollPane.setBounds(10, 304, 461, 189); // This is bad, but will leave for now
// frame.getContentPane().add(table);
frame.getContentPane().add(scrollPane);
此外,您使用空布局和绝对定位会损害您的 GUI,因为这会干扰组件充分正确地显示自身以达到其首选大小的能力。更好的方法是学习和使用布局管理器。
例如,当我运行你的程序在我的平台上时,我看到:
请注意,由于不允许按钮达到其首选大小,因此按钮无法显示其完整文本。
例如,将 BoxLayout 与一些嵌套的 JPanel 一起使用,其中一个使用 GridLayout(1, 0, 5, 0)
作为一行,列数可变,组件之间有 5 磅的水平间距,另一个使用 GridBagLayout 的嵌套 JPanel,用于放置JTextFields 和 JLabel,以及一些 "wrapper" JPanel 使用默认的 FlowLayout 将组件置于其中...
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class AdminPage2 extends JPanel {
private static final long serialVersionUID = 1L;
public static final String TITLE = "Administrator Portal";
private static final Font TITLE_FONT = new Font("Tahoma", Font.BOLD, 20);
private static final String[] COL_NAMES = {"Name", "User Name", "Password"};
private int txtFieldCols = 20;
private JTextField nameField = new JTextField(txtFieldCols);
private JTextField userNameField = new JTextField(txtFieldCols);
private JPasswordField passwordField = new JPasswordField(txtFieldCols);
private DefaultTableModel tableModel = new DefaultTableModel(COL_NAMES, 0);
private JTable table = new JTable(tableModel);
private JScrollPane tableScrollPane = new JScrollPane(table);
public AdminPage2() {
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(TITLE_FONT);
JPanel titlePanel = new JPanel();
titlePanel.add(titleLabel);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
// of course you'd add ActionListeners or Actions to your buttons
buttonPanel.add(new JButton("Add Library"));
buttonPanel.add(new JButton("Delete"));
buttonPanel.add(new JButton("View Library"));
buttonPanel.add(new JButton("Logout"));
JPanel textFieldPanel = new JPanel(new GridBagLayout());
textFieldPanel.add(new JLabel("Name:"), createGbc(0, 0));
textFieldPanel.add(nameField, createGbc(1, 0));
textFieldPanel.add(new JLabel("User Name:"), createGbc(0, 1));
textFieldPanel.add(userNameField, createGbc(1, 1));
textFieldPanel.add(new JLabel("Password:"), createGbc(0, 2));
textFieldPanel.add(passwordField, createGbc(1, 2));
JPanel wrapTfPanel = new JPanel();
wrapTfPanel.add(textFieldPanel);
Dimension scrollPanePrefSz = tableScrollPane.getPreferredSize();
int w = scrollPanePrefSz.width;
int h = scrollPanePrefSz.height / 2;
scrollPanePrefSz = new Dimension(w, h);
tableScrollPane.setPreferredSize(scrollPanePrefSz);
// put together main JPanel components
int ebGap = 4;
setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(Box.createVerticalStrut(5));
add(titlePanel);
add(Box.createVerticalStrut(5));
add(buttonPanel);
add(Box.createVerticalStrut(5));
add(wrapTfPanel);
add(Box.createVerticalStrut(5));
add(tableScrollPane);
}
// create constraints to use when adding component to GridBagLayout
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = x == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
gbc.fill = GridBagConstraints.HORIZONTAL;
int in = 10;
int leftIn = x == 0 ? 4 * in : in;
gbc.insets = new Insets(in, leftIn, in, in);
return gbc;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
AdminPage2 mainPanel = new AdminPage2();
JFrame frame = new JFrame("Administrator Page");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
显示为:
关于您的问题:
but new question why give the scrollpane a bound instead of the table itself
JScrollPane 在其中包含 JTable,因此如果您使用空布局(您不应该这样做),并且您要将这个包含 JTable 的 JScrollPane 添加到GUI,你必须设置它的边界。 好得多 不过,使用我上面概述的布局管理器会更好。它使得以后修改 GUI 和现在调试它变得容易得多。
and why adding the scrollpane into the panel instead of the table.
因为这就是 JScrollPanes 的工作方式。它们不向组件添加滚动条,而是将组件本身(此处为 JTable)嵌套在 JScrollPane 的视口中。请阅读 JScrollPane Tutorial(参见 link)以查看详细信息。
关于布局管理器功能的进一步说明。假设您想添加一个新的 JLabel / JTextField 组合,一个接受密码提示的组合,并假设 JTextField 的名称是 passwordHint
。如果您使用空布局和绝对定位,则必须设置新的 JLabel 和 JTextField 的边界,但您还必须 更改 以下所有组件的边界和在它的右边,并且必须手动重新设置 GUI 的大小。如果您的 GUI 非常复杂,这可能会导致错误和很多挫折。
但是,如果您使用上面的布局管理器,您需要做的就是向 textFieldPanel JPanel 创建代码添加两行代码,如下所示,并带有明显的注释:
// original textFieldPanel creational code
JPanel textFieldPanel = new JPanel(new GridBagLayout());
textFieldPanel.add(new JLabel("Name:"), createGbc(0, 0));
textFieldPanel.add(nameField, createGbc(1, 0));
textFieldPanel.add(new JLabel("User Name:"), createGbc(0, 1));
textFieldPanel.add(userNameField, createGbc(1, 1));
textFieldPanel.add(new JLabel("Password:"), createGbc(0, 2));
textFieldPanel.add(passwordField, createGbc(1, 2));
// !! ****** these lines added ******
textFieldPanel.add(new JLabel("Password Hint:"), createGbc(0, 3));
textFieldPanel.add(passwordHint, createGbc(1, 3));
这样可以完美放置新组件,而不会对旧组件产生不利影响:
正如标题所说,听众的名字没有出现。我尝试了很多选项,比如使用 JScrollPane。并在此论坛上提供了许多指南,但没有帮助。我真的很想自己解决问题,但我已经尝试了一切,但别无选择。
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.Font;
import java.awt.ScrollPane;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.awt.event.ActionEvent;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.JScrollPane;
import javax.swing.JScrollBar;
public class Adminpage extends JPanel {
private JFrame frame;
static String ID[]={"name","Username","Password"};
static DefaultTableModel model;
private JTextField NametextField;
private JTextField UsertextField;
private JTextField PasstextField;
private JTable table;
private JScrollPane scroll;
/**
* Create the panel.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 497, 545);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JLabel lblAdminstratorPortal = new JLabel("Adminstrator Portal");
lblAdminstratorPortal.setFont(new Font("Tahoma", Font.BOLD, 20));
lblAdminstratorPortal.setBounds(109, 26, 218, 25);
frame.getContentPane().add(lblAdminstratorPortal);
JButton btnNewButton = new JButton("Add Librarian");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//model= (DefaultTableModel)table.getModel();
//model.addColumn("name");
//model.addColumn("Username");
//model.addColumn("Password");
model.addRow(new Object[]{NametextField.getText(),UsertextField.getText(),PasstextField.getText()});
}
});
btnNewButton.setBounds(10, 62, 108, 35);
frame.getContentPane().add(btnNewButton);
JButton btnDelete = new JButton("Delete");
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
btnDelete.setBounds(130, 62, 108, 35);
frame.getContentPane().add(btnDelete);
JButton btnViewLibrarian = new JButton("View Librarian");
btnViewLibrarian.setBounds(245, 62, 108, 35);
frame.getContentPane().add(btnViewLibrarian);
JButton btnLogout = new JButton("Logout");
btnLogout.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.dispose();
}
});
btnLogout.setBounds(363, 62, 108, 35);
frame.getContentPane().add(btnLogout);
//model= (DefaultTableModel)table.getModel();
JLabel lblName = new JLabel("Name");
lblName.setBounds(21, 144, 60, 14);
frame.getContentPane().add(lblName);
JLabel lblUsername = new JLabel("Username");
lblUsername.setBounds(21, 195, 60, 14);
frame.getContentPane().add(lblUsername);
JLabel lblPassword = new JLabel("Password");
lblPassword.setBounds(21, 250, 60, 14);
frame.getContentPane().add(lblPassword);
NametextField = new JTextField();
NametextField.setBounds(119, 141, 119, 20);
frame.getContentPane().add(NametextField);
NametextField.setColumns(10);
UsertextField = new JTextField();
UsertextField.setColumns(10);
UsertextField.setBounds(119, 192, 119, 20);
frame.getContentPane().add(UsertextField);
PasstextField = new JTextField();
PasstextField.setColumns(10);
PasstextField.setBounds(119, 247, 119, 20);
frame.getContentPane().add(PasstextField);
table = new JTable();
table.setBounds(10, 304, 461, 189);
frame.getContentPane().add(table);
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Adminpage() {
database();
setLayout(null);
initialize();
model= (DefaultTableModel)table.getModel();
model.addColumn("name");
model.addColumn("Username");
model.addColumn("Password");
}
public void database(){
try {
Class.forName("sun.jdbc.odbc.JdbsOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:Games");
Statement st = con.createStatement();
String getquery = ("Select* from Games");
ResultSet rs= st.executeQuery(getquery);
while(rs.next()){
System.out.println(rs.getString(2));
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
您正在将 JTable 直接添加到 GUI。相反,是的,您需要将 JTable 嵌入到 JScrollPane 的视口中,然后将 JScrollPane 添加到 GUI。
例如:
table = new JTable();
JScrollPane scrollPane = new JScrollPane(table);
// table.setBounds(10, 304, 461, 189);
scrollPane.setBounds(10, 304, 461, 189); // This is bad, but will leave for now
// frame.getContentPane().add(table);
frame.getContentPane().add(scrollPane);
此外,您使用空布局和绝对定位会损害您的 GUI,因为这会干扰组件充分正确地显示自身以达到其首选大小的能力。更好的方法是学习和使用布局管理器。
例如,当我运行你的程序在我的平台上时,我看到:
请注意,由于不允许按钮达到其首选大小,因此按钮无法显示其完整文本。
例如,将 BoxLayout 与一些嵌套的 JPanel 一起使用,其中一个使用 GridLayout(1, 0, 5, 0)
作为一行,列数可变,组件之间有 5 磅的水平间距,另一个使用 GridBagLayout 的嵌套 JPanel,用于放置JTextFields 和 JLabel,以及一些 "wrapper" JPanel 使用默认的 FlowLayout 将组件置于其中...
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class AdminPage2 extends JPanel {
private static final long serialVersionUID = 1L;
public static final String TITLE = "Administrator Portal";
private static final Font TITLE_FONT = new Font("Tahoma", Font.BOLD, 20);
private static final String[] COL_NAMES = {"Name", "User Name", "Password"};
private int txtFieldCols = 20;
private JTextField nameField = new JTextField(txtFieldCols);
private JTextField userNameField = new JTextField(txtFieldCols);
private JPasswordField passwordField = new JPasswordField(txtFieldCols);
private DefaultTableModel tableModel = new DefaultTableModel(COL_NAMES, 0);
private JTable table = new JTable(tableModel);
private JScrollPane tableScrollPane = new JScrollPane(table);
public AdminPage2() {
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(TITLE_FONT);
JPanel titlePanel = new JPanel();
titlePanel.add(titleLabel);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
// of course you'd add ActionListeners or Actions to your buttons
buttonPanel.add(new JButton("Add Library"));
buttonPanel.add(new JButton("Delete"));
buttonPanel.add(new JButton("View Library"));
buttonPanel.add(new JButton("Logout"));
JPanel textFieldPanel = new JPanel(new GridBagLayout());
textFieldPanel.add(new JLabel("Name:"), createGbc(0, 0));
textFieldPanel.add(nameField, createGbc(1, 0));
textFieldPanel.add(new JLabel("User Name:"), createGbc(0, 1));
textFieldPanel.add(userNameField, createGbc(1, 1));
textFieldPanel.add(new JLabel("Password:"), createGbc(0, 2));
textFieldPanel.add(passwordField, createGbc(1, 2));
JPanel wrapTfPanel = new JPanel();
wrapTfPanel.add(textFieldPanel);
Dimension scrollPanePrefSz = tableScrollPane.getPreferredSize();
int w = scrollPanePrefSz.width;
int h = scrollPanePrefSz.height / 2;
scrollPanePrefSz = new Dimension(w, h);
tableScrollPane.setPreferredSize(scrollPanePrefSz);
// put together main JPanel components
int ebGap = 4;
setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(Box.createVerticalStrut(5));
add(titlePanel);
add(Box.createVerticalStrut(5));
add(buttonPanel);
add(Box.createVerticalStrut(5));
add(wrapTfPanel);
add(Box.createVerticalStrut(5));
add(tableScrollPane);
}
// create constraints to use when adding component to GridBagLayout
private GridBagConstraints createGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = x == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
gbc.fill = GridBagConstraints.HORIZONTAL;
int in = 10;
int leftIn = x == 0 ? 4 * in : in;
gbc.insets = new Insets(in, leftIn, in, in);
return gbc;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
AdminPage2 mainPanel = new AdminPage2();
JFrame frame = new JFrame("Administrator Page");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
显示为:
关于您的问题:
but new question why give the scrollpane a bound instead of the table itself
JScrollPane 在其中包含 JTable,因此如果您使用空布局(您不应该这样做),并且您要将这个包含 JTable 的 JScrollPane 添加到GUI,你必须设置它的边界。 好得多 不过,使用我上面概述的布局管理器会更好。它使得以后修改 GUI 和现在调试它变得容易得多。
and why adding the scrollpane into the panel instead of the table.
因为这就是 JScrollPanes 的工作方式。它们不向组件添加滚动条,而是将组件本身(此处为 JTable)嵌套在 JScrollPane 的视口中。请阅读 JScrollPane Tutorial(参见 link)以查看详细信息。
关于布局管理器功能的进一步说明。假设您想添加一个新的 JLabel / JTextField 组合,一个接受密码提示的组合,并假设 JTextField 的名称是 passwordHint
。如果您使用空布局和绝对定位,则必须设置新的 JLabel 和 JTextField 的边界,但您还必须 更改 以下所有组件的边界和在它的右边,并且必须手动重新设置 GUI 的大小。如果您的 GUI 非常复杂,这可能会导致错误和很多挫折。
但是,如果您使用上面的布局管理器,您需要做的就是向 textFieldPanel JPanel 创建代码添加两行代码,如下所示,并带有明显的注释:
// original textFieldPanel creational code
JPanel textFieldPanel = new JPanel(new GridBagLayout());
textFieldPanel.add(new JLabel("Name:"), createGbc(0, 0));
textFieldPanel.add(nameField, createGbc(1, 0));
textFieldPanel.add(new JLabel("User Name:"), createGbc(0, 1));
textFieldPanel.add(userNameField, createGbc(1, 1));
textFieldPanel.add(new JLabel("Password:"), createGbc(0, 2));
textFieldPanel.add(passwordField, createGbc(1, 2));
// !! ****** these lines added ******
textFieldPanel.add(new JLabel("Password Hint:"), createGbc(0, 3));
textFieldPanel.add(passwordHint, createGbc(1, 3));
这样可以完美放置新组件,而不会对旧组件产生不利影响: