`
flyPig
  • 浏览: 139866 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Windows鼠标框选效果

阅读更多
常见情况下,一个JTable是放到一个JScrollPane,这样数据量很大的时候,可以通过滚动条来控制。因此要实现框选效果,需要考虑到这两个主要组件的paint问题。

框选操作,可以分解为 鼠标左键点击,拖拽,释放三个动作,因此需要实现MouseInputListener。考虑到此框选操作为特定look&feel拥有,故以BasicTableUI为基类实现

public class MyTableUI extends BasicTableUI {
	
	protected MouseInputListener createMouseInputListener() {

        return new MyMouseInputHandler();

    }
	class MyMouseInputHandler extends MouseInputHandler {

        private boolean ignoreDrag = false;
    	
        public void mousePressed(MouseEvent e) {
            if (e.getClickCount() == 2) {
                table.clearSelection();
            }
            Point origin = e.getPoint();
            int row = table.rowAtPoint(origin);
            int column = table.columnAtPoint(origin);
            if (row != -1 && column != -1) {
            	if(table instanceof AbstractTable){
            		((AbstractTable)table).mousePressed(e.getPoint());
            	}
                if (table.isCellSelected(row, column)) {
                    ignoreDrag = true;
                } else {
                    super.mousePressed(e);
                }
            }
        }
        
        public void mouseClicked(MouseEvent e) {
            super.mouseClicked(e);
        }

        public void mouseDragged(MouseEvent e) {
            if (!ignoreDrag) {
                super.mouseDragged(e);
                if(table instanceof AbstractTable){
	            	((AbstractTable)table).mouseDragged((Point)e.getPoint().clone());
            	}
            } 
        }
        
        public void mouseExited(MouseEvent e) {
        	if(table instanceof AbstractTable){
            	((AbstractTable)table).mouseExit();
        	}
        }
        
        public void mouseReleased(MouseEvent e) {
            if (ignoreDrag) {
                super.mousePressed(e);
                ignoreDrag = false;
               
            }  
            if(table instanceof AbstractTable){
            	((AbstractTable)table).mouseReleased();
        	}
            super.mouseReleased(e);
        }
        
    }

然后在其中的AbstractTable类中实现相应的鼠标事件处理。
public class AbstractTable extends JTable {

	private static final long serialVersionUID = 1L;
	
	private volatile boolean canSelected = true;
	
	private AbstractScollPane srcollPane;

	AbstractTable() {
		super();
		setUI(new MyTableUI());
	}

	/* 
	 * (non-Javadoc)
	 * @see javax.swing.JTable#changeSelection(int, int, boolean, boolean)
	 */
	public void changeSelection(int rowIndex,int columnIndex,boolean toggle, boolean extend) {
		if(columnIndex != 1){
			return;
		}else{
			super.changeSelection(rowIndex, columnIndex, toggle, extend);
		}
	}
	
	/**
	 * @param p
	 */
	public void mousePressed(Point p) {
		if(srcollPane == null){
			srcollPane = (AbstractScollPane)SwingUtilities.getAncestorOfClass(AbstractScollPane.class, this);
		}
		Point pp = SwingUtilities.convertPoint(this, p, srcollPane);
		srcollPane.setStartPoint(pp);
		//clearSelection();
	}

	public void mouseReleased() {
		canSelected = true;
		try {
			srcollPane.makeRectSelected();
			srcollPane.setStartPoint(null);
			srcollPane.setEndPoint(null);
			srcollPane.repaint();
		} catch (Exception e1) {
			e1.printStackTrace();
		} finally {
			canSelected = true;
		}
	}
	
	/**
	 * @param p
	 */
	public void mouseDragged(Point p) {
		Point pp = SwingUtilities.convertPoint(this, p, srcollPane);
		canSelected = false;
		srcollPane.setEndPoint(pp);
		srcollPane.repaint();
	}
	
	/**
	 * 
	 */
	public void mouseExit() {
		//startPoint = null;
		//endPoint = null;
		//canSelected = true;
	}
	
	/* 
	 * (non-Javadoc)
	 * @see javax.swing.JTable#isCellSelected(int, int)
	 */
	public boolean isCellSelected(int row, int column) {
		if (column != 1) {
			return false;
		} else {
			if(canSelected){
				return super.isCellSelected(row, column);
			}else{
				return false;
			}
		}
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
	}
}

最后由AbstractScollPane 来实现真正的框选效果。
public class AbstractScollPane extends JScrollPane {
	
	private static final long serialVersionUID = 1L;
	public String type;
	
	private transient Point startPoint;
	private transient Point endPoint;
	
	public AbstractScollPane(Component comp){
		super(comp);
		this.addMouseListener(new   MouseAdapter(){
            public   void   mousePressed(MouseEvent   e){
            	startPoint   =e.getPoint();
            	if(getViewport().getView() instanceof AbstractTable) {
            		AbstractTable table = (AbstractTable)getViewport().getView();
            		table.clearSelection();
            	}
            }
            public   void   mouseReleased(MouseEvent   e){
            	makeRectSelected();
            	startPoint = null;
            	endPoint = null;
            	repaint();
            }
		});
		this.addMouseMotionListener(new   MouseMotionAdapter(){
            public   void   mouseDragged(MouseEvent   e){
            	endPoint   =e.getPoint();                
                repaint();
            }
		}); 
	}
	public String getType(){
		return type;
	}
	/**
	 * @param type the type to set
	 */
	public void setType(String type) {
		this.type = type;
	}
	
	public void paint(Graphics g) {
		super.paint(g);
		Graphics2D g2 = (Graphics2D) g;
		if (startPoint != null && endPoint != null) {
			g2.setColor(Color.red);
			int x = Math.min(startPoint.x, endPoint.x);
			int y = Math.min(startPoint.y, endPoint.y);
			int width = Math.abs(startPoint.x - endPoint.x);
			int height = Math.abs(startPoint.y - endPoint.y);
			g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.2f));
			g2.drawRect(x, y, width, height);
			g2.setColor(Color.yellow);
			g2.fillRect(x, y, width, height);
		}	
	}
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);			
	}
	
	public void makeRectSelected() {
		if(startPoint != null && endPoint != null) {
			 if(getViewport().getView() instanceof AbstractTable) {
				 AbstractTable table = (AbstractTable)getViewport().getView();
				 Point tableLocation = table.getLocation();
				 Point tablePointInScroll = SwingUtilities.convertPoint(table, tableLocation, this);				 
				 Rectangle mousedRect = new Rectangle(Math.min(startPoint.x, endPoint.x),Math.min(startPoint.y, endPoint.y),Math.abs(startPoint.x - endPoint.x),Math.abs(startPoint.y - endPoint.y));
				 Rectangle interSection = SwingUtilities.computeIntersection(tablePointInScroll.x, tablePointInScroll.y, getSize().width, table.getHeight(), mousedRect);
				 if(interSection.equals(new Rectangle(0,0,0,0))){
					 return;
				 }else {					 
					 Point start = SwingUtilities.convertPoint(this, new Point(interSection.x,interSection.y), table);
					 Point end = SwingUtilities.convertPoint(this, new Point(interSection.x + interSection.width,interSection.y+interSection.height), table);					 
					 int srow = table.rowAtPoint(start);
						int scolumn = table.columnAtPoint(start);
						int erow = table.rowAtPoint(end);
						if (erow == -1)
							erow = table.getRowCount() - 1;
						if (srow == -1)
							srow = 0;
						if ((scolumn == 0 || scolumn == 1) && Math.abs(erow - srow) >= 0) {
							table.setRowSelectionInterval(srow, erow);
							table.setColumnSelectionInterval(0, 1);
						}else {
							table.clearSelection();
						}
				 }				
			 }
		}
	}
	
	/**
	 * @param endPoint the endPoint to set
	 */
	public void setEndPoint(Point endPoint) {
		this.endPoint = endPoint;
	}
	
	/**
	 * @param startPoint the startPoint to set
	 */
	public void setStartPoint(Point startPoint) {
		this.startPoint = startPoint;
	}
}

总的来说,如果框选初始事件由最里层的AbstractTable捕获,则外传到包装它的AbstractScollPane由它来做具体的paint操作;如果是在AbstractScollPane上直接发生框选事件,就直接paint.
分享到:
评论

相关推荐

    鼠标框选效果

    鼠标框选效果的框选代码,很精简,可以画出js 的选框,模范windows的效果

    c# winform 用鼠标画拉出来的虚线框,鼠标框选边框效

    在 Windows Forms (WinForms) 应用程序开发中,经常需要实现用户交互功能,例如通过鼠标绘制虚线框来选择区域。本文将详细介绍如何在 C# 的 WinForms 中实现这一功能。我们将基于提供的代码片段进行分析,并解释每一...

    JS实现鼠标框选效果完整实例

    本文实例讲述了JS实现鼠标框选效果的方法。分享给大家供大家参考,具体如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <...

    wpf 鼠标拖出虚线框

    - **AdornerLayer**:`AdornerLayer`是WPF中用于附加额外视觉元素的特殊层,它可以覆盖在其他元素之上,使得我们可以在不影响原有控件的情况下添加框选效果。 - **事件处理**:确保正确地绑定和处理事件,避免在非...

    仿Windows桌面框选功能实现

    本示例"仿Windows桌面框选功能实现"是关于如何在WinForm应用中实现类似操作系统桌面的框选功能,即用户可以通过鼠标拖动绘制一个矩形框来选择多个控件或对象,如同在桌面上批量选择文件。这个功能常用于需要多选操作...

    用C# 实现鼠标框选效果的实现代码

    在C#编程中,实现鼠标框选效果是一项常见的需求,特别是在图形界面或者数据可视化应用中。本文将详细介绍如何使用C#来实现这一功能,并提供具体的代码示例。 首先,我们需要了解实现鼠标框选效果的基本步骤: 1. *...

    checkbox鼠标拖拽框选

    通过以上步骤,我们可以实现一个类似Windows文件管理器的拖拽框选功能,使用户在大量checkbox中进行多选操作变得更加方便快捷。这个功能的实现涉及到前端开发的多个方面,包括JavaScript基础、DOM操作、事件处理、...

    VC 实现鼠标拖动控件边框改变其大小

    在VC++编程环境中,开发Windows应用程序时,我们经常需要实现用户可以通过鼠标拖动控件的边框来改变其大小的功能。这个功能对于提高用户界面的交互性和灵活性至关重要。标题"VC 实现鼠标拖动控件边框改变其大小"正是...

    VC MFC实现橡皮筋类(鼠标拖动框选)

    本篇将详细讲解如何在VC MFC中实现橡皮筋类以及鼠标拖动框选功能。 首先,我们需要创建一个新的MFC应用,选择基于对话框的项目类型。然后,在对话框类中添加对鼠标消息的处理函数。这通常包括`ON_WM_LBUTTONDOWN()`...

    为ComboBox控件实现复选框

    为了在ComboBox中实现复选框,我们需要对控件进行自定义扩展或者利用其他技术来模拟这一效果。以下是一些关键知识点: 1. **自定义控件类**:在VC6.0环境下,你可以创建一个新的窗口类(CComboBox派生类),并重写...

    C#实现chart数据点的放大缩小显示、框选、删除、平移.rar

    - **框选**:需要监听鼠标按下和释放事件,计算出鼠标的移动范围,然后根据这个范围调整Chart的VisibleRange属性,使得只有框选区域内的数据点可见。 - **删除数据点**:可以添加一个删除功能,比如右键菜单或按钮...

    MFC透明窗口框选功能.zip

    总的来说,实现MFC透明窗口框选功能涉及的知识点包括:MFC窗口类的使用、Windows消息机制、窗口透明性设置、鼠标消息处理、绘图函数的应用以及用户交互设计。通过这些技术的结合,我们可以创建出富有创意和实用性的...

    原生的复选框(checkbox button)和单选按钮(radio button)实现透明背景效果解决方案

    在Windows编程中,原生的复选框(Checkbox)和单选按钮(Radio Button)通常是由Windows API或者特定的库如ATL/WTL提供的控件。这些控件默认的外观和行为是系统定义的,包括它们的背景颜色,通常与对话框或窗口的...

    复选框封装类

    在这个“复选框封装类”资源中,开发者提供了一个自绘的复选框类,以增强其视觉效果和定制性。下面将详细介绍这个封装类以及相关的编程知识。 1. **自绘控件**:在Windows API或MFC(Microsoft Foundation Classes...

    复选框美化

    "复选框美化"这个主题,就是关于如何在Visual Studio 2003环境下通过自定义控件来提升复选框(Checkbutton)的视觉效果。本文将深入探讨这一技术,包括贴图方法以及如何实现复选框的四态效果。 首先,复选框是用户...

    屏蔽鼠标按键_C#_

    当用户勾选某个复选框时,相应的鼠标事件就会被屏蔽。 UI部分的代码会监听这些复选框的状态变化,并调用`MouseHook.cs`中的方法来开启或关闭钩子。例如,如果用户勾选了“屏蔽左键”,代码会调用`MouseHook.SetHook...

    VB.NET鼠标拖选控件(源码+注释)

    4. **状态更新**:在`MouseUp`事件中,根据标记的结果更新控件的状态,例如改变控件的背景色、添加选中边框等,以视觉上展示出拖选的效果。 5. **源码结构**:提供的源码可能包括一个自定义控件类,继承自`System....

    矩形任意框选图像改变图片像素灰度值

    该项目采用Visual Studio 2010作为开发环境,并且自带了测试数据,能够实现用户通过矩形框选区域来调整图像的灰度值,提供了直观的图形处理效果。接下来,我们将详细探讨这个项目中的关键知识点。 首先,我们要了解...

    框选要素显示(高亮,闪烁)(C#2005+AE9.2)

    框选是一种常见的选择方式,用户可以通过鼠标绘制一个矩形框来选择框内的所有要素。 4. **高亮显示**:被选中的要素可以通过改变颜色、透明度等方式进行高亮显示,以突出其在地图上的存在。这通常通过修改要素的...

    VS2019MFC 控件自绘大全(按钮/复选框/单选框/菜单栏/静态文本/等控件自绘继承类)

    复选框和单选框的自绘需要处理选中和未选中的不同状态,以及可能的鼠标悬停效果。 4. **菜单栏自绘** 菜单栏自绘通常涉及到CMenubar类,通过重写OnDrawMenuImage()和OnDrawMenuItem()来控制菜单项的显示。可以实现...

Global site tag (gtag.js) - Google Analytics