Мое приложение разделено на два основных компонента:
- заголовок, состоящий из
JLabel
иJTableHeader
JScrollPane
, содержащийJTable
Причина, по которой JTableHeader
находится на отдельной панели, заключается в том, что она не должна прокручиваться. Для всех столбцов в таблице установлена предпочтительная/максимальная ширина (за исключением столбца в середине), поэтому при изменении размера фрейма только столбец должен изменять свою ширину.
РЕДАКТИРОВАТЬ: я считаю, что могу использовать JScrollPane.setColumnHeaderView( JTable.getTableHeader() );
, чтобы заголовок таблицы оставался статичным - код, который я получил, был таким, и его изменение, насколько я могу судить, не влияет на проблему.
У меня проблема с JScrollPane
, нарушающим ориентацию справа налево (RTL) JTableHeader
. JTableHeader
будет выровнено по левому краю, тогда как JTable
будет выровнено по правому краю.
Вопрос аналогичен тому, что было опубликовано здесь который указывает на эту неустраненную ошибку. Я не совсем уверен, что это проблема, которую я вижу, поскольку JTableHeader
не должно быть на панели прокрутки. Кроме того, предлагаемое решение не работает, поскольку мне нужно, чтобы полоса прокрутки находилась слева, как и следовало ожидать в ориентации RTL.
Как я могу исправить ориентацию для JTableHeader
, сохраняя при этом возможность автоматического изменения размера столбцов?
РЕДАКТИРОВАТЬ: добавлен JButton
в tablePanel, потому что он должен быть там.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ComponentOrientation;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
public class SwingTest {
public static void main( String[] args ) {
final JFrame frame = new JFrame( "RTL Test" );
//ComponentOrientation orientation = ComponentOrientation.LEFT_TO_RIGHT;
ComponentOrientation orientation = ComponentOrientation.RIGHT_TO_LEFT;
frame.setComponentOrientation( orientation );
/* Build and populate table */
String data[][] = {
{ "1", "foo", "bar", "5000" },
{ "2", "wtf", "RTL", "20000" },
{ "3", "hello", "world", "30000" },
{ "4", "why", "align", "25000" },
{ "5", "foo", "bar", "5000" },
{ "6", "wtf", "RTL", "20000" },
{ "7", "hello", "world", "30000" },
{ "8", "why", "align", "25000" },
{ "9", "hello", "world", "30000" },
{ "10", "hello", "world", "30000" },
{ "11", "hello", "world", "30000" }
};
String col[] = { "First", "Second", "Third", "Fourth" };
DefaultTableModel model = new DefaultTableModel( data, col );
/* Simply overrides isCellEditable to always * return false */
JTable table = new NonEditableTable( model );
/* By using AUTO_RESIZE_OFF, the header becomes correctly aligned but columns no longer auto-resize */
//table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
table.setAutoResizeMode( JTable.AUTO_RESIZE_ALL_COLUMNS );
table.applyComponentOrientation( orientation );
/* Set all but 3rd column to have a preferred/max size */
TableColumn tableColumn = null;
for ( int i = 0; i < table.getColumnCount(); i++ ) {
if ( i != 2 ) {
tableColumn = table.getColumnModel().getColumn( i );
tableColumn.setMaxWidth( 100 );
tableColumn.setPreferredWidth( 100 );
}
}
/* Pretty */
JTableHeader header = table.getTableHeader();
header.setForeground( Color.RED );
/* ScrollPane = JScrollPane + JTable */
JPanel tablePanel = new JPanel( new BorderLayout() );
tablePanel.add( BorderLayout.CENTER, table );
tablePanel.add( BorderLayout.CENTER, new JButton( "Doh!" ) );
JScrollPane scrollPane = new JScrollPane( tablePanel );
scrollPane.setBorder( BorderFactory.createEmptyBorder() );
/* NOTE: This is what breaks the header when using AUTO_RESIZE_ALL_COLUMNS, comment out to see */
scrollPane.setComponentOrientation( orientation );
/* Header */
JPanel headerPanel = new JPanel( new BorderLayout() );
headerPanel.add( BorderLayout.NORTH, new JLabel( "SWING TEST" ) );
headerPanel.add( BorderLayout.CENTER, Box.createVerticalStrut( 5 ) );
headerPanel.add( BorderLayout.SOUTH, table.getTableHeader() );
headerPanel.applyComponentOrientation( orientation );
/* Main = Header + ScrollPane */
JPanel mainPanel = new JPanel( new BorderLayout() );
mainPanel.add( BorderLayout.NORTH, headerPanel );
mainPanel.add( BorderLayout.CENTER, scrollPane );
/* Add to main frame */
frame.add( mainPanel );
frame.setUndecorated( true );
frame.getRootPane().setWindowDecorationStyle( JRootPane.PLAIN_DIALOG );
frame.setSize( 500, 200 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
frame.setVisible( true );
}
} );
}
@SuppressWarnings( "serial" )
public static class NonEditableTable extends JTable {
public NonEditableTable( DefaultTableModel model ) {
super( model );
}
@Override
public boolean isCellEditable( int row, int column ) {
return false;
}
}
}
It's actually quite common to freeze a row (in this case the header) so that as the table scrolls, you can easily see the header without having to scroll back up
— это поведение JScrollPane по умолчанию. При вертикальной прокрутке заголовок остается вверху. Если вы прокручиваете по горизонтали, заголовок прокручивается горизонтально, чтобы соответствовать прокручиваемым столбцам. - person camickr   schedule 30.08.2013