Java表格单元格渲染器仅在首次单击后才处于活动状态

时间:2012-12-07 12:04:58

标签: java swing

我创建了一个用于即时交互的表(对于数独求解器),但只有在我单击进入单元格后,鼠标事件(进入,退出,单击)才会到达单元格渲染器。 (对于每个单元格,我必须在激活渲染器之前单击一次。稍后返回该单元格,它将立即生效。)

如何更改代码以立即激活表格单元格?或者我可以找到第一次鼠标点击发生了什么,所以我可以在创建表后立即执行这些操作? (我试图在UI层次结构的所有级别捕获鼠标事件,但找不到它。)

我已将表格缩小到最小1x1并删除了所有不必要的代码。其余代码显示如下。请注意,鼠标悬停(显示一个小的黑色方块)仅在单击一次后才会激活。 (代码完整,可以按原样编译。)

import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.EventObject;


public class GUI extends JFrame
{
  private class Table extends JTable
  {
    public Table()
    {
      super(new AbstractTableModel()
        {
          public int getRowCount() { return 1; }
          public int getColumnCount() { return 1; }
          public Object getValueAt(int x, int y) { return null; }
          @Override public boolean isCellEditable(int x, int y) { return true; }
        });
    }
    @Override public TableCellRenderer getCellRenderer(int x, int y) { return new Editor(); }
    @Override public TableCellEditor getCellEditor(int x, int y) { return new Editor(); }
  }

  private class Editor extends JComponent implements TableCellEditor, TableCellRenderer, MouseListener
  {
    private boolean hasFocus = false;

    public Editor()
    {
      addMouseListener(this);
    }

    @Override public void paintComponent(Graphics g)
    {
      if (hasFocus)
      {
        g.fillRect(0, 0, 9, 9);
      }
    }

    public void mouseEntered(MouseEvent e)
    {
      hasFocus = true;
      repaint();
    }

    public void mouseExited(MouseEvent e)
    {
      hasFocus = false;
      repaint();
    }

    public void mouseClicked(MouseEvent e) { }
    public void mousePressed(MouseEvent e) { }
    public void mouseReleased(MouseEvent e) { }

    public Object getCellEditorValue() { return 0; }
    public boolean isCellEditable(EventObject e) { return true; }
    public boolean shouldSelectCell(EventObject e) { return false; }
    public boolean stopCellEditing() { return true; }
    public void cancelCellEditing() { }
    public void addCellEditorListener(CellEditorListener l) { }
    public void removeCellEditorListener(CellEditorListener l) { }
    public Component getTableCellEditorComponent(JTable t, Object v, boolean s, int x, int y) { return this; }
    public Component getTableCellRendererComponent(JTable t, Object v, boolean s, boolean f, int x, int y) { return this; }
  }

  public static void main(String[] args)
  {
    new GUI();
  }

  public GUI()
  {
    setContentPane(new Table());
    setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE);
    pack();
    setVisible(true);
  }
}

1 个答案:

答案 0 :(得分:1)

那是因为渲染器不应该处理事件。渲染器是一个独特的组件,仅用于绘制表或列中的每个单元格。

当表格自我绘制时,它会遍历单元格。对于每个单元格,修改渲染器组件,然后获取渲染器组件的“屏幕截图”并将其粘贴到表格单元格中。所以它无法处理事件。您应该在表本身上添加一个事件侦听器。不在渲染器上。

单击后,它可以正常工作,因为渲染器也是编辑器,编辑器可以处理事件。但在我看来,你的桌子实际上是不可编辑的,你根本就没有编辑器。而是在表上添加一个监听器。