简体   繁体   English

如何使JTable单击未选中执行拖动而不是选择

[英]How to make JTable click on unselected do a drag instead of a select

If you have JTable set with table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) and then you click drag on a row that is not already selected, it starts selecting multiple rows. 如果您使用table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)设置JTable,然后单击拖动尚未选中的行,它将开始选择多行。 We don't want that behavior. 我们不希望这种行为。 We want it so if you click on a node, even if it's not already selected, it will start dragging it. 我们想要它,所以如果你点击一个节点,即使它还没有被选中,它也会开始拖动它。

We do need the multi select mode on, so setting it to single select (which does result in the behavior we want) is not an option. 我们确实需要启用多选模式,因此将其设置为单选(这会导致我们想要的行为)不是一个选项。

Update: At this point, it appears it will require some type of ugly hack since the logic is in a private method BasicTableUI$Handler.canStartDrag 更新:此时,它似乎需要某种类型的丑陋黑客,因为逻辑是在私有方法BasicTableUI $ Handler.canStartDrag

Unfortunately none of the other answers worked for me. 不幸的是,其他答案都没有对我有用。

So I made my own hack/fix for the problem (I'm posting it here for others with the same problem): 所以我为这个问题做了我自己的黑客/修复(我在这里发布它给其他有同样问题的人):

public class SFixTable extends JTable {
private static final long serialVersionUID = 1082882838948078289L;

boolean pressed = false;
int  currSRow = -100;

public SFixTable(TableModel dm) {
    super(dm);
}

public SFixTable() {
    super();
}

public SFixTable(Vector<?> rowData, Vector<?> columnNames) {
    super(rowData, columnNames);
}

@Override
protected void processMouseEvent(MouseEvent e) {
    int row = rowAtPoint(e.getPoint());
    int col = columnAtPoint(e.getPoint());
    if (SwingUtilities.isLeftMouseButton(e) && !e.isShiftDown() && !e.isControlDown()) {
        boolean isDragRelease = (e.getID() == MouseEvent.MOUSE_RELEASED) && row != currSRow;
        boolean isStartClick = (e.getID() == MouseEvent.MOUSE_PRESSED);

        if (row >= 0 && col >= 0) {
            if (isStartClick) {
                super.changeSelection(row, col, false, false);
            } else if (isDragRelease) {
                super.changeSelection(currSRow, col, false, false);
            }
        }
        pressed = (e.getID() == MouseEvent.MOUSE_PRESSED);
        if (pressed) {
            currSRow = row;
        } else {
            currSRow = -100;
        }
    }

    super.processMouseEvent(e);
}

@Override
public boolean isCellSelected(int row, int col) {
    return (pressed)? (row == currSRow) : super.isCellSelected(row, col);
}

}

I found one possible solution. 我找到了一个可能的解决方 You bracket the mouse listeners so you can lie to the call to isCellSelected during the canStartDrag call. 您可以将鼠标侦听器括起来,这样您就可以在canStartDrag调用期间调用isCellSelected。

Subclass JTable (or in my case, JXTreeTable). 子类JTable(或者在我的例子中,JXTreeTable)。 In the constructor call this: 在构造函数中调用:

private void setupSelectionDragHack()
{
    // Bracket the other mouse listeners so we may inject our lie
    final MouseListener[] ls = getMouseListeners();
    for (final MouseListener l : ls)
    {
        removeMouseListener(l);
    }
    addMouseListener(new MouseAdapter()
    {
        @Override
        public void mousePressed(final MouseEvent e)
        {
            // NOTE: it might not be necessary to check the row, but... I figure it's safer maybe?
            mousingRow = rowAtPoint(e.getPoint());
            mousingInProgress = true;
        }
    });
    for (final MouseListener l : ls)
    {
        addMouseListener(l);
    }
    addMouseListener(new MouseAdapter()
    {
        @Override
        public void mousePressed(final MouseEvent e)
        {
            mousingInProgress = false;
        }
    });
}

And then you'll need this: 然后你需要这个:

@Override
public boolean isCellSelected(final int row, final int column)
{
    if (mousingInProgress && row == mousingRow)
    {
        // Only lie to the canStartDrag caller. We tell the truth to everyone else.
        final StackTraceElement[] elms = Thread.currentThread().getStackTrace();
        for (int i = 0; i < 3; i++)
        {
            if (elms[i].getMethodName().equals("canStartDrag"))
            {
                return mousingInProgress;
            }
        }
    }
    return super.isCellSelected(row, column);
}

It's an ugly hack in many ways, but... for now it seems to work. 这在很多方面都是一个丑陋的黑客,但是......现在似乎有效。

If what you are looking for is to drag an unselected row in a single selection JTable, setting the table's selection model to SINGLE_SELECTION mode is not enough, you also have to set the column model's selection mode. 如果您要查找的是在单个选择JTable中拖动未选择的行,则将表的选择模型设置为SINGLE_SELECTION模式是不够的,您还必须设置列模型的选择模式。

JTable table = new JTable();
table.getSelectionModel()
     .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().getSelectionModel()
     .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

It's a bug: 这是一个错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223

and as you already assumed, it requires some ugly hack. 正如你已经假设的那样,它需要一些丑陋的黑客攻击。 Here's one (not from me, but from a user Aephyr on old sun forums which didn't survive the migration to OTN) 这是一个(不是来自我,而是来自老太阳论坛上的用户Aephyr,它在迁移到OTN后无法生存)

    table = new JTable() {
        // fix for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223
        // requirement is the option to turn off drag-selection if dragEnabled
        // fix posted in sun dev forum by Aephyr
        // http://forums.sun.com/thread.jspa?threadID=5436355&tstart=0
        private boolean pressed;

        @Override
        protected void processMouseEvent(MouseEvent e) {
                pressed = e.getID() == MouseEvent.MOUSE_PRESSED;
                if (pressed && !e.isShiftDown() && !e.isControlDown())
                        clearSelection();
                try {
                        super.processMouseEvent(e);
                } finally {
                        pressed = false;
                }
        }

        @Override
        public boolean isCellSelected(int row, int col) {
                return pressed ? true : super.isCellSelected(row, col);
        }

    };

