Линии сетки JTable исчезают неожиданно

У меня есть S (очень S) SCCE, который иллюстрирует проблему: есть JTable и JTree, оба содержатся в JPanel с BorderLayout. Большинство линий сетки в JTable показывают, но не ту, что слева, и не ту, что вверху. Пробовал экспериментировать с границами, размещая JTable на собственной выделенной JPanel и т. Д.

Я узнал от экспертов, что плохая идея вызывать любой из методов setXXXSize, поэтому, например, не прибегать к setPreferredSize. В SSCCE вы можете поменять местами позиции дерева и таблицы, раскомментировав строку "EAST")

Как сделать так, чтобы эти затемненные / отсутствующие линии сетки снова появлялись?

(Примечание: идея заключается в том, чтобы в конечном итоге таблица динамически увеличивалась / уменьшалась с помощью JTree, чтобы в таблице и в дереве всегда было одинаковое количество строк... отсюда и желание содержать оба компонента в одной и той же 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 );

      }
        });
    }
}

потом

В ответ на предположение, что все, что мне нужно сделать, это обернуть этот JTable в JScrollPane... это не решает проблему, по крайней мере со стандартным Java L&F. Я также попробовал различные варианты размещения JTable на JScrollPane на JPanel, нахождения JTable на своем JPanel и присвоения последнему LineBorder и т. Д. Проблема, кажется, немного сложнее. Мои главные подозреваемые - это Insets и менеджеры компоновки... но 1) ни один из методов getInsets JTable не вызывается в этом коде, однако 2) возможно, BorderLayout не идеален. Я попробовал GridLayout и BoxLayout, но, насколько я помню, ни один из них не решил проблему...

потом

еще более простой SSCCE, который иллюстрирует проблему (не может видеть левую вертикальную линию сетки)

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

* позже (6 сентября) *

скриншоты для двух SSCCE:

Таблица Сетка Проб

Таблица Сетка Проб 2

надеюсь, вы видите проблему: отсутствует вертикальная левая линия сетки (и верхняя линия сетки она появляется) в обоих случаях...

2 ответа

Решение

Несколько заметок для справки:

  • Я включил предложение @Reimeus, но я не совсем уверен, что вы хотите.

  • Я уверен, что граница является просто иллюстративной, но учтите, что авторы API"рекомендуют поместить компонент в JPanel и установить границу на JPanel"В частности, зеленая рамка закрывает часть первой строки таблицы.

  • Обратите внимание, что линии сетки принадлежат делегату пользовательского интерфейса, как показано здесь; если это критично, запланируйте тестирование на каждом целевом L&F.

  • Если у вас нет конкретной причины ждать в начальном потоке, используйте invokeLater(),

  • Если JTable доминирует над вашей первоначальной внешностью, перекрывая Scrollable метод интерфейса getPreferredScrollableViewportSize() это разумный компромисс общих руководящих принципов здесь.

  • использование pack() использовать предпочтительный размер компонента.

  • Делать setVisible() прошлой.

Приложение: на основе вашего обновления, TableGridProb2Я добавил цветную рамку на ограждающую панель, чтобы лучше видеть. В самом деле, com.apple.laf.AquaTableUI оставляет левое поле размером в один пиксель, предположительно для прямоугольника выбора. Вы можете попробовать это с выбранным вами L&F.

образ

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

образ

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

Поместите выше JTable в JScrollPane так что линии сетки нарисованы этим контейнером. Похоже, вы не хотите заголовки таблицы, чтобы вы могли сделать

jTable.setTableHeader(null);
leftPanel.add(new JScrollPane(jTable));
Другие вопросы по тегам