2013-10-05 48 views
1

我想從它的單元格渲染器getListCellRendererComponent()方法中獲取JList的寬度。如何獲取JList的大小?

我得到的異常行爲是,只要它被放大,我就會得到正確的寬度,但對於比原始尺寸更小的尺寸,我總是可以獲得它在第一次繪製時的寬度。

對於list.getWidth(),list.getSize(),list.getBounds()和list.getCellBounds(),這是如此。 使用parent.getxxxxx()獲取包含ScrollPanel的列表的寬度將按預期工作。

順便說一下,這個JList上沒有設置min/max/preferredSize。

在這一點上,我茫然..

編輯:
所以,因爲它似乎含有ScrollPanel沒有被重新驗證上調整大小。不應該重新驗證()自動調用?請注意,這不是以編程方式完成的任何事情,而只是由用戶執行的鼠標幀大小調整。

編輯2:
是啊,Jlist的幾何形狀,其在一天結束時沒有相關的所有實際屏幕實際狀態的一些複雜intrincacies。任何對後者感興趣的人都可以更好地瞭解包含ScrollPane的ViewPort並查詢(getWidth,getHaight,getSize,getBounds)。

編輯3
這是根據要求的SSCCE。雖然不是很短,但我想保留Netbeans的佈局代碼,以防它對問題有所影響。有了這個,我得到了667的JList寬度,這似乎與最長項目的長度有些相關(在667它開始在最後顯示省略號)。 只要視口寬度達到667,jlists寬度就開始跟蹤視口的寬度。在收縮時,此跟蹤在667處停止並保持在此位置。

package com.dafquest.operator.mvc; 

import java.awt.Component; 
import javax.swing.DefaultListCellRenderer; 
import javax.swing.JLabel; 
import javax.swing.JList; 

public class JListSSCCE extends javax.swing.JFrame { 

    public JListSSCCE() { 
     initComponents(); 
    } 

    @SuppressWarnings("unchecked") 
    private void initComponents() { 

     jPanel1 = new javax.swing.JPanel(); 
     jScrollPane1 = new javax.swing.JScrollPane(); 
     jList1 = new javax.swing.JList(); 

     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     setName("Form"); 

     jPanel1.setName("jPanel1"); 

     jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 
     jScrollPane1.setName("jScrollPane1"); 

     jList1.setModel(new javax.swing.AbstractListModel() { 
      String[] strings = { "This is this Jlist's Item 1", "A shorter Item 2", "For some reason Item 3 seems to be longer", "Certainly issue whith item 3 must be a mirage, Item 4 *is* a really long item", "Item 5" }; 
      public int getSize() { return strings.length; } 
      public Object getElementAt(int i) { return strings[i]; } 
     }); 
     jList1.setCellRenderer(new MyCellRenderer()); 
     jList1.setName("jList1"); 
     jScrollPane1.setViewportView(jList1); 

     javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); 
     jPanel1.setLayout(jPanel1Layout); 
     jPanel1Layout.setHorizontalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 330, Short.MAX_VALUE) 
     ); 
     jPanel1Layout.setVerticalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 110, Short.MAX_VALUE) 
     ); 

     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addContainerGap() 
       .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 
       .addContainerGap()) 
     ); 
     layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) 
      .addGroup(layout.createSequentialGroup() 
       .addContainerGap() 
       .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) 
       .addContainerGap()) 
     ); 

     pack(); 
    }       

    public static void main(String args[]) { 
     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(JListSSCCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); 
     } 

     java.awt.EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new JListSSCCE().setVisible(true); 
      } 
     }); 
    } 

    private javax.swing.JList jList1; 
    private javax.swing.JPanel jPanel1; 
    private javax.swing.JScrollPane jScrollPane1; 

    private class MyCellRenderer extends DefaultListCellRenderer { 

     @Override 
     public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 

      JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
      String widths = "(SPViewPort: " + list.getParent().getWidth() 
        + ", Jlist: " + list.getWidth() 
        + ", Cell: " + comp.getWidth() 
        + ", CellPref: " + comp.getPreferredSize().width + ") "; 
      comp.setText(widths + comp.getText()); 

      // Lets see after adding text, might be that JList width is equal 
      // tho longest item's preferred width? 
      widths = "(SPViewPort: " + list.getParent().getWidth() 
        + ", Jlist: " + list.getWidth() 
        + ", Cell: " + comp.getWidth() 
        + ", CellPref: " + comp.getPreferredSize().width + ") "; 
      System.out.println(widths); 

      return comp; 
     } 
    } 
} 
+0

異常 - 請顯示一個證明問題的SSCCE – kleopatra

+0

感謝您的SSCCE :-)列表的大小與打印完全一致,問題在於它未更新爲實際大小要求。 – kleopatra

回答

1

的問題是,你正在有效地改變列表的尺寸要求不通知它:-)

下面是你的渲染修改,以證明行爲:

  • 最初,也就是之前該列表被顯示,它的ui-delegate測量每個項目的大小要求並緩存當時每個單元的大小,並且當時視口和列表的大小都是0:添加的文本長度是somefixedChars + 2
  • 列表是-一個滾動並報告其prefScrollableSize作爲其PREF
  • 滾動窗格總是尺寸列表在其prefScrollableSize,滾動如果其較大
  • 後顯示,列表/視做有一個大小> 0改變最大長度項目的實際prefSize到somefixedChars + 2* digitsOfSize
  • UI是不知道的變化,所以無論其PREF還是其prefScrollable還是其實際更新

的解決方案取決於您的實際使用情況:你需要找到一種強制ui使其大小緩存無效的方法。SwingX' JXList有一個方法給它,如:

xList.invalidateCellSizeCache(); 

爲核心,您可以通過RE /黑客設置一個固定大小:

list.setFixedCellWidth(somearbitraryValue); 
list.setFixedCellWidth(-1); 

一起玩的渲染:

private class MyCellRenderer extends DefaultListCellRenderer { 

    private int zeroPref; 

    @Override 
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 

     JLabel comp = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
     String widths = "(SPViewPort: " + list.getParent().getWidth() 
       + ", Jlist: " + list.getWidth() 
       + ", CellPref: " + comp.getPreferredSize().width + ") "; 
     comp.setText(widths + comp.getText()); 
     if (list.getWidth() == 0) { 
      // keep track of the pref for a zero sized list/viewport 
      zeroPref = Math.max(comp.getPreferredSize().width, zeroPref); 
     } 
     //list is sized to its initial pref 
     widths = //"index: " + index 
       "initial: " + zeroPref 
       + "(SPViewPort: " + list.getParent().getWidth() 
       + ", Jlist: " + list.getWidth() 
       + ", CellPref: " + comp.getPreferredSize().width + ") "; 
     System.out.println(widths); 

     return comp; 
    } 
} 
+0

@keopatra你真不可思議!說真的,我們中有一羣人正在與javadoc進行戰鬥,而在另一個聯盟中有你呢.-) – AndRAM