SWT/JFace一些经典技术与算法<o:p></o:p>
转自:http://blog.csdn.net/jackkp_Catus/archive/2007/09/17/1787698.aspx
1图形拖动<o:p></o:p>
图形的拖动就是图形选中的图形跟着鼠标的移动而不断的相应改变位置,这是在图形界面中是经常见的一个操作,但是在SWT/JFace中来实现却不是意见容易的事。在这里底板是一个Canvas,图形也是建立在一个Canvas上,当然位置的改变是建立在鼠标移动的监听下
l 首先建立几个变量:
Int oldx = -1;// 拖动前的x Int oldy = -1;//拖动前的y Int xoffset = 0; //拖动后的偏移量x Int yoffset =0 ;// 拖动后的偏移量y; Int x,y;// 拖动后图形应该在的位置 |
l 在第一次拖动时,取得oldx和oldy
if(oldX==-1&&oldY==-1){<o:p></o:p> oldX=e.x;<o:p></o:p> oldY=e.y;<o:p></o:p> } |
l 获得偏移量
xoffset=e.x-oldX;<o:p></o:p> yoffset=e.y-oldY; |
l 得到新的图形位置
x=ca.getBounds().x+xoffset;<o:p></o:p> y=ca.getBounds().y+yoffset;<o:p></o:p> |
l 重新设置图形的位置
ca.setBounds(x,y,ca.getSize.x,ca.getSize.y) |
这样就实现了图形的拖动,不仅算法简洁,而且效果也很好。当然为了更好的效果,还可以加上边界控制,以保证图形不超出边界
2图形连线与画线<o:p></o:p>
<st1:chsdate isrocdate="False" month="12" islunardate="False" day="30" w:st="on" year="1899">2.1</st1:chsdate> 图形的连线<o:p></o:p>
整个SWT中只有一个类GC与之有关,就是在一个画板上画线,这样简单的线根本无法满足复杂连线的要求,要实现比较复杂的图形间的连线,我们使用了eclipse的另一个插件——draw2D,在draw2D的图形中比较容易实现连线,但是draw2D中连线的图形都是IFigure类的图形,否则就无法实现draw2D内的连线,然而我们的图形使用SWT设计的,因此出现了两者的兼容问题。因此我们自行设计了综合使用两者来实现图形连线的方案,就是图形是用SWT设计的,而线是用draw2D来设计的。这样设计表面看起来能够达到draw2D的两线的完美效果,而又不改变我们需要是用的SWT设计的图形。<o:p></o:p>
l 连线的简化流程<o:p></o:p>
<v:group coordsize="7200,1630" id="_x0000_s1037" coordorigin="2055,1776" editas="canvas" style="WIDTH: 414pt; HEIGHT: 93.6pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line"><o:lock v:ext="edit" aspectratio="t"></o:lock><v:shapetype o:spt="75" coordsize="21600,21600" filled="f" stroked="f" id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" o:connecttype="rect" gradientshapeok="t"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><v:shape id="_x0000_s1038" type="#_x0000_t75" o:preferrelative="f" style="LEFT: 2055px; WIDTH: 7200px; POSITION: absolute; TOP: 1776px; HEIGHT: 1630px"><v:fill o:detectmouseclick="t"></v:fill><v:path o:extrusionok="t" o:connecttype="none"></v:path><o:lock text="t" v:ext="edit"></o:lock></v:shape><v:shapetype o:spt="202" coordsize="21600,21600" id="_x0000_t202" path="m,l,21600r21600,l21600,xe"><v:stroke joinstyle="miter"></v:stroke><v:path o:connecttype="rect" gradientshapeok="t"></v:path></v:shapetype><v:shape id="_x0000_s1039" type="#_x0000_t202" style="LEFT: 2368px; WIDTH: 1722px; POSITION: absolute; TOP: 2319px; HEIGHT: 679px"><v:textbox>
获得起始图形,计算出连线的起点 |
获得指向图形,计算出连线的终点 |
根据起点和终点来建立连线 |
l 解决Canvas与Panel之间的兼容问题
因为我们的建立在一个画布(Canvas)上的,而连线则要建立在一个(Panel)上。因此我们要将两者联系起来,才能实现图形间的连线。这里需要用到轻量级系统(LightweightSystem)
<v:group coordsize="6261,951" id="_x0000_s1044" coordorigin="2662,2187" editas="canvas" style="WIDTH: 5in; HEIGHT: 54.65pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line"><o:lock v:ext="edit" aspectratio="t"></o:lock><v:shape id="_x0000_s1045" type="#_x0000_t75" o:preferrelative="f" style="LEFT: 2662px; WIDTH: 6261px; POSITION: absolute; TOP: 2187px; HEIGHT: 951px"><v:fill o:detectmouseclick="t"></v:fill><v:path o:extrusionok="t" o:connecttype="none"></v:path><o:lock text="t" v:ext="edit"></o:lock></v:shape><v:shape id="_x0000_s1046" type="#_x0000_t202" style="LEFT: 3601px; WIDTH: 4383px; POSITION: absolute; TOP: 2459px; HEIGHT: 544px"><v:textbox>
lws=new LightweightSystem(editPlace);<o:p></o:p> |
图形所在的面板 |
然后就可以新建Panel,并将他设为轻量级系统的内容
<v:group coordsize="6574,951" id="_x0000_s1048" coordorigin="2662,5766" editas="canvas" style="WIDTH: 378pt; HEIGHT: 54.6pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line"><o:lock v:ext="edit" aspectratio="t"></o:lock><v:shape id="_x0000_s1049" type="#_x0000_t75" o:preferrelative="f" style="LEFT: 2662px; WIDTH: 6574px; POSITION: absolute; TOP: 5766px; HEIGHT: 951px"><v:fill o:detectmouseclick="t"></v:fill><v:path o:extrusionok="t" o:connecttype="none"></v:path><o:lock text="t" v:ext="edit"></o:lock></v:shape><v:shape id="_x0000_s1050" type="#_x0000_t202" style="LEFT: 3132px; WIDTH: 5478px; POSITION: absolute; TOP: 5901px; HEIGHT: 816px"><v:textbox>
panel=new Figure();<o:p></o:p> lws.setContents(panel);<o:p></o:p> |
这样我们就可以在panel上添加我们的连线了
<st1:chsdate isrocdate="False" month="12" islunardate="False" day="30" w:st="on" year="1899">2.2</st1:chsdate> 在面板上画曲线<o:p></o:p>
l 这个曲线也同样要建立在Panel之上,因此也要像上面一样建立Panle,这里不再重复
l 要创建曲线则要用到PolylineConnection(),我们先创建一个PolylineConnection的对象pc.<o:p></o:p>
l 如果要显示箭头,则可以给pc添加修饰,<o:p></o:p>
p2.setTargetDecoration(new PolygonDecoration());<o:p></o:p>
l 接下来就是设置pc上的关键点,包括起点,终点,拐点。确定这些点后,从起点到终点依次排列即可
<v:group coordsize="7200,951" id="_x0000_s1051" coordorigin="2662,6798" editas="canvas" style="WIDTH: 414pt; HEIGHT: 54.6pt; mso-position-horizontal-relative: char; mso-position-vertical-relative: line"><o:lock v:ext="edit" aspectratio="t"></o:lock><v:shape id="_x0000_s1052" type="#_x0000_t75" o:preferrelative="f" style="LEFT: 2662px; WIDTH: 7200px; POSITION: absolute; TOP: 6798px; HEIGHT: 951px"><v:fill o:detectmouseclick="t"></v:fill><v:path o:extrusionok="t" o:connecttype="none"></v:path><o:lock text="t" v:ext="edit"></o:lock></v:shape><v:shape id="_x0000_s1053" type="#_x0000_t202" style="LEFT: 2975px; WIDTH: 6417px; POSITION: absolute; TOP: 6934px; HEIGHT: 407px"><v:textbox>
p2.setPoints(new PointList(new int[]{p1, p2,p3,…})); |
l 这样就可以建立了曲线,不过线上的个关键点的确定是一个难点,根据不同的情况会有不同的确定方法,这里不能一一列出了
3图像常用处理与Canvas<o:p></o:p>
<st1:chsdate isrocdate="False" month="12" islunardate="False" day="30" w:st="on" year="1899">3.1</st1:chsdate> 如何在Canvas上添加图像<o:p></o:p>
要在一个画布Canvas上添加,需要注册画布的画图事件,代码如下:
canvas.addPainListener(new PaintListener(){ public void paintControl(PaintEvent e){ e.gc.drawImage(image,10,10); } } |
<st1:chsdate isrocdate="False" month="12" islunardate="False" day="30" w:st="on" year="1899">3.2</st1:chsdate> 图像的创建<o:p></o:p>
1. Image(display, “eclipse.gif”)
2. Image (display , “eclipse.gif”,SWT.IMAGE_FRAY)
3.ImageData data = new ImageData(“eclipse.gif);
Image image = new Image(display, data)
<st1:chsdate isrocdate="False" month="12" islunardate="False" day="30" w:st="on" year="1899">3.3</st1:chsdate> 图像的放大或缩小<o:p></o:p>
通过ImageData的scaledTo可意见图像放大或缩小,在这里是新建另一个图像,而不是直接改变原来的图像。
ImageData data = image.getImageData(); ImageDate newData = data.scaledTo(newWidth,newHeight); Image newImage = new Image(display, newData); |
<o:p> </o:p>
<st1:chsdate isrocdate="False" month="12" islunardate="False" day="30" w:st="on" year="1899">3.4</st1:chsdate> 图像的保存<o:p></o:p>
<v:shape id="_x0000_s1054" type="#_x0000_t62" adj="-11859,21849" style="MARGIN-TOP: 21.3pt; Z-INDEX: 6; LEFT: 0px; MARGIN-LEFT: 270pt; WIDTH: 153pt; POSITION: absolute; HEIGHT: 39pt; TEXT-ALIGN: left"><v:textbox>
因为一个动态的图片可能有多个图片组成,所以用数组 |
4文件的过滤<o:p></o:p>
这里所说的文件的过滤不是上面说的文件对话框中的文件的过滤,在这里我们设置了一个树,让它来显示工程下已有的文件,在这里我们只希望看到(.grh)的文件,因此需要给它设置过滤器。先来看看我们怎么实现显示文件的;<o:p></o:p>
<o:p> </o:p>
在这里使用的是TreeViewer,TreeViewer的构建步骤如下:
u 创建新对象,例如TreeViewer tv=new TreeViewer(fileComposite,SWT.NONE);
u 设置内容管理器,如tv.setContentProvider( new FileTreeContentProvider());
u 设置标签提供器,如tv.setLabelProvider(new FileTreeLabelProvider());
u 设定TreeViewer的输入数据,如tv.setInput(new File("e:\"));
其中