user3500147
user3500147

Reputation: 125

Java JTable column header not showing using DefaultModel

Like the title said, the hearder name is just not showing up. i tried many options like using a JScrollPane. and fallowed many guide on this forum but no help. I really wanted to get resolve problem by myself but i have tried everything and out of option.

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

        }
    }
}

Upvotes: 3

Views: 1226

Answers (1)

You're adding the JTable directly to the GUI. Instead, yes you need to embed the JTable into the viewport of a JScrollPane and then add the JScrollPane to the GUI.

For example:

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

Also, you're harming your GUI by using null layouts and absolute positioning, as this can interfere with a component's ability to show itself fully and correctly, to achieve its own preferred size. Much better is to learn and use the layout managers.

For instance, when I run your program on my platform, I see:

enter image description here

Note how the buttons do not show their full texts due to their not being allowed to achieve their preferred sizes.

For example, using BoxLayout with some nested JPanels, one using GridLayout(1, 0, 5, 0) for one row, variable number of columns, and a 5 point horizontal gap between components, and another nested JPanel using GridBagLayout, for placement of JTextFields and JLabels, and some "wrapper" JPanels using default FlowLayout to center components within them...

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

}

Which displays as:

enter image description here

Regarding your questions:

but new question why give the scrollpane a bound instead of the table itself

The JScrollPane holds the JTable within it, and so if you use null layouts (which you shouldn't), and you're adding this JTable-containing JScrollPane to the GUI, you must set its bounds. Much better though is to use layout managers as I've outlined above. It makes it much easier to modify the GUI later and to debug it now.

and why adding the scrollpane into the panel instead of the table.

Because that's how JScrollPanes work. They don't add scrollbars to a component but rather nest the component itself, here the JTable, within the JScrollPane's viewport. Please read the JScrollPane Tutorial (see link) to see the details on this.


A further note on the power of layout managers. Say you want to add a new JLabel / JTextField combination, one that accepts a password hint, and say the JTextField's name is passwordHint. If you were using null layouts and absolute positioning, you'd have to set the bounds of your new JLabel and JTextField, but you'd also have to change the bounds of all components below and to the right of it, and would have to re-set the size of the GUI manually. If your GUI is very complex, this can lead to bugs and a lot of frustration.

If you used the layout managers above however, all you'd need to do would be to add two lines of code to the textFieldPanel JPanel creational code as shown below with the obvious comments:

// 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));

This results in a perfect placement of the new components without adversely affecting the old:

enter image description here

Upvotes: 5

Related Questions