Выбор нескольких строк в пользовательском JTable только с помощью mousePressed, mouseReleased и mouseDragged

У меня возникают проблемы при выборе и отмене выбора строк в моем пользовательском классе JTable.

Мой собственный класс расширяет JTable и реализует MouseListener и MouseMotionListener. Когда я нажимаю строку, я хочу, чтобы эта строка была выбрана; если нажата невыбранная строка, я хочу, чтобы она была отменена; код для выбора и отмены выбора строк в настоящее время находится в переопределенном методе changeSelection.

import javax.swing.*;
import javax.swing.table.TableModel;
import java.awt.event.*;

public class SelectFRCTable extends JTable implements MouseListener, MouseMotionListener {

  private boolean isPressed;
  private boolean isReleased;
  private boolean isDragged;

  public SelectFRCTable(TableModel model) {
    //Register for mouse events on the table.
    this.setModel(model);
    addMouseListener(this);
    addMouseMotionListener(this);
  }

  public void mousePressed(MouseEvent e) {
    System.out.println("Mouse Pressed: " + e.getClickCount());
    isPressed = true;
    isReleased = false;
  }

  public void mouseReleased(MouseEvent e) {
    System.out.println("Mouse Released: " + e.getClickCount());
    isPressed = false;
    isDragged = false;
    isReleased = true;
  }

  public void mouseEntered(MouseEvent e) {}

  public void mouseExited(MouseEvent e) {}

  public void mouseClicked(MouseEvent e) {
    System.out.println("Mouse Clicked: " + e.getClickCount());
  }

  public void mouseDragged(MouseEvent e) {
    System.out.println("Mouse Dragged: " + e.getClickCount());
    isDragged = true;
  }

  public void mouseMoved(MouseEvent e) {}

  @Override
  public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
    ListSelectionModel selectionModel = getSelectionModel();
    boolean selected = selectionModel.isSelectedIndex(rowIndex);

    if (selected) {
      selectionModel.removeSelectionInterval(rowIndex, rowIndex);
      getValueAt(rowIndex, columnIndex);
    } else if (!selected) {
      selectionModel.addSelectionInterval(rowIndex, rowIndex);
    }
  }
}


import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.Vector;

public class TableExample extends JFrame{

  public TableExample() {
    JFrame frame = new JFrame("Custom JTable Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(925,700);
    frame.setLayout(new GridBagLayout());

    // Create a table with all the events
    Vector<String> columns = new Vector<String>();
    Vector<Vector<String>> rows = new Vector<Vector<String>>();
    columns.add("Column 1");

    // Get information about each event and store it in a vector to eventually be loaded into a
    // table model.
    for (int i=0; i<30; i++) {
      String info = "Hello World";
      Vector<String> data = new Vector<String>();
      data.add(info);
      rows.add(data);
    }

    // Create table model and configure it so that none of the cells are editable.
    TableModel model = new DefaultTableModel(rows, columns) {
      public Class getColumnClass(int column) {
        Class returnValue;
        if ((column >= 0) && (column < getColumnCount())) {
          returnValue = getValueAt(0, column).getClass();
        } else {
          returnValue = Object.class;
        }
        return returnValue;
      }
      public boolean isCellEditable(int row, int column) {
        return false; //This causes all cells to be not editable
      }
    };

    // Create custom table
    SelectFRCTable table = new SelectFRCTable(model);

    // Add the table to a scrollable pane
    JScrollPane scrollPane = new JScrollPane(table);
    add(scrollPane, BorderLayout.CENTER);

    pack();
    setVisible(true);
  }
}

Текущий код работает до определенной степени. Он выбирает строку, если пользователь нажимает указанную строку, и отменяет выбор выбранной строки, если пользователь снова нажимает указанную строку. Однако, если пользователь нажимает строку и выбирает ее, а затем продолжает удерживать левую кнопку мыши и перемещает курсор после ее выбора, строка затем отменяется, затем снова выделяется, затем снова отменяется и так далее, и так далее до тех пор, пока пользователь отпускает левую кнопку мыши.

Это результат использования текущих условий для выполнения операторов if/else-if в методе changeSelection. Я пробовал различные другие условия, которые также используют комбинацию глобальных логических переменных isPressed, isReleased и isDragged, но пока мне не удалось найти работающее решение.

У кого-нибудь есть идеи?

Любая помощь приветствуется, заранее спасибо.


person Chris C.    schedule 24.07.2019    source источник


Ответы (1)


Я нашел решение своей первоначальной проблемы, которое также работает с включенным перетаскиванием:

import javax.swing.*;
import javax.swing.table.TableModel;
import java.awt.event.*;

public class SelectFRCTable extends JTable implements MouseListener, MouseMotionListener {

  private boolean selectionDetermined;
  private boolean isSelecting;
  private boolean isDeselecting;

  public SelectFRCTable(TableModel model) {
    //Register for mouse events on the table.
    this.setModel(model);
    addMouseListener(this);
    addMouseMotionListener(this);
  }

  public void mousePressed(MouseEvent e) {}

  public void mouseReleased(MouseEvent e) {
    selectionDetermined = false;
    isSelecting = false;
    isDeselecting = false;
  }

  public void mouseEntered(MouseEvent e) {}

  public void mouseExited(MouseEvent e) {}

  public void mouseClicked(MouseEvent e) {}

  public void mouseDragged(MouseEvent e) {}

  public void mouseMoved(MouseEvent e) {}

  @Override
  public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
    ListSelectionModel selectionModel = getSelectionModel();
    boolean selected = selectionModel.isSelectedIndex(rowIndex);

    if (selected && !selectionDetermined) {
      selectionDetermined = true;
      isSelecting = false;
      isDeselecting = true;
    } else if (!selected && !selectionDetermined) {
      selectionDetermined = true;
      isSelecting = true;
      isDeselecting = false;
    }

    if (isSelecting && !selected) {
      selectionModel.addSelectionInterval(rowIndex, rowIndex);
    } else if (isDeselecting && selected) {
      selectionModel.removeSelectionInterval(rowIndex, rowIndex);
    }
  }
}

Флаги устанавливаются, когда мышь отпускается, и эти флаги используются в методе changeSelection() в качестве условий для операторов if\else-if.

person Chris C.    schedule 24.07.2019