Swing 如何获得JList的大小?
我试图从JList的单元格渲染器getListCellRenderComponent()方法中获取JList的宽度 我得到的疏远行为是,只要它被放大,我就得到了正确的宽度,但对于比原始尺寸小的尺寸,我总是得到它第一次绘制时的宽度 list.getWidth()、list.getSize()、list.getBounds()和list.getCellBounds()也是如此。 使用parent.getxxxxx()获取包含滚动面板的列表的宽度可以正常工作 顺便说一下,此JList上没有设置最小/最大/首选大小 现在我不知所措 编辑:Swing 如何获得JList的大小?,swing,jlist,Swing,Jlist,我试图从JList的单元格渲染器getListCellRenderComponent()方法中获取JList的宽度 我得到的疏远行为是,只要它被放大,我就得到了正确的宽度,但对于比原始尺寸小的尺寸,我总是得到它第一次绘制时的宽度 list.getWidth()、list.getSize()、list.getBounds()和list.getCellBounds()也是如此。 使用parent.getxxxxx()获取包含滚动面板的列表的宽度可以正常工作 顺便说一下,此JList上没有设置最小/最
因此,似乎包含ScrollPanel的页面在调整大小时没有重新验证。不应该自动调用revalidate()吗?请注意,这不是通过编程实现的,而是由用户执行的鼠标帧调整 编辑2:
是的,好吧,JList的几何结构有一些复杂的内在因素,这些因素最终与实际屏幕的真实状态毫无关系。对后者感兴趣的人最好访问包含滚动窗格的视口并查询它(getWidth、getHaight、getSize、getBounds) 编辑3
这是按要求提供的SSCCE。但不是很短,因为我想保留Netbeans的布局代码,以防它对这个问题有影响。这样我得到的JList宽度为667,这似乎与最长项目的长度有关(在667处,它开始在末尾显示省略号)。 一旦视口的宽度达到667,jlists width就开始跟踪视口的宽度。收缩时,此跟踪将在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;
}
}
}
问题是,您在不通知列表的情况下有效地更改了列表的大小要求:-) 下面是为演示行为而修改的渲染器:
- 最初,即在显示列表之前,它的ui委托测量每个项目的大小要求,并缓存每个单元格的大小要求
- 此时,视口和列表的大小均为0:添加的文本长度为
somefixedChars+2
- 列表是可滚动的,并将其prefScrollableSize报告为其pref
- 滚动窗格始终按其prefScrollableSize调整列表大小,如果较大,则滚动
- 显示后,列表/视口的大小确实大于0,将最大长度项目的实际预大小更改为
somefixedChars+2*digitofsize
- ui没有意识到更改,因此它的pref、prefScrollable和实际值都不会更新
xList.invalidateCellSizeCache();
对于core,您可以通过重新/设置固定大小进行黑客攻击:
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;
}
}
问题是,您在不通知列表的情况下有效地更改了列表的大小要求:-) 下面是为演示行为而修改的渲染器:
- 最初,即在显示列表之前,它的ui委托测量每个项目的大小要求,并缓存每个单元格的大小要求
- 此时,视口和列表的大小均为0:添加的文本长度为
somefixedChars+2
- 列表是可滚动的,并将其prefScrollableSize报告为其pref
- 滚动窗格始终按其prefScrollableSize调整列表大小,如果较大,则滚动
- 显示后,列表/视口的大小确实大于0,将最大长度项目的实际预大小更改为
somefixedChars+2*digitofsize
- ui没有意识到更改,因此它的pref、prefScrollable和实际值都不会更新
xList.invalidateCellSizeCache();
对于core,您可以通过重新/设置固定大小进行黑客攻击:
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;
}
}
不寻常-请显示一个显示问题的SSCCE感谢SSCCE:-)列表的大小与打印的完全一样,问题是它没有更新到实际大小要求。不寻常-请显示一个显示问题的SSCCE感谢SSCCE:-)列表的大小与打印的完全一样,问题是它没有更新到实际的尺寸要求。@keopatra你太不可思议了!!说真的,有一群人在和javadocs战斗,而另一个联盟里有你:-)@keopatra你真是难以置信!!说真的,我们一群人在和javadocs战斗,而你在另一个联盟中:-)