Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JTable的一列中,JPanel中没有显示JLabel的工具提示_Java_Swing_Jtable - Fatal编程技术网

Java 在JTable的一列中,JPanel中没有显示JLabel的工具提示

Java 在JTable的一列中,JPanel中没有显示JLabel的工具提示,java,swing,jtable,Java,Swing,Jtable,我有一个应用程序,在目录树中显示文件占用的空间;它使用一个JTable,每行是树中的一个级别,最右边的列显示一行jlabel,显示找到每个扩展名的文件占用的空间百分比。如果用户更改应用程序窗口的宽度,最后一列将更改以适应它,JLabel将更改以反映其在新列宽中所占的百分比。这一切都起作用了 我最近决定在每个标签上添加一个工具提示,以便用户可以根据需要查找准确的百分比。但是,我无法显示工具提示 我对最右边的列使用自定义渲染器。它在构造时创建50个JLabel,然后在渲染时修改所需的尺寸,以避免重复

我有一个应用程序,在目录树中显示文件占用的空间;它使用一个JTable,每行是树中的一个级别,最右边的列显示一行jlabel,显示找到每个扩展名的文件占用的空间百分比。如果用户更改应用程序窗口的宽度,最后一列将更改以适应它,JLabel将更改以反映其在新列宽中所占的百分比。这一切都起作用了

我最近决定在每个标签上添加一个工具提示,以便用户可以根据需要查找准确的百分比。但是,我无法显示工具提示

我对最右边的列使用自定义渲染器。它在构造时创建50个JLabel,然后在渲染时修改所需的尺寸,以避免重复创建对象。我试着将带有工具提示的jlabel放在JPanel中;这样做没有问题,但在我的应用程序中不可用。我还尝试在包含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;  
  }
  
}