2016-01-22 9 views
2

При написании этого вопроса я смог найти способ заставить его вести себя так, как я хотел. Основываясь на this, я все еще задаю вопрос, поскольку другие люди могут столкнуться с подобными проблемами.Проблемы с размерами с JTabbedPane и фиксированным содержимым высоты

У меня есть следующие проблемы с размером JTabbedPane, используемого для контента, который растягивается горизонтально, но имеет фиксированную высоту. Оба варианта для setTabLayoutPolicy(), похоже, изменяют высоту содержимого и не будут последовательно отображать его на его предпочтительной или минимальной высоте.

С умолчанию WRAP_TAB_LAYOUT, предпочтительный размер вкладок панели не учитывает ли вкладки фактически сложенных или отображается рядом друг с другом в данный момент, как обсуждалось here, here и в this bug report. Если панель с вкладками выложена на основе уложенных вкладок, высота содержимого увеличивается примерно на 20 пикселей (высота одной вкладки) для каждой вкладки, добавленной, когда достаточно места для вкладок, которые будут отображаться рядом друг с другом. Если панель с вкладками выложена на основе вкладок, отображаемых рядом друг с другом, высота содержимого уменьшается, когда вкладки должны быть сложены.

Когда политика установлена ​​в SCROLL_TAB_LAYOUT, высота панели вкладок фиксирована, а макет в основном верен. Однако в зависимости от внешнего вида размер содержимого вкладки уменьшается на несколько пикселей. Я смог узнать, что это связано с вставками области табуляции, как определено L & F, которые не учитываются при вычислении предпочтительного размера панели вкладок (см. this bug report). Установка UIManager.getDefaults().put("TabbedPane.tabAreaInsets", new Insets(0,0,0,0)) работает для некоторых L & F (например, Metal), но не для других (например, Nimbus).

кажется, что есть только следующие варианты:

  • использовать сложены вкладки и имеют дополнительную высоту добавлены к содержанию
  • использовать сложены вкладки и имеют содержание охватывает, когда не хватает места
  • используйте прокрученные вкладки и добавьте несколько пикселей к минимальному/предпочтительному размеру содержимого вкладки, что делает его немного отличающимся с каждым L & F (но, по крайней мере, содержимое не должно быть обрезано)
  • использовать прокрученные вкладки и установить UI o е вкладки панель на новый BasicTabbedPaneUI который не выглядит большой

Есть чистый способ обеспечить, чтобы содержание вкладок панели всегда отображаются на фиксированную высоту для?

Следующий код и скриншоты иллюстрируют проблему

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JTabbedPane; 
import javax.swing.UIManager; 

public class TabbedPaneTest extends JFrame { 

    TabbedPaneTest() { 

     JPanel mainPanel = new JPanel(); 
     mainPanel.setBackground(Color.white); 

     JTabbedPane tabs = new JTabbedPane(); 
     //tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); // content cut off by a few pixels 
     tabs.setTabPlacement(JTabbedPane.BOTTOM); 

     Dimension min = new Dimension(100,200); 
     Dimension max = new Dimension(Short.MAX_VALUE,Short.MAX_VALUE); 
     //Dimension pref = new Dimension(Short.MAX_VALUE,200); // content cut off when small 
     Dimension pref = new Dimension(0,200); // content gets extra space when large 

     int tabCount = 3; 
     for (int i = 0; i < tabCount; i++) { 
      JLabel content = new JLabel(); 
      content.setMinimumSize(min); 
      content.setMaximumSize(max); 
      content.setPreferredSize(pref); 
      tabs.addTab("lorem ipsum dolor sit amet", content); 
     } 

     // set up and render window 
     getContentPane().add(mainPanel, BorderLayout.CENTER); 
     getContentPane().add(tabs, BorderLayout.PAGE_END); 
     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     setTitle("JScrollPane Test"); 
     pack(); 
     setSize(700,400); 

     tabs.addComponentListener(new ComponentAdapter() { 
      @Override 
      public void componentResized(ComponentEvent e) { 
       JTabbedPane tabbedPane = (JTabbedPane) e.getComponent(); 
       int tabCount = tabbedPane.getTabCount(); 
       for (int i = 0; i < tabCount; i++) { 
        Component c = tabbedPane.getComponentAt(i); 
        ((JLabel) c).setText("<html>" 
          + getSizes(c, "content") 
          + getSizes(tabbedPane, "tabs") 
          + "</html>"); 
       } 
      } 
     }); 
    } 

    private static String getSizes(Component c, String name) { 
     return "<p>" + name + " - " 
       + " minimum:" + Integer.toString(c.getMinimumSize().width) 
         + "x" + Integer.toString(c.getMinimumSize().height) 
       + " maximum:" + Integer.toString(c.getMaximumSize().width) 
         + "x" + Integer.toString(c.getMaximumSize().height) 
       + " preferred:" + Integer.toString(c.getPreferredSize().width) 
         + "x" + Integer.toString(c.getPreferredSize().height) 
       + " actual:" + Integer.toString(c.getSize().width) 
         + "x" + Integer.toString(c.getSize().height) 
       + "</p>"; 
    } 

    public static void main(String args[]) { 

     /* Set the Nimbus look and feel */ 
     //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> 
     /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. 
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */ 
     try { 
      for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { 
       if ("Nimbus".equals(info.getName())) { 
        javax.swing.UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { 
      java.util.logging.Logger.getLogger(TabbedPaneTest.class 
        .getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 
     //</editor-fold> 

     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override public void run() { 
       new TabbedPaneTest().setVisible(true); 
      } 
     }); 
    } 

} 

С прокручивать вкладки, содержание отрезанный несколько пикселей (193px вместо 200px здесь):

screenshot with scrolled tabs

Сложенными вкладками и широким контентом содержимое обрезается, когда окно мало (здесь 160px вместо 200px):

enter image description here

С СТекой закладками и узким содержанием, содержание сделано больше, когда окно является большим (240px вместо 200px здесь):

enter image description here

ответ

2

После прочтения больше о том, предпочтительном размере вычисленная панель с вкладками, я смог придумать следующее решение для случая WRAP_TAB_LAYOUT.

Проблема в том, что для панели с вкладками связаны предпочтительная высота и ширина. Предпочтительная высота рассчитывается для предпочтительной ширины, а не для фактической ширины тока. Это проблематично, если менеджер макетов родителя соответствует предпочтительной высоте, но не предпочтительной ширине.

Решение, с которым я столкнулся, состоит в том, чтобы настроить слушателя, который устанавливает предпочтительную ширину каждого содержимого вкладки в свою текущую ширину. Таким образом, панель с вкладками правильно вычисляет ее предпочтительную высоту и может быть выложена, например. с BorderLayout.

tabs.addComponentListener(new ComponentAdapter() { 
    @Override 
    public void componentResized(ComponentEvent e) { 
     JTabbedPane tabbedPane = (JTabbedPane) e.getComponent(); 
     int tabCount = tabbedPane.getTabCount(); 
     for (int i = 0; i < tabCount; i++) { 
      Component c = tabbedPane.getComponentAt(i); 
      c.setPreferredSize(new Dimension(c.getSize().width, c.getPreferredSize().height)); 
     } 
    } 
}); 

Я не смог найти удовлетворительное решение SCROLL_TAB_LAYOUT случае еще, так что если кто-то имеет представление о том, что будет оценено.