3

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...

mike rodent
  • 14,126
  • 11
  • 103
  • 157

2 Answers2

3

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);
            }
        });
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thanks for the code changes and guidelines. Yes the LineBorder was just the remnant of experimentation. After setting table's header to null I tried replacing left_panel.add( jtable... ) with left_panel.add( new JScrollPane( jtable )... ) but this produces a single line around the JSP, and inside this an additional line (i.e. JTable gridline) at the top and right and bottom... but the left gridline is still missing... L&F is the standard Java one... – mike rodent Sep 03 '13 at 21:46
  • turns out that the basic Java L&F *is* MetalLookAndFeel. I tried other L&Fs seemingly available but all caused some confusing exceptions (different in each case): SynthLookAndFeel, BasicLookAndFeel, MultiLookAndFeel – mike rodent Sep 04 '13 at 06:34
  • Thanks for your addendum. I'm not sure how to go about changing the MetalUI L&F in this way... I have also don't know a lot about getting hold of and using an alternative L&F. I see that there is no specific TableUI for the Metal L&F specifically (could this be part of the problem?) ... and I don't know whether the TableUI of the "Basic" L&F (a superclass of the Metal L&F) has any influence on the appearance of tables when using Metal L&F! In short I have much homework to do unless someone can't point me in the right direction... – mike rodent Sep 04 '13 at 16:20
  • `MetalLookAndFeel` uses `javax.swing.plaf.basic.BasicTableUI`; as `paintGrid()` is `private`, you'll have to decide how much effort to invest. I honestly never noticed. – trashgod Sep 04 '13 at 16:38
  • thanks for looking that up... this thing does bug me however...! Will look on it as a learning excercise about these (to me) rather mysterious UI and L&F classes. Just a thought: if you were able to determine that your Apple AquaTableUI added a 1-pixel margin does this mean you have viewed the code involved? Of the paintGrid method? Could you show the code involved here? – mike rodent Sep 04 '13 at 17:21
  • Sorry, I just magnified the screen; here's [`paintGrid()`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/javax/swing/plaf/basic/BasicTableUI.java#BasicTableUI.paintGrid%28java.awt.Graphics%2Cint%2Cint%2Cint%2Cint%29). – trashgod Sep 04 '13 at 21:34
  • Thanks... but that link appears to be the standard java javax.swing.plaf.basic.BasicTableUI... I was wondering how you know what the mechanism used by the AquaTableUI is to insert this 1-pixel margin... – mike rodent Sep 05 '13 at 07:42
  • Well, I can see the gap, and [`AquaTableUI`](http://searchcode.com/codesearch/view/17983274) doesn't override the `BasicTableUI` implementation of `paintGrid()`. Does Windows? Can you post a post screenshot of what you're seeing? – trashgod Sep 05 '13 at 10:45
  • Have just posted screenshots for both SSCCEs... NB slightly confused a while ago because the main frame is given a Windows L&F whatever the L&F (in this case cross platform i.e. Metal) used in the actual GUI of the App... – mike rodent Sep 06 '13 at 08:29
  • Windows apparently uses BasicTableUI (for Metal L&F)... and as you say, paintGrid is private so can't be overridden... one would have to reconstruct a TableUI which wd be used instead of BasicTableUI (how to get the L&F to do this? I have no idea whatsoever!) – mike rodent Sep 06 '13 at 08:36
  • One more thing! I am going to start examining the code of SwingSet2 (demo which comes with Java 6 JDK)... in fact you can see the problem with the vertical lines very clearly... the left hand vertical does not appear and disappear with the rest ("Vert Lines" checkbox) because it is not a table grid line at all... But the "illusion" of a left hand grid line at the start is quite good... – mike rodent Sep 06 '13 at 08:39
2

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));
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • Thanks. I did in fact try this... but wondered why you have to place a JTable in a JSP just to show the missing gridlines... also, without really thinking it through fully I wondered whether the scrollbars might appear in certain circs when you don't want them to (OK obviously you could hard-code them never to appear). I'm just wondering what is actually going on here Swing-wise resulting in the "trimming" of 2 edges of the JTable's grid... – mike rodent Sep 03 '13 at 19:20
  • Never drilled down into the mechanics of why it does this but just know that the outer container doesnt draw a `JTable's` borders correctly if its added directly :) – Reimeus Sep 03 '13 at 19:27
  • later: see comment for trashgod: actually putting it on a JSP didn't solve the problem: left-hand gridline is still missing/obscured... – mike rodent Sep 03 '13 at 21:48
  • I think I see it, too {[update](http://stackoverflow.com/a/18599978/230513)}; +1 for `JScrollPane`. – trashgod Sep 04 '13 at 10:26