Java 如何在JTable中的前导选择单元格上显示消息?

Java 如何在JTable中的前导选择单元格上显示消息?,java,swing,jtable,Java,Swing,Jtable,我有一个带有自定义列表选择模型的JTable,其中包含自定义选择模式。此选择模式可确保仅在一行中进行选择,但有多个单元格。当用户单击选择表中的某些单元格时,选定的单元格与第一个选定的单元格都位于同一行中 现在,我想在前导选择单元格的右上角上方创建一条小消息,其中显示一些数据,即所选单元格的计数。更改前导选择时,应移动消息 但是我该怎么做呢?它不是一个工具提示,因为它是在用户单击表格并选择单元格时显示的,而不是通过将鼠标悬停在表格上 有什么建议吗 致以最良好的祝愿, htz 您可以使用类似于MsE

我有一个带有自定义
列表选择模型的
JTable
,其中包含自定义选择模式。此选择模式可确保仅在一行中进行选择,但有多个单元格。当用户单击选择表中的某些单元格时,选定的单元格与第一个选定的单元格都位于同一行中

现在,我想在前导选择单元格的右上角上方创建一条小消息,其中显示一些数据,即所选单元格的计数。更改前导选择时,应移动消息

但是我该怎么做呢?它不是一个工具提示,因为它是在用户单击表格并选择单元格时显示的,而不是通过将鼠标悬停在表格上

有什么建议吗

致以最良好的祝愿, htz

  • 您可以使用类似于MsExcell的效果为设置位置
它不是一个工具提示,因为它是在用户单击表格并选择单元格时显示的,而不是通过将鼠标悬停在表格上

  • 对于不可编辑的内容,您可以使用
    JPopup
    /
    JWindow
    而不是
    工具提示

  • JPopup
    /
    JWindow
    默认情况下不能包含可编辑的
    JComponent
    JTextComponents

  • 对于用户输入,您可以仅使用未修饰的
    JDialod

或者(不是很漂亮,但工作得很好),您可以利用JTable与其他所有组件一样是一个JComponent的事实,因此您可以向它添加子组件。您所要做的就是确保组件的大小和位置正确(这只是因为JTable使用空布局)

下面是一个带有JLabel的小演示,它显示所选项目的数量。标签将自动定位在第一个可见行上,除非它是当前lead选择,在这种情况下,标签将移动到第二个可见行:

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();
            }
        });
    }

}
导入java.awt.BorderLayout;
导入java.awt.Point;
导入java.util.Vector;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JScrollPane;
导入javax.swing.JTable;
导入javax.swing.ListSelectionModel;
导入javax.swing.SwingUtilities;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.event.ChangeEvent;
导入javax.swing.event.ChangeListener;
导入javax.swing.event.ListSelectionEvent;
导入javax.swing.event.ListSelectionListener;
公共类测试表{
受保护的void initUI(){
向量数据=新向量();
向量colNames=新向量();
对于(int i=0;i<5;i++){
添加(“Col-”+(i+1));
}
对于(int i=0;i<200;i++){
向量行=新向量();
对于(int j=0;j<5;j++){
添加(“单元格”+(i+1)+“-”+(j+1));
}
添加数据(行);
}
表=新的JTable(数据、列名称);
someText=newjlabel();
set不透明(true);
表.添加(某些文本);
表.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.getSelectionModel().addListSelectionListener(新ListSelectionListener()){
@凌驾
public void值已更改(ListSelectionEvent e){
int count=table.getSelectedRowCount();
someText.setText(“您当前已选择“+count+”项“+(count>1?”s):”);
layoutLabel();
}
});
JFrame=新JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
scrollpane=新的JScrollPane(表);
scrollpane.getViewport().addChangeListener(新的ChangeListener()){
@凌驾
公共无效状态已更改(更改事件e){
layoutLabel();
}
});
frame.add(滚动窗格,BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
私有JLabel someText;
专用JTable表;
私有JScrollPane滚动窗格;
私有void布局标签(){
someText.setSize(someText.getPreferredSize());
点位置=scrollpane.getViewport().getViewRect().getLocation();
int leadSelectionIndex=table.getSelectionModel().getLeadSelectionIndex();
如果(leadSelectionIndex>-1){
if(表格行点(位置)=引线选择索引){
location.y+=table.getRowHeight(leadSelectionIndex);
}
}
setLocation(位置);
}
publicstaticvoidmain(字符串[]args)抛出ClassNotFoundException、InstantiationException、IllegalAccessException、,
不受支持的LookandFeelException{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(新的Runnable(){
@凌驾
公开募捐{
新的TestTable().initUI();
}
});
}
}

另一个选项是实现每个组件的glassPane(1.7版的JLlayer角色之一,1.6版的JXLlayer角色之一),如下所示。请注意,我并没有试图美化这个位置(正如@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());
公共静态类工具提示扩展了{
私有层;
私人JToolTip工具提示;
@凌驾
public void installUI(JComponent c){
super.installUI(c);
this.layer=(JLayer)c;
安装玻璃窗格();
installListeners();
}
私有void installListeners(){
ListSelectionListener l=新建ListSelectionListener(){
@凌驾
public void值已更改(ListSelectionEvent e){
if(如getValueIsAdjusting())返回;
更新OLTIP