更改 Ctrl + JTable 上的单击行为

发布于 2024-07-15 03:29:22 字数 3020 浏览 6 评论 0原文

当按下键盘按钮(即 CTRL 按钮)并选择一行时,是否有一种简单的方法来操作 JTable 上的控件以提供不同的功能? 我被要求创建一个表,其中行上的 CTRL + 单击(鼠标单击)只会取消选择选定的行,而不会选择行。 如果用户 CTRL + 单击未选定的行,则不会发生任何情况。

我已经能够创建一个表格,并禁用 CTRL + A(全选)等功能,并且我已经能够检查生成 MouseEvent 时是否按下了控制按钮,但我似乎无法弄清楚了解如何调整 CTRL + 单击。 这是一些代码:

package nicky;

import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;

public class TableTester extends JPanel {
    public TableTester() {
        super(new GridLayout(1,0));

        final String[] columnNames = {"First Name",
                                      "Last Name",
                                      "Sport",
                                      "# of Years",
                                      "Vegetarian"};

        final Object[][] data = {
            {"Tom",   "Roberts","Athletic", new Integer(5),  new Boolean(false)},
            {"Sarah", "Watt",   "Football", new Integer(3),  new Boolean(true)},
            {"Laura", "Brown",  "Swimming", new Integer(2),  new Boolean(false)},
            {"Simon", "Smith",  "Tennis",   new Integer(20), new Boolean(true)},
            {"Paul",  "Jones",  "Rugby",    new Integer(10), new Boolean(false)}
        };

        JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(500, 100));

        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

        table.addMouseListener(new MouseListener(){
            public void mouseEntered(MouseEvent me){}
            public void mouseExited(MouseEvent me){}
            public void mouseReleased(MouseEvent me){}
            public void mouseClicked(MouseEvent me){}
            public void mousePressed(MouseEvent me){
                if (me.isControlDown()){
                    System.out.println("This is working ");
                }
            }
        });

        InputMap inputMap = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK);
        inputMap.put(keyStroke, "none");

        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
    }

    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("TableTester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        TableTester newContentPane = new TableTester();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

在 mousePressed 方法中,我尝试从表中获取所有选定的行,然后检查新单击的行是否在 selectedRows 中...但是,我不确定是否有是一种查看哪一行与 MouseEvent 关联的方法。

(另外,我知道这样的预期行为不应该被玩弄太多,但它是为了复制公司中的遗留系统)

任何想法/建议将不胜感激!

Is there an easy way to manipulate the controls on a JTable to give different functionality when there is a keyboard button pressed (ie. CTRL button) and a row is selected? I've been asked to create a table where the CTRL + Click (mouse click) on a row will only deselect a selected row, never select a row. If the user CTRL + Clicks an unselected row, nothing will happen.

I've been able to create a table, and disable functions like CTRL + A (select all), and i've been able to check if the control button is pressed when a MouseEvent is generated, but I can't seem to figure out how the CTRL + Click can be adjusted. Here's some code:

package nicky;

import javax.swing.*;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;

public class TableTester extends JPanel {
    public TableTester() {
        super(new GridLayout(1,0));

        final String[] columnNames = {"First Name",
                                      "Last Name",
                                      "Sport",
                                      "# of Years",
                                      "Vegetarian"};

        final Object[][] data = {
            {"Tom",   "Roberts","Athletic", new Integer(5),  new Boolean(false)},
            {"Sarah", "Watt",   "Football", new Integer(3),  new Boolean(true)},
            {"Laura", "Brown",  "Swimming", new Integer(2),  new Boolean(false)},
            {"Simon", "Smith",  "Tennis",   new Integer(20), new Boolean(true)},
            {"Paul",  "Jones",  "Rugby",    new Integer(10), new Boolean(false)}
        };

        JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(500, 100));

        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

        table.addMouseListener(new MouseListener(){
            public void mouseEntered(MouseEvent me){}
            public void mouseExited(MouseEvent me){}
            public void mouseReleased(MouseEvent me){}
            public void mouseClicked(MouseEvent me){}
            public void mousePressed(MouseEvent me){
                if (me.isControlDown()){
                    System.out.println("This is working ");
                }
            }
        });

        InputMap inputMap = table.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK);
        inputMap.put(keyStroke, "none");

        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
    }

    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("TableTester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        TableTester newContentPane = new TableTester();
        newContentPane.setOpaque(true);
        frame.setContentPane(newContentPane);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

In the mousePressed method I've played around with getting all the selected rows from the table, and was then going to check if the newly clicked row was in the selectedRows... However, I'm not sure if there is a way to see which row is associated with the MouseEvent.

(Also, I know expected behaviour such as this shouldn't be played around with too much, but it's to replicate a legacy system in the company)

Any ideas/suggestions would be appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仙女山的月亮 2024-07-22 03:29:22

好的,第二个(我留下了第一个,因为它可能会对其他用途感兴趣,谁知道?说它是出于教育目的......:-))。

