【问题标题】:Detect multiple double-clicks/Reset MouseEvent?检测多次双击/重置鼠标事件?
【发布时间】:2019-07-11 22:22:23
【问题描述】:

我正在尝试使用JTables 编写自定义文件导航器来导航文件系统。我遇到的问题是,只要您按住按钮,鼠标事件就会一直持续下去,所以如果有人试图通过不断双击“上一层”字段来上多层(因为它没有t 移动),它只会回到一个目录,除非他们长时间停止点击。因此,我意识到这是由于 MouseEvent 仍然处于活动状态。

我很确定我可以简单地通过 if(e.getClickCount() % 2 == 0) 做我想做的事,但这感觉像是一个不正确的解决方法。是否有更好/更正确的方法来执行此操作,例如在初始双击后重置MouseEvent?甚至可以手动重置MouseEvent 吗?如果有,怎么做?

编辑:恢复为一体式代码,以便于复制/粘贴:

package main;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;

public class Main {

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

class CreateFrame extends JFrame {
    public CreateFrame() {
        setPreferredSize(new Dimension(800, 600));
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        setContentPane(new LocalNavigator());
        pack();
        setVisible(true);
    }

    class LocalTable extends JTable {

        private DefaultTableModel dtm;
        private File path;
        private FileSystemView fsv = FileSystemView.getFileSystemView();

        public LocalTable() {
            String[] header = new String[] { "Icon", "File/Folder Name", "File Type" };

            dtm = new DefaultTableModel() {
                @Override
                public boolean isCellEditable(int row, int column) {
                    return false;
                }

                @Override
                public Class<?> getColumnClass(int column) {
                    if (getRowCount() > 0) {
                        return getValueAt(0, column).getClass();
                    }

                    return super.getColumnClass(column);
                }
            };
            dtm.setColumnIdentifiers(header);
            setAutoCreateRowSorter(true);
            setRowHeight(25);
            setModel(dtm);

            addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    if (e.getClickCount() == 2) {
                        JTable table = (JTable) e.getSource();
                        Point p = e.getPoint();
                        int row = table.rowAtPoint(p);
                        String type = getValueAt(row, 2).toString().toLowerCase();
                        if (type.contains("root") || type.contains("folder")) {
                            File file = new File((path != null ? path + "/" + getValueAt(row, 1) : getValueAt(row, 1).toString()));
                            if (file != null)
                                repopulateFileFolderList(file);
                        } else if (getValueAt(row, 1).toString().toLowerCase().contains("up one")
                            && getValueAt(row, 2).toString().equals("")) {
                            File file = path.getParentFile();
                            if (file != null)
                                repopulateFileFolderList(file);
                            else
                                getTableRoot();
                        } else {
                            System.out.println("Not a directory!");
                        }

                    }
                }
            });
        }

        public void getTableRoot() {
            path = null;
            while (dtm.getRowCount() > 0) {
                dtm.removeRow(0);
            }
            File[] roots = File.listRoots();
            for (File root : roots) {
                dtm.addRow(new Object[] { fsv.getSystemIcon(root), root.getAbsoluteFile(), "Root Directory" });
            }
        }

        private void repopulateFileFolderList(File folder) {
            path = folder;
            while (dtm.getRowCount() > 0) {
                dtm.removeRow(0);
            }
            dtm.addRow(new Object[] { fsv.getSystemIcon(folder), "Up One Level", "" });
            File[] files = folder.listFiles();
            for (File file : files) {
                dtm.addRow(new Object[] { fsv.getSystemIcon(file), file.getName(),
                    (file.isDirectory() ? "Folder" : file.isFile() ? "File" : "Unknown") });
            }
        }
    }

    class LocalNavigator extends JPanel {

        private LocalTable localTable;

        public LocalNavigator() {
            setLayout(new BorderLayout());

            localTable = new LocalTable();
            localTable.getTableRoot();

            JScrollPane lTree = new JScrollPane(localTable);

            add(lTree, "Center");

            TableColumnModel columns = localTable.getColumnModel();
            for (int c = 0;c < columns.getColumnCount();c++) {
                if (c == 0)
                    columns.getColumn(c).setMaxWidth(25);
                else
                    columns.getColumn(c).setPreferredWidth(50);
            }
        }
    }
}

【问题讨论】:

  • 考虑提供一个runnable example 来证明您的问题。这将导致更少的混乱和更好的响应
  • 我会这样做的,谢谢。给我一点时间来编辑掉多余的垃圾......
  • 创建了一个简单的工作示例并替换了部分代码。
  • 一个 MCVE 应该是一个源文件(可能包含一个以上的类),并且包含导入。
  • 啊,谢谢你澄清......我已经恢复到我之前的例子......不像网络上那样整洁,但我想复制/粘贴能力弥补了它...

标签: java swing mouseevent double-click


【解决方案1】:

在您的要求中,您解释说您希望允许快速延迟的双击。 但是您使用的e.getClickCount()==2 不是解决方案,因为它受您的操作系统配置的限制。 你可以通过查看Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval")的结果得到它

绕过该问题的一个简单而好的方法是您自己处理鼠标侦听器中两次单击之间的延迟。 您可以使用计时器,您可以在其中选择点击之间的最大间隔并自行处理计数。

解决方案相当简单。因此,由于您的代码是可测试的,因此我直接对其进行了修改并进行了测试。这个对我有用。 总结一下我的修改,我添加了一个布尔实例来计算当前点击次数 并将双击检测(技术)和双击处理(逻辑)分开在两个地方。它更具可读性。 我选择了 0.5 秒作为两次点击之间授权的最大延迟。 您可以选择其他值,但如果该值太重要(例如一秒或更长时间),可能会导致意外的双击。

class CreateFrame extends JFrame {
    ...
   private boolean isAlreadyOneClick;
   ...
   addMouseListener(new MouseAdapter() {

    @Override
    public void mouseClicked(MouseEvent e) {

        if (isAlreadyOneClick) {
           handleDoubleClick(e);
           isAlreadyOneClick = false;
        }
        else {
           isAlreadyOneClick = true;
           Timer t = new Timer("doubleclickTimer", false);
           t.schedule(new TimerTask() {

            @Override
            public void run() {
               isAlreadyOneClick = false;
            }
           }, 500);
        }

    }

    private void handleDoubleClick(MouseEvent e) {
        JTable table = (JTable) e.getSource();
        Point p = e.getPoint();
        int row = table.rowAtPoint(p);
        String type = getValueAt(row, 2).toString().toLowerCase();
        if (type.contains("root") || type.contains("folder")) {
        File file = new File((path != null ? path + "/" + getValueAt(row, 1) : getValueAt(row, 1).toString()));
        if (file != null)
            repopulateFileFolderList(file);
        }
        else if (getValueAt(row, 1).toString().toLowerCase().contains("up one")
            && getValueAt(row, 2).toString().equals("")) {
        File file = path.getParentFile();
        if (file != null)
            repopulateFileFolderList(file);
        else getTableRoot();
        }
        else {
        System.out.println("Not a directory!");
        }
    }
    }

【讨论】:

    猜你喜欢
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 2012-01-14
    • 2023-04-04
    • 2010-09-24
    • 1970-01-01
    相关资源
    最近更新 更多