[英]Disable drag selection in JTable
Problem 问题
I'd like to click on an unselected cell in a JTable and drag it, ie the table should be in drag mode. 我想点击JTable中一个未选中的单元格并拖动它,即表格应该处于拖动模式。 The problem is that the JTable has a mechanism that when you click on an unselected cell and drag, you actually aren't in drag mode, but in selection mode. 问题是JTable有一种机制,当你点击一个未选择的单元格并拖动时,你实际上不是处于拖动模式,而是处于选择模式。 Selection mode should only be possible via click and should be extendable via shift + click, not via dragging. 选择模式应该只能通过点击进行,并且可以通过shift +点击进行扩展,而不是通过拖动进行扩展。
From what I've found the culprit is in BasicTableUI, but unfortunately everything there that's relevant is private. 从我发现的罪魁祸首是在BasicTableUI,但不幸的是那里的相关内容是私有的。
Question 题
How can you prevent selection via dragging and be instantly in drag mode when you click on an unselected cell and drag it? 当您单击未选择的单元格并拖动它时,如何通过拖动阻止选择并立即处于拖动模式?
I searched, but none of the solutions I found were satisfactory. 我搜索过,但我找到的解决方案都没有令人满意。 Or they were for older Java versions. 或者它们适用于较旧的Java版本。
Code 码
Here's some code for the reproduction: 这是复制的一些代码:
The code: 编码:
import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.DropMode;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
public class Main {
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
Object rowData[][] = {
{ "a", "a", "a" },
{ "a", "a", "a" },
{ "a", "a", "a" },
{ "a", "a", "a" },
{ "a", "a", "a" },
};
Object columnNames[] = { "Column 1", "Column 2", "Column 3" };
final JTable table = new JTable( rowData, columnNames);
table.setDragEnabled( true);
table.setDropMode( DropMode.INSERT_ROWS);
table.addMouseMotionListener( new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
boolean selectionIsAdjusting = table.getSelectionModel().getValueIsAdjusting();
if( selectionIsAdjusting) {
System.out.println("selecting");
} else {
System.out.println("dragging");
}
}
});
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(true);
JScrollPane scrollPane = new JScrollPane( table);
frame.add( scrollPane, BorderLayout.CENTER);
frame.setSize( 300, 150);
frame.setVisible( true);
}
}
Screenshot: 截图:
Thank you very much for the help! 非常感谢你的帮助!
You might be able to directly call TransferHandler#exportAsDrag(...) method in MouseMotionListener#mouseDragged(...)
: 您可以在MouseMotionListener#mouseDragged(...)
直接调用TransferHandler #exportAsDrag(...)方法:
import java.awt.*;
import java.awt.event.*;
import java.util.Optional;
import javax.swing.*;
import javax.swing.table.*;
public class Main2 {
public JComponent makeUI() {
Object columnNames[] = {"Column 1", "Column 2", "Column 3"};
Object data[][] = {
{ "a", "a", "a" },
{ "a", "a", "a" },
{ "a", "a", "a" },
{ "a", "a", "a" },
{ "a", "a", "a" },
};
JTable table = new JTable(new DefaultTableModel(data, columnNames));
table.setDragEnabled(true);
table.setDropMode(DropMode.INSERT_ROWS);
table.addMouseMotionListener(new MouseAdapter() {
@Override public void mouseDragged(MouseEvent e) {
JComponent c = (JComponent) e.getComponent();
Optional.ofNullable(c.getTransferHandler())
.ifPresent(th -> th.exportAsDrag(c, e, TransferHandler.COPY));
}
});
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(true);
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
p.add(new JTextField(), BorderLayout.SOUTH);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new Main2().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
Selection mode should only be possible via click and should be extendable via shift + click, not via dragging 选择模式应该只能通过点击进行,并且可以通过shift +点击进行扩展,而不是通过拖动进行扩展
You may be able to alter the behavior by overriding JTable's processMouseEvent
method with some additional logic. 您可以通过使用一些额外的逻辑覆盖JTable的processMouseEvent
方法来改变行为。 When a button down event occurs - and shift is not down - alter the selection of the JTable to the current clicked row before calling the parent method. 当发生按钮按下事件 - 并且shift没有停止时 - 在调用父方法之前将JTable的选择更改为当前单击的行。
JTable table = new JTable( rowData, columnNames){
@Override
public void processMouseEvent(MouseEvent e){
Component c = (Component)e.getSource();
if (e.getModifiersEx() == MouseEvent.BUTTON1_DOWN_MASK && ( e.getModifiers() & MouseEvent.SHIFT_DOWN_MASK) == 0 ){
int row = rowAtPoint(e.getPoint());
int col = columnAtPoint(e.getPoint());
if ( !isCellSelected(row, col) ){
clearSelection();
changeSelection(row, col, false, false);
}
}
MouseEvent e1 = new MouseEvent(c, e.getID(), e.getWhen(),
e.getModifiers() | InputEvent.CTRL_MASK,
e.getX(), e.getY(),
e.getClickCount(),
e.isPopupTrigger() ,
e.getButton());
super.processMouseEvent(e1);
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.