JavaFX2: 鼠标拖动选择和Ctrl+Shift连续区间选择的ListView
JavaFX2的ListView中的多选没有提供鼠标拖动选择的功能,同时按下Ctrl和Shift后连续的区间选中也不支持,以下代码用于处理这两个问题,细节见代码注释:
import com.sun.javafx.scene.control.skin.ListViewSkin;
import com.sun.javafx.scene.control.skin.VirtualFlow;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.control.IndexedCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.input.MouseEvent; /**
* 该类增强了ListView本身的行中选中功能.
* <br/>1. 鼠标拖动选中
* <br/>2. 连续Ctrl+Shift区间选中
*
* 其中使用VirtualFlow vf = ((VirtualFlow) ((ListViewSkin)
* getChildrenUnmodifiable().get(0)).getChildrenUnmodifiable().get(0));来判断当前显示可见的行号,
* 使用setOnMousePressed/setOnMouseDragged/setOnMouseReleased来处理增强的拖动和Ctrl+Shift选中事件.
*
* 遗留问题: 当Ctrl+Shift操作后一次鼠标点击在一个已经选中的行时, 最后的结果会取消选中该行.
* 如果还需要添加其他鼠标事件而需要使用到选中状态时可能会有冲突, 还未测试.
*
* @author Alan Zeng
*/
public class DragSelectionListView<T extends Object> extends ListView<T> { /**
* 鼠标拖动之前ListView的选中状态. 在鼠标拖动的过程中需要根据拖动事件的起始行号和当前行号来计算新选中的行,
* 同事和原始选中状态结合作为新的选中状态.
*/
private ObservableList<Integer> oldSelectedIndices;
/**
* 鼠标拖动事件是否已经开始. 会在MouseDragged中设置为true, 在MouseReleased中重置为false
*/
private boolean isDragStarted = false;
/**
* 最后一次鼠标点击选中的行号. 每次鼠标点击时都会进行记录
*/
private int lastPressedRow;
/**
* 鼠标拖动事件的起始行. 会在MousePressed中设置为当前点击行, 在MouseReleased中重置为-1
*/
private int dragStartedRow = -1;
/**
* 上一次拖动经过的行号. 鼠标拖动事件过程中, 会不断的触发MouseDragged事件, 每次事件结束时记录鼠标所在行号,
* 在MouseReleased中重置为-1
*/
private int prevDragRow = -1; public DragSelectionListView() {
getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
addDragSelectionEventHandlers();
} public DragSelectionListView(ObservableList<T> ol) {
super(ol);
getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
addDragSelectionEventHandlers();
} /**
* 根据相对于ListView的坐标,获取鼠标所在行
*
* @param x
* @param y
* @return
*/
public int getRowAtPoint(double x, double y) {
int row = -1;
VirtualFlow vf = ((VirtualFlow) ((ListViewSkin) getChildrenUnmodifiable().get(0)).getChildrenUnmodifiable().get(0));
int firstIndex = vf.getFirstVisibleCell().getIndex();
int lastIndex = vf.getLastVisibleCell().getIndex();
for (int i = firstIndex; i <= lastIndex; i++) {
IndexedCell visibleCell = vf.getVisibleCell(i);
if (visibleCell.getBoundsInParent().contains(x, y)) {
row = i;
break;
}
}
return row;
} /**
* 获取当前显示出来的第一行行号
*
* @return
*/
public int getFirstVisibleRow() {
VirtualFlow vf = ((VirtualFlow) ((ListViewSkin) getChildrenUnmodifiable().get(0)).getChildrenUnmodifiable().get(0));
return vf.getFirstVisibleCell().getIndex();
} /**
* 获取当前显示出来的最后一行行号
*
* @return
*/
public int getLastVisibleRow() {
VirtualFlow vf = ((VirtualFlow) ((ListViewSkin) getChildrenUnmodifiable().get(0)).getChildrenUnmodifiable().get(0));
return vf.getLastVisibleCell().getIndex();
} /**
* 添加用于处理拖动选中和连续Ctrl+Shift选中的事件: MousePressed/MouseDraggedMouseReleased
*/
private void addDragSelectionEventHandlers() {
setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
final int rowAtPoint = getRowAtPoint(t.getX(), t.getY()); //<editor-fold defaultstate="collapsed" desc="当Shift和Ctrl键同时按下时,会增加选中鼠标两次点击之间的行(不分左右键)">
if (t.isControlDown() && t.isShiftDown()) {
final int min = Math.min(rowAtPoint, lastPressedRow);
final int max = Math.max(rowAtPoint, lastPressedRow);
DragSelectionListView.this.getSelectionModel().selectRange(min, max + 1);
}
//</editor-fold> dragStartedRow = rowAtPoint;
lastPressedRow = rowAtPoint;
}
});
setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
int rowAtPoint = getRowAtPoint(t.getX(), t.getY());
if (prevDragRow == rowAtPoint) {
return;
} ObservableList<Integer> selectedIndices = DragSelectionListView.this.getSelectionModel().getSelectedIndices();
if (!isDragStarted) {
oldSelectedIndices = FXCollections.observableArrayList(selectedIndices);
isDragStarted = true;
} else {
DragSelectionListView.this.getSelectionModel().clearSelection();
for (Integer integer : oldSelectedIndices) {
DragSelectionListView.this.getSelectionModel().selectIndices(integer);
} if (dragStartedRow != -1) {
DragSelectionListView.this.getSelectionModel().selectRange(Math.min(rowAtPoint, dragStartedRow), Math.max(rowAtPoint, dragStartedRow) + 1);
}
} prevDragRow = rowAtPoint;
}
});
setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
//下面主要是重置Drag完毕后的一些状态
dragStartedRow = -1;
prevDragRow = -1;
isDragStarted = false;
}
});
}
}
JavaFX2: 鼠标拖动选择和Ctrl+Shift连续区间选择的ListView的更多相关文章
- Ctrl+Shift+F12切换最大化编辑器
常用快捷键(keymaps:Default情况下) Esc键编辑器(从工具窗口) F1帮助千万别按,很卡! F2(Shift+F2)下/上高亮错误或警告快速定位 F3向下查找关键字出现位置 F4查找变 ...
- (转)Eclipse快捷键大全,导包快捷键:ctrl+Shift+/
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当前行到上一行(复制增加)Alt+↓ 当 ...
- Eclipse快捷键大全,导包快捷键:ctrl+Shift+/【转】
Ctrl+Shift+L 显示所有快捷键 Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复 ...
- CTRL+SHIFT
CTRL+SHIFT+鼠标左右,上下拖动,可快速实现平行和垂直上下复制的功能,
- 【editplus经常用的快捷键】Editplus 选中一行ctrl+r,Edit 合并行 Ctrl+Shift+J 合并选定行 删除当前行
Editplus 选中一行: ctrl+rEditplus 复制一行: ctrl+r选择行,然后ctrl+c复制.复制一行到下一行中:Editplus有:Ctrl+j 复制上一行的一个字符到当前行Ed ...
- echats 油表盘 鼠标拖动指针改变数值
近期需要做一个鼠标拖动完成油表盘数值改变的功能,使用canvas感觉太麻烦,而且指针不太好监听和拖动,只能另谋出路,在网上参考了某位大神的操作,最终选择了echats来解决这个问题.废话不多说,直接上 ...
- python模拟鼠标拖动操作的方法
本文实例讲述了python模拟鼠标拖动操作的方法.分享给大家供大家参考.具体如下: pdf中的书签只有页码,准备把现有书签拖到一个目录中,然后添加自己页签.重复的拖动工作实在无趣,还是让程序帮我实现吧 ...
- listbox鼠标拖动数据和为button注册快捷键
将listbox1中的数据用鼠标拖动至listbox2,即有左至右. 分别对应控件注册如下事件DragEnter,MouseDown,DragDrop 代码如下: //P128 DataGridVie ...
- Android Studio 调试过程中快捷查看断点处变量值(Ctrl+Shift+I无效)?
当你在做Keymap到Eclipse后,在debug过程中,在Eclipse中我们很喜欢用Ctrl+Shift+I去查看一个运算或者调用的结果,这样用起来很方便.但是keymap到Eclipse后,你 ...
随机推荐
- Join的实现步骤 以及连接的概念
Join的实现步骤 以及连接的概念 我们常说连接有三种,即 交叉连接.内连接.外连接,这三者的概念很容易模糊,现在我们先放下概念,搞清楚完整连接实现的步骤: 一个完整的连接有三个步骤:.做笛卡儿积: ...
- 手把手教你安装QT集成开发环境(操作系统为ubuntu10.04)
在安装QT集成开发工具包之前需要先安装build-essential和libncurses5-dev这两个开发工具和库,libncurses5-dev库是一个在Linux/Unix下广泛应用的图形函数 ...
- VC 2005 解决方案的目录结构设置和管理
VC 2005 解决方案的目录结构设置和管理 Roger (roger2yi@gmail.com) 一个中等规模的解决方案通常都会包含多个项目,其中一些项目产出静态库,一些产出动态库,一些用于 ...
- android 播放音乐-进度条
今天学渣研究了一下使用MediaPlayer播放音乐时加入进度条,进度条如今用的是android自带的seekbar,后期会跟换UI的,在之前可以播放音乐的基础上,如今加入的主要功能有两个: 1实时显 ...
- Python标准库:内置函数dict(**kwarg)
本函数是从一个字典參数构造一个新字典.參数kwarg是键值对的字典參数.以两个*开头的參数.就会收集成字典形式. 样例: #dict() #以键对方式构造字典 d1 = dict(one = 1, t ...
- 如何解决android logcat不打印信息在android开发中
用eclipse进行android开发中经常遇到logcat无任何信息输出,这给我们调试程序带来很大的不便.解决办法:window-->show view-->选择android下的dev ...
- overflow:hidden与position:absolute
在做一个下拉框的动画效果中遇到了这个bug,记录一下. 在写下拉框的动画的时候,一般我们的做法都是把下拉框的外盒子设为overflow:hidden,然后设下外层盒子高度,之后通过js慢慢的改变高度从 ...
- JS的预编译和执行顺序 详析
原文:JS的预编译和执行顺序 详析 最近在复习javascript的事件处理时发现了一个问题,然后也是我来写javascript的预编译和执行顺序的问题 代码: 复制代码 代码一 <ht ...
- 十分钟开发一个调用Activity的PhoneGap插件
在HybridApp开发中,非常多业务我们是没有办法通过HTML5+js实现的,比方调用第三方的包括Activity的jar包,一些必须使用原生代码才干实现的功能,比方复杂的UI的效果,调用通讯相关的 ...
- [置顶] 关于本博客 http://www.imobilebbs.com
由于时间上的关系,本博客不再和引路蜂移动软件博客同步更新, 请直接访问 http://www.imobilebbs.com 谢谢您的支持,再见 引路蜂博客