Java 在JTable的一列中,JPanel中没有显示JLabel的工具提示
我有一个应用程序,在目录树中显示文件占用的空间;它使用一个JTable,每行是树中的一个级别,最右边的列显示一行jlabel,显示找到每个扩展名的文件占用的空间百分比。如果用户更改应用程序窗口的宽度,最后一列将更改以适应它,JLabel将更改以反映其在新列宽中所占的百分比。这一切都起作用了 我最近决定在每个标签上添加一个工具提示,以便用户可以根据需要查找准确的百分比。但是,我无法显示工具提示 我对最右边的列使用自定义渲染器。它在构造时创建50个JLabel,然后在渲染时修改所需的尺寸,以避免重复创建对象。我试着将带有工具提示的jlabel放在JPanel中;这样做没有问题,但在我的应用程序中不可用。我还尝试在包含jlabel的面板中重写Java 在JTable的一列中,JPanel中没有显示JLabel的工具提示,java,swing,jtable,Java,Swing,Jtable,我有一个应用程序,在目录树中显示文件占用的空间;它使用一个JTable,每行是树中的一个级别,最右边的列显示一行jlabel,显示找到每个扩展名的文件占用的空间百分比。如果用户更改应用程序窗口的宽度,最后一列将更改以适应它,JLabel将更改以反映其在新列宽中所占的百分比。这一切都起作用了 我最近决定在每个标签上添加一个工具提示,以便用户可以根据需要查找准确的百分比。但是,我无法显示工具提示 我对最右边的列使用自定义渲染器。它在构造时创建50个JLabel,然后在渲染时修改所需的尺寸,以避免重复
getToolTiptText()
,但无法使getComponentAt()
工作
我想知道是否有人能指出我在工具提示上哪里出错了
SizeBlockTester.java
package sizeblocktester.filedata;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
/**
* Test frame for an unexpected behavior of a Swing UI; a label inside a panel
* used as a value for a column does not display its tooltip. The good stuff is
* in SizeBlockTesterPercentageRenderer.
*/
@SuppressWarnings("serial")
public class SizeBlockTester extends JFrame
{
public static void main(String[] args)
{
SizeBlockTester tester = new SizeBlockTester();
tester.go();
}
public void go()
{
createUI();
setVisible(true);
}
private void createUI()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SizeBlockTesterJTableModel model = new SizeBlockTesterJTableModel();
SizeBlockTesterJTable table = new SizeBlockTesterJTable(model);
table.setDefaultRenderer(SizeBlockList.class, new SizeBlockTesterPercentageRenderer());
table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane, BorderLayout.CENTER);
pack();
}
}
SizeBlock.java
package sizeblocktester.filedata;
/**
* A block of something to display; for this test, size and percentage are set to the same thing.
*/
public class SizeBlock
{
private String label;
public String getLabel() { return label; }
private long size;
public long getSize() { return size; }
private int percentage;
public void setPercentage(int value) { percentage = value; }
public int getPercentage() { return percentage; }
public SizeBlock(String givenLabel, long givenSize)
{
label = givenLabel;
size = givenSize;
percentage = (int)givenSize;
}
public String toString() { return label; }
}
SizeBlockList.javav
package sizeblocktester.filedata;
import java.util.ArrayList;
/**
* A list of SizeBlock, put in its own class so we can assign a default renderer to it.
* @author ralph
*
*/
public class SizeBlockList
{
public SizeBlockList (ArrayList<SizeBlock> givenList) { list = givenList; }
private ArrayList<SizeBlock> list = new ArrayList<SizeBlock>();
public ArrayList<SizeBlock> getList() { return list; }
public void setList(ArrayList<SizeBlock> givenList) { list = givenList; }
}
package sizeblocktester.filedata;
导入java.util.ArrayList;
/**
*SizeBlock的列表,放在它自己的类中,这样我们就可以为它指定默认的渲染器。
*@作者拉尔夫
*
*/
公共类SizeBlockList
{
public SizeBlockList(ArrayList givenList){list=givenList;}
private ArrayList list=new ArrayList();
public ArrayList getList(){return list;}
public void setList(ArrayList givenList){list=givenList;}
}
SizeBlockTesterTable.java
package sizeblocktester.filedata;
import javax.swing.JTable;
import javax.swing.table.TableColumnModel;
/**
* This extension of JTable lays out the table such that
* resizing a column widens or narrows the column to its
* right, and resizing the window just widens or narrows
* the last column.
* @author rcook
*
*/
public class SizeBlockTesterJTable extends JTable
{
private static final long serialVersionUID = 1L;
public SizeBlockTesterJTable(SizeBlockTesterJTableModel model)
{ super(model);
}
public SizeBlockTesterJTableModel getDirTableModel()
{ return (SizeBlockTesterJTableModel)getModel();
}
/**
* set the widths of the columns so that the last column
* gets any extra or narrows to accommodate any surfeit
* needed.
*/
public void doLayout()
{
TableColumnModel model = getColumnModel();
int tableWidth = getWidth();
int usedWidth = 0;
// add up the widths of all columns except the last
int columnCount = model.getColumnCount();
for (int i=0; i<columnCount - 1; i++)
{
int width = model.getColumn(i).getWidth();
usedWidth += width;
}
// set the width of the last column to the remaining space
int lastWidth = tableWidth - usedWidth;
model.getColumn(columnCount-1).setWidth(lastWidth);
}
}
package sizeblocktester.filedata;
导入javax.swing.JTable;
导入javax.swing.table.TableColumnModel;
/**
*JTable的这个扩展对表进行了布局,以便
*调整列的大小会将列加宽或缩小到其大小
*对,调整窗口大小只会扩大或缩小
*最后一栏。
*@author-rcook
*
*/
公共类SizeBlockTesterTable扩展了JTable
{
私有静态最终长serialVersionUID=1L;
公共SizeBlockTesterTable(SizeBlockTesterTableModel模型)
{超级(模型);
}
公共SizeBlockTesterTableModel GetDirtTableModel()
{return(SizeBlockTesterJTableModel)getModel();
}
/**
*设置列的宽度,使最后一列
*获得任何额外或缩小以容纳任何过量
*需要。
*/
公共空间布局()
{
TableColumnModel=getColumnModel();
int tableWidth=getWidth();
int usedWidth=0;
//将除最后一列之外的所有列的宽度相加
int columnCount=model.getColumnCount();
对于(int i=0;ic=null;
//列0和1是字符串,2是sizeBlockList。
如果(colNumber,但在此基础上,如果没有最小的工作示例,则始终警告您一个问题-据我所知,您的问题是关于在添加到用作渲染器的面板上的JLabel上显示工具提示。对于渲染器,您只需在面板上有两个标签的自定义渲染器,然后根据光标所在的标签显示工具提示。all关于动态调整标签大小的逻辑与所述问题无关。自定义TableModel无关。首先,让简单的解决方案发挥作用,然后将解决方案应用于应用程序。例如:
package sizeblocktester.filedata;
import javax.swing.table.AbstractTableModel;
@SuppressWarnings("serial")
public class SizeBlockTesterJTableModel extends AbstractTableModel
{
SizeBlockTesterTableRow[] rowList = new SizeBlockTesterTableRow[]
{
new SizeBlockTesterTableRow("dum", "dee", "Alice", 75, "WRabbit", 25) ,
new SizeBlockTesterTableRow("Laurel", "Hardy", "Kukla", 60, "Fran", 40)
};
@Override
public int getRowCount() { return rowList.length; }
public int getColumnCount() { return 3; }
public Object getValueAt (int row, int col) { return getColumnValue(rowList[row], col); }
public Object getColumnValue(SizeBlockTesterTableRow row, int col) { return row.getColumnValue(col); }
public Class<?> getColumnClass(int colNumber)
{
Class<?> c = null;
// columns 0 and 1 are strings, 2 is the sizeBlockList.
if (colNumber <= 1) { c = String.class; }
else { c = SizeBlockList.class; }
return c;
}
}
package sizeblocktester.filedata;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
//import rcutil.color.NamedColor;
/**
* a Size Block is an object with a string name, long size, and an int
* percentage. This renderer takes a list of such size blocks and creates a
* component to display each size block within a JTable cell such that each
* block's percentage is reflected as the relative width of that block in the
* cell. <B>Furthermore, the string label on the cell is used as an key into a
* hashmap that tracks the color being used for that index; the same color is
* used on each call to the renderer.
*
* @author rcook
*
*/
@SuppressWarnings("serial")
public class SizeBlockTesterPercentageRenderer extends DefaultTableCellRenderer
implements TableCellRenderer
{
boolean blueBackground = true; // toggles so we can alternate colors for backgrounds
private static final int MINIMUM_LABEL_WIDTH = 10;
private static final String REST_OF_TYPES_STRING = "---";
// the container panel is the one we'll return; In it we'll put one JLabel for each
// size block being represented on that row.
private JPanel containerPanel = new JPanel();
// this array of JLabels is put in the container panel; we set the width
// and the background color based on its label and its percentage,
// respectively.
// it is sized so that we never need more JLabels than this for one row
// of the display (since we're currently doing percentages, 50 seems safe).
private static final int MAX_LABELS = 50;
private JLabel[] sizeBlockLabels = new JLabel[MAX_LABELS];
private Dimension[] sizeBlockDimensions = new Dimension[MAX_LABELS];
private JLabel REST_OF_TYPES_LABEL = null;
public SizeBlockTesterPercentageRenderer()
{
containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.LINE_AXIS));
sizeBlockLabels = new JLabel[MAX_LABELS];
sizeBlockDimensions = new Dimension[MAX_LABELS];
for (int i = 0; i < MAX_LABELS; i++)
{
JLabel l = new JLabel();
l.setOpaque(true);
sizeBlockLabels[i] = l;
sizeBlockDimensions[i] = new Dimension(10, 10);
containerPanel.add(sizeBlockLabels[i]);
}
REST_OF_TYPES_LABEL = new JLabel();
REST_OF_TYPES_LABEL.setBackground(Color.gray);
}
public Component getTableCellRendererComponent
(JTable table, Object givenList,
boolean isSelected, boolean hasFocus,
int row, int col)
{
SizeBlockList sizeBlockList = (SizeBlockList) givenList;
// set the height and width of the container panel to that of the cell
// (row height, column width)
int rowHeight = table.getRowHeight(row);
int columnWidth = table.getColumnModel().getColumn(col).getWidth();
// remainingWidth keeps getting set to the width we have not yet used up
// on the display. done is set to true when we're done displaying things.
int remainingWidth = columnWidth;
boolean done = false;
int i = 0;
for (SizeBlock sizeBlock : sizeBlockList.getList())
{
// create a panel for each sizeBlock, setting the width according to
// the percentage of space it uses. Since we're reusing JPanels, they're
// already added to the containerPanel, so we don't need to do that here.
String labelText = null;
int newWidth = (columnWidth * sizeBlock.getPercentage()) / 100;
if (newWidth < MINIMUM_LABEL_WIDTH)
{
labelText = REST_OF_TYPES_STRING;
newWidth = remainingWidth;
done = true;
}
else
{
labelText = sizeBlock.getLabel();
}
remainingWidth -= newWidth;
sizeBlockDimensions[i].setSize(newWidth, rowHeight);
sizeBlockLabels[i].setPreferredSize(sizeBlockDimensions[i]);
sizeBlockLabels[i].setMaximumSize(sizeBlockDimensions[i]);
sizeBlockLabels[i].setBackground(blueBackground? Color.CYAN : Color.green); blueBackground = !blueBackground;
sizeBlockLabels[i].setText(labelText);
sizeBlockLabels[i].setToolTipText(String.format("%d%%", sizeBlock.getPercentage()));
sizeBlockLabels[i].setVisible(true);
i++;
if (done)
{
break;
}
}
for (int j = i; j < MAX_LABELS; j++)
{
sizeBlockLabels[j].setVisible(false);
}
containerPanel.doLayout();
return containerPanel;
}
// The following methods override the defaults for performance reasons
public void validate() { }
public void revalidate() { }
protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { }
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { }
}
package sizeblocktester.filedata;
import java.util.ArrayList;
public class SizeBlockTesterTableRow
{
String firstValue;
String secondValue;
SizeBlockList sizeBlockList;
public SizeBlockTesterTableRow(String a, String b, String x, int c, String y, int d)
{
firstValue = a;
secondValue = b;
ArrayList<SizeBlock> list = new ArrayList<>();
list.add(new SizeBlock(x, c));
list.add(new SizeBlock(y, d));
sizeBlockList = new SizeBlockList(list);
}
public Object getColumnValue(int col)
{
Object result = null;
switch (col)
{
case 0: result = firstValue; break;
case 1: result = secondValue; break;
case 2: result = sizeBlockList; break;
default: System.out.println("No value in row for col " + col);
}
return result;
}
}