Similar to kleopatra's answer, but this seems to handle a few issues with the previous one -- you can control-click to both add and remove items from a multiple selection, and you can successfully drag a multi-select group. 与kleopatra的答案类似,但这似乎可以处理前一个问题 - 您可以通过控制单击同时添加和删除多个选项中的项目,并且您可以成功拖动多选组。 I've tested this only with an ETable/Outline from NetBeans, but should work with a regular JTable. 我只使用NetBeans的ETable / Outline测试了这个,但是应该使用常规的JTable。

table = new JTable() {
    private boolean inPress = false;

    @Override protected void processMouseEvent(MouseEvent e) {
        inPress = e.getID() == MouseEvent.MOUSE_PRESSED && e.getButton() == MouseEvent.BUTTON1 && !e.isShiftDown() && !e.isControlDown();
        try {
            super.processMouseEvent(e);
        } finally {
            inPress = false;
        }
    }

    @Override public boolean isCellSelected(int row, int col) {
        boolean selected = super.isCellSelected(row, col);
        if (inPress) {
            if (!selected)
                clearSelection();
            return true;
        }

        return selected;
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使带有JComboBox的JTable仅在双击而不是单击时响应 - How to make JTable with JComboBox respond only on double click instead of single click 如何将文件拖放到 JTable 中? - How do I drag & drop files into a JTable? 如何在JTable中拖放行? - How do I drag and drop a row in a JTable? 如何在选择该表中的任何行后将JTable行设置为“未选定”状态? - How to make a JTable row to an “unselected” state after selected any row in that table? 单击拖放JTable - Single click in a drag and drop JTable 如何使JTable单元在单击时执行与双击不同的操作? - How can I make a JTable cell do different things on single-click than on double-click? 如何通过单击从jTable中选择对象 - how to select an object from a jTable by a click 如何通过在 java 中按下鼠标并拖动 jtable 来 select 几个连续的列 - how to select a few continuous columns by pressing mouse and drag in jtable in java 如何使带有mySQL数据的jtable出现在选项卡式窗格中,而不是显示在单独的窗口中? - How do I make a jtable with mySQL data appear in my tabbed pane instead of in a seperate window? "<i>Java Swing JTable;<\/i> Java Swing JTable;<\/b> <i>Right Click Menu (How do I get it to &quot;select&quot; aka highlight the row)<\/i>右键单击菜单(如何让它“选择”也就是突出显示该行)<\/b>" - Java Swing JTable; Right Click Menu (How do I get it to "select" aka highlight the row)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM