JScrollPane нарушает ориентацию справа налево

Мое приложение разделено на два основных компонента:

  • заголовок, состоящий из 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;
    }

  }
}

person nevets1219    schedule 28.08.2013    source источник
comment
Я предлагаю опубликовать ваш вопрос в Coderanch, это @Darryl Burke автор большинства обходных путей для LTR и Swing, поэтому, пожалуйста, сообщите о кросспостинге на обоих форумах.   -  person mKorbel    schedule 29.08.2013
comment
на самом деле, я не понимаю, чего вы хотите достичь: звучит странно, что заголовок не прокручивается, когда сама таблица это делает. Технически проблема не связана с панелью прокрутки (не может быть связана, так как заголовок не t добавлено куда угодно в scrollPane;), даже его CO правильный, только выравнивание странное. Удаление его связи с таблицей исправляет это, не копал, почему это происходит. На вашем месте я бы начал сначала: опишите ваши требования и давайте посмотрим, как их можно выполнить, не делая ничего необычного.   -  person kleopatra    schedule 29.08.2013
comment
На самом деле довольно часто замораживают строку (в данном случае заголовок), чтобы при прокрутке таблицы вы могли легко видеть заголовок без необходимости прокручивать назад. Мои требования не изменились независимо от источника проблемы. Заголовок таблицы должен быть выровнен по правому краю в соответствии с ориентацией, а размер столбца должен автоматически изменяться.   -  person nevets1219    schedule 29.08.2013
comment
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
comment
Эта программа ведет себя крайне странно, даже когда вы убираете листание ВПРАВО_ВЛЕВО.   -  person Trejkaz    schedule 12.08.2014


Ответы (1)


Как насчет того, чтобы сделать что-то подобное? и тогда у вас будет лучший контроль над ориентацией.

JPanel headerPanel = new JPanel( new BorderLayout() );

JPanel headerPan = new JPanel();
JLabel xxx = new JLabel( "SWING TEST" );
xxx.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

headerPan.add(xxx);

Надеюсь, это полезно.

person David Gidony    schedule 26.02.2014
comment
Мне удалось получить ответ от CodeRanch по адресу coderanch.com/t/618982/GUI/java/ - person nevets1219; 27.02.2014