JTable grid lines disappear unexpectedly

2.2k views Asked by At

I have an S (very S) SCCE which illustrates the problem: there is a JTable and a JTree both contained in a JPanel with a BorderLayout. Most of the grid lines in the JTable show, but not the one at the left, and not the one at the top. Have tried experimenting with borders, with placing the JTable on its own dedicated JPanel, etc.

I have gleaned from the experts that it is a bad idea to call any of the setXXXSize methods, so have not resorted to setPreferredSize, for example. In the SSCCE you can swap the tree and table positions round by uncommenting the "EAST" line)

How do I make these obscured/missing gridlines reappear?

(NB the idea is eventually for the table to grow/shrink dynamically with the JTree, so that there are always the same number of rows in the table and the tree... hence the desire to contain both components on the same JPanel).

SSCCE:

import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
import javax.swing.border.LineBorder;


public class TableGridProb {
    public static void main( String[] args ) throws InterruptedException, InvocationTargetException{

        EventQueue.invokeAndWait( new Runnable(){

            @Override
      public void run() {
          JFrame frame = new JFrame( "Table Grid Prob" );
          frame.setSize( 800, 300 );
          frame.setVisible( true );
          JSplitPane split_pane = new JSplitPane();
          JScrollPane split_jsp = new JScrollPane( split_pane );
          JPanel left_panel = new JPanel();
          left_panel.setLayout( new BorderLayout() );
          JTree jt = new JTree();
          jt.setRowHeight( 20 );
          left_panel.add( jt, BorderLayout.WEST );
//        left_panel.add( jt, BorderLayout.EAST );

          JTable jtable = new JTable( 4, 1  );

//        jtable.setBorder( new LineBorder( Color.green, 3 ));

          jtable.setRowHeight( 20 );
          left_panel.add( jtable, BorderLayout.CENTER );
          split_pane.setLeftComponent( left_panel );
          frame.getContentPane().add( split_jsp );
          split_pane.setDividerLocation( 0.5d );

      }
        });
    }
}

later

In answer to the suggestion that all I have to do is wrap this JTable in a JScrollPane... this doesn't appear to solve the problem, at least with the standard Java L&F. I have also tried various permutations of sitting the JTable on a JScrollPane on a JPanel, sitting the JTable on its own JPanel and giving the latter a LineBorder, etc. The problem appears to be a bit trickier. My chief suspects are Insets and the layout managers... but 1) neither of the getInsets methods of the JTable is called in the course of this code however 2) maybe a BorderLayout is not ideal. I did try GridLayout and BoxLayout but, as I recall, neither of these solved the problem...

later

even simpler SSCCE which illustrates the prob (cannot see left-hand vertical gridline)

import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;


public class TableGridProb2 {
  public static void main( String[] args ) throws InterruptedException, InvocationTargetException{
    EventQueue.invokeLater( new Runnable(){
      @Override
      public void run() {
        JFrame frame = new JFrame( "Table Grid Prob2" );
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JScrollPane sp = new JScrollPane( new JTable( 20, 5 ));
        frame.getContentPane().add( sp );
        frame.pack();
        frame.setVisible( true );
      }
    });
  }
}

* later (6 Sep) *

screenshots for the two SSCCEs:

Table Grid Prob

Table Grid Prob 2

hope you can see the problem: missing vertical left-hand gridline (and top gridline it appears) in both cases...

2

There are 2 answers

11
trashgod On BEST ANSWER

A few notes for reference:

  • I've incorporated @Reimeus' suggestion, but I'm not really sure what you want.

  • I'm sure the border is merely illustrative, but note that the API authors, "recommend that you put the component in a JPanel and set the border on the JPanel." In particular, the green border obscures part of the first table row.

  • Note that the gridlines belong to the UI delegate, as shown here; if this is critical, plan to test on each target L&F.

  • Unless you have a specific reason to wait on the initial thread, use invokeLater().

  • If the JTable dominates your initial appearance, overriding the Scrollable interface method getPreferredScrollableViewportSize() is a reasonable compromise of the general guidelines here.

  • Use pack() to leverage a component's preferred size.

  • Make setVisible() last.

Addendum: Based on your update, TableGridProb2, I added a colored border to an enclosing panel to see better. Indeed, com.apple.laf.AquaTableUI leaves a one-pixel left margin, presumably for the selection rectangle. You might try this with your chosen L&F.

image

import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.plaf.ColorUIResource;

public class TableGridProb2 {

    public static void main(String[] args) {
        UIManager.put("Table.gridColor", new ColorUIResource(Color.gray));
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Table Grid Prob2");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                JScrollPane sp = new JScrollPane(new JTable(20, 5));
                JPanel p = new JPanel(new GridLayout());
                p.setBorder(new LineBorder(Color.green, 4));
                p.add(sp);
                frame.getContentPane().add(p);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

image

import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.plaf.ColorUIResource;

public class TableGridProb {

    public static void main(String[] args) {
        UIManager.put("Table.gridColor", new ColorUIResource(Color.gray));
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Table Grid Prob");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                JPanel leftPanel = new JPanel(new BorderLayout());
                JTree jt = new JTree();
                jt.expandRow(1);
                leftPanel.add(jt, BorderLayout.WEST);
                JTable table = new JTable(20, 1) {
                    @Override
                    public Dimension getPreferredScrollableViewportSize() {
                        return new Dimension(300, 200);
                    }
                };
                table.setBorder(new LineBorder(Color.green, 4));
                table.setTableHeader(null);
                leftPanel.add(new JScrollPane(table), BorderLayout.CENTER);

                JSplitPane splitPane = new JSplitPane();
                splitPane.setLeftComponent(leftPanel);
                frame.add(splitPane);
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}
4
Reimeus On

Place the above JTable in a JScrollPane so that gridlines are drawn by that container. It appears that you dont want the table headers so you could do

jTable.setTableHeader(null);
leftPanel.add(new JScrollPane(jTable));