Линии сетки 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 ответа
Несколько заметок для справки:
Я включил предложение @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));