我有一个JTable带有自定义的ListSelectionModel,其中包含自定义选择模式。此选择模式可确保仅在一行中进行选择,但包含多个单元格。当用户单击选择表格中的某些单元格时,选定的单元格都与第一个选定的单元格位于同一行。
现在我想在前导选择单元格的右上角创建一个小消息,它显示一些数据,即所选单元格的计数。更改前导选择时应移动消息。
但是我该怎么做呢?它不是工具提示,因为它旨在在用户单击表格并选择单元格时显示,而不是通过将鼠标悬停在其上。
有什么建议么?
最好的问候, htz
或者(不是很漂亮,但效果很好),您可以利用 JTable 和所有其他 JComponent 一样的事实,因此您可以向它添加子组件。您所要做的就是确保正确调整组件的大小和位置(这只是因为 JTable 使用空布局)。
这是一个带有 JLabel 的小演示,它显示所选项目的数量。标签会自动定位在第一个可见行上,除非它是当前的潜在客户选择,在这种情况下,标签会移动到第二个可见行:
import java.awt.BorderLayout;
import java.awt.Point;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class TestTable {
protected void initUI() {
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
Vector<String> colNames = new Vector<String>();
for (int i = 0; i < 5; i++) {
colNames.add("Col-" + (i + 1));
}
for (int i = 0; i < 200; i++) {
Vector<Object> row = new Vector<Object>();
for (int j = 0; j < 5; j++) {
row.add("Cell " + (i + 1) + "-" + (j + 1));
}
data.add(row);
}
table = new JTable(data, colNames);
someText = new JLabel();
someText.setOpaque(true);
table.add(someText);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int count = table.getSelectedRowCount();
someText.setText("You currently have selected " + count + " item" + (count > 1 ? "s" : ""));
layoutLabel();
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
scrollpane = new JScrollPane(table);
scrollpane.getViewport().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
layoutLabel();
}
});
frame.add(scrollpane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private JLabel someText;
private JTable table;
private JScrollPane scrollpane;
private void layoutLabel() {
someText.setSize(someText.getPreferredSize());
Point location = scrollpane.getViewport().getViewRect().getLocation();
int leadSelectionIndex = table.getSelectionModel().getLeadSelectionIndex();
if (leadSelectionIndex > -1) {
if (table.rowAtPoint(location) == leadSelectionIndex) {
location.y += table.getRowHeight(leadSelectionIndex);
}
}
someText.setLocation(location);
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestTable().initUI();
}
});
}
}
Locations为ToolTip设置与 MsExcell 中类似的效果,它不是工具提示,因为它旨在在用户单击表格并选择单元格时显示,而不是通过将鼠标悬停在其上。
您可以使用JPopup/JWindow而不是ToolTip, 对于不可编辑的内容
JPopup/JWindow默认情况下不能包含可编辑的JComponent( JTextComponents)
对于用户输入,您只能使用未装饰JDialod的
另一种选择是实现每个组件的 glassPane(JLayer 用于 1.7,JXLayer 用于 1.6 的众多角色之一),如下所示。请注意,我并没有试图美化这个位置(就像@Guillaume 所做的那样)。此外,您必须稍微修改 Rob 的 DragLayout 以确保该框显示在表格区域内。
public static class ToolTipUI extends LayerUI<JTable> {
private JLayer<JTable> layer;
private JToolTip toolTip;
@Override
public void installUI(JComponent c) {
super.installUI(c);
this.layer = (JLayer) c;
installGlassPane();
installListeners();
}
private void installListeners() {
ListSelectionListener l = new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) return;
updateToolTip();
}
};
getTable().getColumnModel().getSelectionModel().addListSelectionListener(l);
getTable().getSelectionModel().addListSelectionListener(l);
}
private void updateToolTip() {
int[] selectedColumns = getTable().getColumnModel().getSelectedColumns();
int selectedRow = getTable().getSelectedRow();
if (selectedRow < 0 || selectedColumns.length == 0) {
setToolTipText("");
} else {
String text = "selected cells: ";
for (int i = 0; i < selectedColumns.length; i++) {
text += " " + selectedColumns[i];
}
setToolTipText(text);
}
}
private void setToolTipText(String string) {
toolTip.setTipText(string);
Rectangle cellBounds = getTable().getCellRect(getTable().getSelectedRow(), 0, false);
toolTip.setLocation(cellBounds.getLocation());
doLayout(layer);
}
@Override
public void doLayout(JLayer<? extends JTable> l) {
super.doLayout(l);
l.getGlassPane().doLayout();
}
private JTable getTable() {
return layer.getView();
}
private void installGlassPane() {
toolTip = ((JComponent) layer.getView()).createToolTip();
layer.getGlassPane().setBorder(BorderFactory.createLineBorder(Color.RED));
// DragLayout by Rob Camick http://tips4java.wordpress.com/2011/10/23/drag-layout/
layer.getGlassPane().setLayout(new DragLayout());
layer.getGlassPane().add(toolTip);
layer.getGlassPane().setVisible(true);
}
}
// usage:
JTable table = new JTable(new AncientSwingTeam());
JLayer layer = new JLayer<JTable>(table, new ToolTipUI());