我查看了JTable的源代码,发现鼠标事件是由外观处理的。 知道它如何处理控制键,我可以安全地重写 changeSelection 方法来执行您需要的操作。
我发现要求有点奇怪(您仍然可以使用 Shift+单击,不是吗?)但我不知道上下文。

class SpecialTable extends JTable
{
    SpecialTable(Object[][] data, String[] columnNames)
    {
        super(data, columnNames);
// That's already the default        
//        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }

    /**
     * Called by javax.swing.plaf.basic.BasicTableUI.Handler.adjustSelection(MouseEvent)
     * like: table.changeSelection(pressedRow, pressedCol, e.isControlDown(), e.isShiftDown());
     */
    @Override
    public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend)
    {
        if (toggle && !isRowSelected(rowIndex))
            return; // Don't do the selection
        super.changeSelection(rowIndex, columnIndex, toggle, extend);
    }
}

更简单,正是您所需要的!

顺便说一句,感谢您提供如此简单的良好测试用例,如果我必须自己编写它,我可能不会尝试...:-D 这是一个有趣的学习挑战。

OK, second take (I left the first one as it might interest somebody for some other usage, who know? Say it is there for educational purpose... :-)).

I had a look at the source code of JTable and found out that mouse events are handled by the look and feel. Knowing how it handles the control key, I could safely override the changeSelection method to do what you need.
I find requirements a bit strange (you can still use Shift+click, no?) but I don't know context.

class SpecialTable extends JTable
{
    SpecialTable(Object[][] data, String[] columnNames)
    {
        super(data, columnNames);
// That's already the default        
//        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }

    /**
     * Called by javax.swing.plaf.basic.BasicTableUI.Handler.adjustSelection(MouseEvent)
     * like: table.changeSelection(pressedRow, pressedCol, e.isControlDown(), e.isShiftDown());
     */
    @Override
    public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend)
    {
        if (toggle && !isRowSelected(rowIndex))
            return; // Don't do the selection
        super.changeSelection(rowIndex, columnIndex, toggle, extend);
    }
}

Much simpler and exactly what you need!

BTW, thanks for providing such simple good test case, I might have not tried if I had to write it myself... :-D It was an interesting and learning challenge.

忆离笙 2024-07-22 03:29:22

我通过以下方法取得了成功,尽管我不确定这是最好的方法...

class SpecialTable extends JTable
{
    boolean bIsControlDown;
    int clickedRow;

    SpecialTable(Object[][] data, String[] columnNames)
    {
        super(data, columnNames);
//        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        getSelectionModel().addListSelectionListener(this);
        addMouseListener(new MouseInputAdapter()
        {
            public void mousePressed(MouseEvent me)
            {
                bIsControlDown = me.isControlDown();
                clickedRow = rowAtPoint(me.getPoint());
            }
        });
    }

    public void valueChanged(ListSelectionEvent evt)  
    {
        super.valueChanged(evt);
        if (bIsControlDown)
        {
            if (!evt.getValueIsAdjusting())
            {
//                System.out.println(evt);
//                System.out.println("=> " + clickedRow);
                getSelectionModel().removeSelectionInterval(clickedRow, clickedRow);
            }
        }
    }
}

仅将代码中定义 table 的行替换为:

    JTable table = new SpecialTable(data, columnNames);
    table.setPreferredScrollableViewportSize(new Dimension(500, 100));

当您按住 Control 键单击未选择的行时,它会被短暂选择,然后取消选择。

I had success with the following, although I am not sure that's the best method...

class SpecialTable extends JTable
{
    boolean bIsControlDown;
    int clickedRow;

    SpecialTable(Object[][] data, String[] columnNames)
    {
        super(data, columnNames);
//        setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        getSelectionModel().addListSelectionListener(this);
        addMouseListener(new MouseInputAdapter()
        {
            public void mousePressed(MouseEvent me)
            {
                bIsControlDown = me.isControlDown();
                clickedRow = rowAtPoint(me.getPoint());
            }
        });
    }

    public void valueChanged(ListSelectionEvent evt)  
    {
        super.valueChanged(evt);
        if (bIsControlDown)
        {
            if (!evt.getValueIsAdjusting())
            {
//                System.out.println(evt);
//                System.out.println("=> " + clickedRow);
                getSelectionModel().removeSelectionInterval(clickedRow, clickedRow);
            }
        }
    }
}

Replace the lines defining table in your code with only:

    JTable table = new SpecialTable(data, columnNames);
    table.setPreferredScrollableViewportSize(new Dimension(500, 100));

When you control-click an unselected row, it is briefly selected, then unselected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文