[英]Tooltips don't display for JLabels in a JPanel in a JTable cell
下面显示了JTable
单元格,每个单元格都包含一个面板,该面板又包含两个标签。 我已经在 JLabel 上设置了工具JLabel
,但它们没有出现。 (感谢@MadProgrammer 提供的原始精简代码以显示JTable
并说明 setToolTipLocation setToolTipLocation()
。)
我为一个 label 覆盖getToolTipText()
,并为另一个调用 setToolTipText setToolTipText()
; 如果我在前一个中设置断点,它会被调用,但不会出现工具提示。 所以我尝试覆盖setToolTipLocation()
,尽管我不确定它的合适值是什么; 我不确定它会使用什么坐标系,认为 10,10 会将它留在大多数事物的范围内。
这里没有显示,我还尝试在getTableCellRendererComponent()
调用之外创建标签,并在getTableCellRendererComponent()
() 中设置它们的尺寸、背景 colors 和工具提示。 那也行不通。
我还需要做什么才能看到这些工具提示?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class Test
{
Border labelBorder = BorderFactory.createLineBorder(Color.black);
public static void main(String[] args)
{
new Test();
}
public Test()
{
EventQueue.invokeLater
(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
);
}
public class TestPane extends JPanel
{
public TestPane()
{
setLayout(new BorderLayout());
int rows = 4;
int cols = 3;
DefaultTableModel model = new DefaultTableModel(0, cols);
for (int row = 0; row < rows; row++)
{
Object[] data = new Object[cols];
for (int col = 0; col < cols; col++)
{
data[col] = row + "x" + col;
}
model.addRow(data);
}
JTable table = new JTable(model);
// table.setToolTipText("table text"); // this works, but would block tooltips from UI children
table.setDefaultRenderer(Object.class, new TestCellRenderer());
add(new JScrollPane(table));
}
public class TestCellRenderer extends DefaultTableCellRenderer
{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column)
{
// create two labels, put them side-by-side in a panel, and return
// the panel as the component being rendered.
JLabel label1 = new JLabel("a Banana @" + value.toString())
{
@Override
public String getToolTipText()
{
return "AA";
}
@Override public Point getToolTipLocation(MouseEvent mouseEvent) { return new Point(10,10); }
};
label1.setBorder(labelBorder);
label1.setToolTipText("AA"); // this tooltip text does not show up.
JLabel label2 = new JLabel("b Banana @" + value.toString());
label2.setBorder(labelBorder);
label2.setToolTipText("BB"); // this tooltip text does not show up.
JPanel panel = new JPanel();
BoxLayout layout = new BoxLayout(panel, BoxLayout.X_AXIS);
panel.setLayout(layout);
// panel.setToolTipText("panel text"); //this works, but would block tooltips on the JLabels
panel.add(label1);
panel.add(label2);
return panel;
}
}
}
}
我为一个 label 覆盖 getToolTipText()
如何尝试覆盖JTable#getToolTipText(MouseEvent)
方法而不是JLabel
:
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.table.*;
public class Test2 {
public static void main(String[] args) {
new Test2();
}
public Test2() {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class TestPane extends JPanel {
public TestPane() {
super(new BorderLayout());
int rows = 4;
int cols = 3;
DefaultTableModel model = new DefaultTableModel(0, cols);
for (int row = 0; row < rows; row++) {
Object[] data = new Object[cols];
for (int col = 0; col < cols; col++) {
data[col] = row + "x" + col;
}
model.addRow(data);
}
JTable table = new JTable(model) {
@Override public String getToolTipText(MouseEvent e) {
Point pt = e.getPoint();
int vrow = rowAtPoint(pt);
int vcol = columnAtPoint(pt);
TableCellRenderer tcr = getCellRenderer(vrow, vcol);
Component c = prepareRenderer(tcr, vrow, vcol);
if (c instanceof JPanel) {
Rectangle r = getCellRect(vrow, vcol, true);
c.setBounds(r);
c.doLayout();
pt.translate(-r.x, -r.y);
Component l = SwingUtilities.getDeepestComponentAt(c, pt.x, pt.y);
if (l instanceof JLabel) {
return ((JLabel) l).getToolTipText();
}
}
return super.getToolTipText(e);
}
};
table.setDefaultRenderer(Object.class, new TestCellRenderer());
add(new JScrollPane(table));
}
}
class TestCellRenderer extends DefaultTableCellRenderer {
@Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label1 = new JLabel("a Banana @" + value.toString());
label1.setBorder(BorderFactory.createLineBorder(Color.BLACK));
label1.setToolTipText("AA");
JLabel label2 = new JLabel("b Banana @" + value.toString());
label2.setBorder(BorderFactory.createLineBorder(Color.BLACK));
label2.setToolTipText("BB");
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(label1);
panel.add(label2);
return panel;
}
}
有一些旧代码允许您覆盖用作渲染器的面板的getToolTipText(...)
方法。
不幸的是,它似乎只在将 GridLayout 用作面板的布局管理器时才起作用。
使用aterai
提供的“布局”代码,我也能够使代码适用于 FlowLayout。 (没有尝试其他布局管理器):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableRendererPanelHelp
{
static class MultiLabelRenderer implements TableCellRenderer
{
private JTable table;
private int row;
private int column;
private JPanel panel;
private JLabel red;
private JLabel blue;
public MultiLabelRenderer()
{
red = new JLabel();
red.setForeground(Color.RED);
blue = new JLabel();
blue.setForeground(Color.BLUE);
panel = new JPanel( new FlowLayout(0, 0, FlowLayout.LEFT) )
{
public String getToolTipText(MouseEvent e)
{
String tooltip = null;
Rectangle r = table.getCellRect(row, column, true);
setBounds(r);
doLayout();
Component c = getComponentAt( e.getPoint() );
if (c instanceof JLabel)
{
JLabel label = (JLabel)c;
tooltip = label.getToolTipText();
}
return tooltip;
}
};
panel.add(red);
panel.add(blue);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, final int row, final int column)
{
this.row = row;
this.column= column;
this.table = table;
panel.setBackground( isSelected ? table.getSelectionBackground() : table.getBackground() );
if (value == null || value.toString().isEmpty())
{
red.setText("");
blue.setText("");
}
else
{
String text = value.toString();
red.setText( text.substring(0, 3) );
red.setToolTipText( red.getText() );
blue.setText( text.substring(3) );
blue.setToolTipText( blue.getText() );
}
return panel;
}
}
public static void createAndShowGUI()
{
JTable table = new JTable(5, 3);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.getColumnModel().getColumn(0).setCellRenderer( new MultiLabelRenderer());
JScrollPane scrollPane = new JScrollPane( table );
table.setValueAt("abcde", 0, 0);
table.setValueAt("123456789", 1, 0);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( scrollPane );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
这种方法的一个好处是所有逻辑都包含在渲染器 class 中,您不需要覆盖 JTable。
此外,此方法尝试重用 JPanel 和 JLabels,因此您不必在每次呈现单元格时都不断创建新组件。
也许晚了,但这里有一个类似的方法,不应该依赖于布局管理器。
所有代码都在直接扩展 JPanel 的 CellRenderer 中,然后将 getToolTip 请求重新抛出到适应 MouseEvent 的子组件。
package test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
public class TestTooltipTable {
Border labelBorder = BorderFactory.createLineBorder(Color.black);
public static void main(String[] args) {
new TestTooltipTable();
}
public TestTooltipTable() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
int rows = 4;
int cols = 3;
DefaultTableModel model = new DefaultTableModel(0, cols);
for (int row = 0; row < rows; row++) {
Object[] data = new Object[cols];
for (int col = 0; col < cols; col++) {
data[col] = row + "x" + col;
}
model.addRow(data);
}
JTable table = new JTable(model);
// table.setToolTipText("table text"); // this works, but would block tooltips from UI children
table.setDefaultRenderer(Object.class, new TestCellRenderer());
add(new JScrollPane(table));
}
public class TestCellRenderer extends JPanel implements TableCellRenderer {
protected JLabel label1;
protected JLabel label2;
protected Rectangle cellRect;
public TestCellRenderer() {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
label1 = new JLabel(" ");
label2 = new JLabel(" ");
label1.setBorder(labelBorder);
label1.setToolTipText("AA"); // this tooltip text does not show up.
label2.setBorder(labelBorder);
label2.setToolTipText("BB"); // this tooltip text does not show up.
add(label1);
add(label2);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
// create two labels, put them side-by-side in a panel, and return
// the panel as the component being rendered.
label1.setText("a Banana @" + value.toString());
label1.setToolTipText("AA "+row+"x"+column);
label2.setText("b Banana @" + value.toString());
label2.setToolTipText("BB "+row+"x"+column); // this tooltip text does not show up.
cellRect=table.getCellRect(row, column, true);
return this;
}
@Override
public String getToolTipText(MouseEvent event) {
if (cellRect==null) {
return null;
}
setBounds(cellRect);
doLayout();
Point p=event.getPoint();
Component c=SwingUtilities.getDeepestComponentAt(this, p.x, p.y);
if (!(c instanceof JComponent)) {
return null;
}
p=SwingUtilities.convertPoint(this, p, c);
MouseEvent newEvent = new MouseEvent(c, event.getID(),
event.getWhen(), event.getModifiersEx(),
p.x, p.y,
event.getXOnScreen(),
event.getYOnScreen(),
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
return ((JComponent) c).getToolTipText(newEvent);
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.