0

Hello and good morning,

I am requesting help with styling a JTable appropriately. I am very new to Java GUIs and thus am having a hell of a time trying to get this to work appropriately.

My objectives are to try and recreate the Jeopardy scoreboard as closely as possible.

Right now, I am trying to accomplish 3 things:

  1. Trying to center all data (including headers) in the table
  2. Trying to change the header font color and background
  3. Trying to extend the table to fit the full frame of the JPanel it is in

My code is listed below. Any help, feedback, or guidance would be appreciated.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package QuestionBoard;

import java.awt.*;
import javax.swing.table.*;
import javax.swing.*;

/**
 *
 * @author Kelly
 */


public class WiP_QuestionBoard extends javax.swing.JFrame {

    /**
     * Creates new form frameQuestionBoard
     */

    public WiP_QuestionBoard() {
        initComponents();

        //Trying to center components
        DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
        centerRenderer.setHorizontalAlignment( SwingConstants.CENTER );
        tblQuestions.setDefaultRenderer(Integer.class, centerRenderer);

        //Trying to change header settings
        JTableHeader Theader = tblQuestions.getTableHeader();
        Theader.setBackground(Color.BLUE);
       // Theader.setFontColor???(Color.YELLOW);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        panelQuestions = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        tblQuestions = new javax.swing.JTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        tblQuestions.setBackground(new java.awt.Color(51, 102, 255));
        tblQuestions.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0), 2));
        tblQuestions.setFont(new java.awt.Font("Tahoma", 1, 13)); // NOI18N
        tblQuestions.setForeground(new java.awt.Color(204, 153, 0));
        tblQuestions.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"200", "200", "200", "200", "200", "200"},
                {"400", "400", "400", "400", "400", "400"},
                {"600", "600", "600", "600", "600", "600"},
                {"800", "800", "800", "800", "800", "800"},
                {"1000", "1000", "1000", "1000", "1000", "1000"}
            },
            new String [] {
                "Category 1", "Category 2", "Category 3", "Category 4", "Category 5", "Category 6"
            }
        ));
        tblQuestions.setDoubleBuffered(true);
        tblQuestions.setGridColor(new java.awt.Color(0, 0, 0));
        tblQuestions.setRowMargin(2);
        tblQuestions.setSelectionBackground(new java.awt.Color(0, 51, 255));
        tblQuestions.setSelectionForeground(new java.awt.Color(204, 204, 0));
        tblQuestions.getTableHeader().setReorderingAllowed(false);
        jScrollPane1.setViewportView(tblQuestions);

        javax.swing.GroupLayout panelQuestionsLayout = new javax.swing.GroupLayout(panelQuestions);
        panelQuestions.setLayout(panelQuestionsLayout);
        panelQuestionsLayout.setHorizontalGroup(
            panelQuestionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 675, Short.MAX_VALUE)
        );
        panelQuestionsLayout.setVerticalGroup(
            panelQuestionsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(panelQuestionsLayout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 118, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 313, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(panelQuestions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(panelQuestions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(WiP_QuestionBoard.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(WiP_QuestionBoard.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(WiP_QuestionBoard.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(WiP_QuestionBoard.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new WiP_QuestionBoard().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPanel panelQuestions;
    private javax.swing.JTable tblQuestions;
    // End of variables declaration                   
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
artemis
  • 6,857
  • 11
  • 46
  • 99

2 Answers2

2

I am very new to Java GUIs

I would suggest you don't use the IDE to generate your code. You spend time learning the IDE not Swing. Use the IDE to help compile, debug etc.

1.Trying to center all data (including headers) in the table

tblQuestions.setDefaultRenderer(Integer.class, centerRenderer);

All the data in the TableModel is String data not Integer data. If you want Integer data then you need to add Integer objects to the model.

However, even that is not enough. You now need to tell the table what type of data is in each column by overriding the getColumnClass(...) method of the TableModel to return Integer.class.

However the easiest solution as your code stands it so use:

tblQuestions.setDefaultRenderer(Object.class, centerRenderer);

because the default getColumnClass(...) implementation just returns Object.class for all columns.

For the header you need to access the default renderer to change the alignment:

DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)tblQuestions.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(SwingConstants.CENTER);

2.Trying to change the header font color and background

That is an issue with the Nimbus LAF. The default renderer appears to be ignoring the setBackground() method. Not sure how to fix that.

Maybe this posting will help: Nimbus - override color for TableHeader

3.Trying to extend the table to fit the full frame of the JPanel it is in

The preferred size of the table is based on the height of each row in the table. This height does not change dynamically. If you want the height of each row to be larger then use:

table.setRowHeight(32);

Also, following up on my initial comment I would not use the IDE to generate the layout code. The GroupLayout is overly complex. I would simply take advantage of the default BorderLayout of the frame to create the GUI with code something like:

JTable table = new JTable(...);
frame.add(new JScrollPane( table ), BorderLayout.PAGE_START);
frame.pack();
frame.setVisible();

With simple layout code like that the table will be displayed at the top of the frame at its preferred size. As the width of the frame is changed the columns will resize. Nothing will happen if the frame height is changed, so you may want to make the frame non-resizable to make sure the table always fills the frame.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • thanks a lot for your detailed post. I know it can be frustrating dealing with a newbie, but I appreciate the time you put into laying out all of those steps for me. I've been reading what you wrote and then looking through documentation to try and learn more, so i certainly appreciate it. Thank you. I will try implementing shortly (finally getting some lunch :)) – artemis Jul 15 '18 at 18:18
1

Here is the code that will fulfill your requirements, change your constructor to the following (there are some comments to help you out):

public WiP_QuestionBoard() {
        initComponents();

        //Makes the table header text centered.
        ((DefaultTableCellRenderer) tblQuestions.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(SwingConstants.CENTER);

        //This will center the text in table (header not included).
        DefaultTableCellRenderer centerAlign = new DefaultTableCellRenderer();

        //center columns.
        centerAlign.setHorizontalAlignment(SwingConstants.CENTER);
        for (int i = 0; i < tblQuestions.getColumnCount(); i++) {
            tblQuestions.getColumnModel().getColumn(i).setCellRenderer(centerAlign);
        }

        //makes the table span the panel it is in.
        tblQuestions.setPreferredSize(this.panelQuestions.getPreferredSize());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

enter image description here

M. Al Jumaily
  • 731
  • 1
  • 6
  • 21
  • you are a lifesaver! Thank you so much for providing some quick, easy ways to complete my objectives. However, I think I worded something incorrectly, and I am trying to watch a YT Video to implement a fix and I can't seem to understand where the problem is. For example, in your picture, i would like the table (and the rows / columns, etc) to span the entire width of that panel. Is there a way to do that? Or am I stuck with the small table? Again - thank you so much. Your solution worked beautifully. – artemis Jul 15 '18 at 18:22
  • They would span if you make the size of the JFrame larger (i.e. maximize the window). If you would like, you can add this in the the for loop `tblQuestions.getColumnModel().getColumn(i).setMinWidth(200);` and add the following `if (tblQuestions.getPreferredSize().width < panelQuestions.getPreferredSize().width) { tblQuestions.setPreferredSize(panelQuestions.getPreferredSize()); } else { panelQuestions.setPreferredSize(tblQuestions.getPreferredSize()); }` instead of the `tblQuestions.setPreferredSize(this.panelQuestions.getPreferredSize());` – M. Al Jumaily Jul 15 '18 at 18:41
  • Also, add `pack();` before you end your constructor, I forgot that. – M. Al Jumaily Jul 15 '18 at 18:47
  • Thank you so very much for all of your help. By chance, are you an instructor? I truly appreciate your help. – artemis Jul 15 '18 at 19:19
  • You are very welcome! I wish I was an instructor, I just finished my undergrad a couple of months ago. – M. Al Jumaily Jul 15 '18 at 19:26
  • That is amazing. I am so appreciative of learning from you. By chance, that did not fix the last issue. Do you have any other resources I could maybe look at / time for me to prod you with questions? – artemis Jul 17 '18 at 01:40
  • @bm0r3son, `i would like the table (and the rows / columns, etc) to span the entire width of that panel` - I don't understand the question. In the code you posted the table and columns widths do automatically change as the width of the frame is changed. In any case if it doesn't work as you expect you should NOT be using setPreferredSize(). You SHOULD be using an appropriate layout manager as has already been suggested. – camickr Jul 17 '18 at 02:44