【问题标题】:How to show a message over leading selection cell in JTable?如何在 JTable 中的前导选择单元格上显示消息?
【发布时间】:2012-10-01 12:20:50
【问题描述】:

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

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

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

有什么建议吗?

最好的问候, 赫兹

【问题讨论】:

    标签: java swing jtable


    【解决方案1】:

    或者(不是很漂亮,但工作得很好),您可以利用 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();
                }
            });
        }
    
    }
    

    【讨论】:

    • 这正是我需要的!我刚刚将 Listener 更改为 TableColumnModelListener 以监听列选择的变化,并编辑了 layoutLabel()- 方法以在前导选择索引的右上角布局标签。谢谢!
    【解决方案2】:
    • 您可以将Locations 设置为ToolTip,效果与MsExcell 中类似,

    它不是工具提示,因为它旨在在用户单击表格并选择单元格时显示,而不是通过将鼠标悬停在其上。

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

    • JPopup/JWindow默认不能包含可编辑的JComponent(JTextComponents)

    • 对于用户输入,您只能使用未修饰的JDialod

    【讨论】:

      【解决方案3】:

      另一种选择是实现每个组件的 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());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-24
        • 2013-11-07
        • 2015-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多