<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    大夢(mèng)想家

    5年開(kāi)發(fā)工程師,2年實(shí)施經(jīng)理,X年售前顧問(wèn),......
    數(shù)據(jù)加載中……
    SWT/JFace一些經(jīng)典技術(shù)與算法

    1。圖形拖動(dòng)

    圖形的拖動(dòng)就是圖形選中的圖形跟著鼠標(biāo)的移動(dòng)而不斷的相應(yīng)改變位置,這是在圖形界面中是經(jīng)常見(jiàn)的一個(gè)操作,但是在SWT/JFace中來(lái)實(shí)現(xiàn)卻不是意見(jiàn)容易的事。在這里底板是一個(gè)Canvas,圖形也是建立在一個(gè)Canvas上,當(dāng)然位置的改變是建立在鼠標(biāo)移動(dòng)的監(jiān)聽(tīng)下.

    1、首先建立幾個(gè)變量:

    Int oldx = -1;// 拖動(dòng)前的x

    Int oldy = -1;//拖動(dòng)前的y

    Int xoffset = 0; //拖動(dòng)后的偏移量x

    Int yoffset =0 ;// 拖動(dòng)后的偏移量y;

    Int x,y;// 拖動(dòng)后圖形應(yīng)該在的位置

    2、 在第一次拖動(dòng)時(shí),取得oldx和oldy

    if(oldX==-1&&oldY==-1){

    oldX=e.x;

    oldY=e.y;

    }

    3、 獲得偏移量

    xoffset=e.x-oldX;

    yoffset=e.y-oldY;

    4、得到新的圖形位置

    x=ca.getBounds().x+xoffset;

    y=ca.getBounds().y+yoffset;

    5、 重新設(shè)置圖形的位置

    ca.setBounds(x,y,ca.getSize.x,ca.getSize.y)

       這樣就實(shí)現(xiàn)了圖形的拖動(dòng),不僅算法簡(jiǎn)潔,而且效果也很好。當(dāng)然為了更好的效果,還可以加上邊界控制,以保證圖形不超出邊界

    2。圖形連線與畫(huà)線

    2.1 圖形的連線

    整個(gè)SWT中只有一個(gè)類GC與之有關(guān),就是在一個(gè)畫(huà)板上畫(huà)線,這樣簡(jiǎn)單的線根本無(wú)法滿足復(fù)雜連線的要求,要實(shí)現(xiàn)比較復(fù)雜的圖形間的連線,我們使用了eclipse的另一個(gè)插件——draw2D,在draw2D的圖形中比較容易實(shí)現(xiàn)連線,但是draw2D中連線的圖形都是IFigure類的圖形,否則就無(wú)法實(shí)現(xiàn)draw2D內(nèi)的連線,然而我們的圖形使用SWT設(shè)計(jì)的,因此出現(xiàn)了兩者的兼容問(wèn)題。因此我們自行設(shè)計(jì)了綜合使用兩者來(lái)實(shí)現(xiàn)圖形連線的方案,就是圖形是用SWT設(shè)計(jì)的,而線是用draw2D來(lái)設(shè)計(jì)的。這樣設(shè)計(jì)表面看起來(lái)能夠達(dá)到draw2D的兩線的完美效果,而又不改變我們需要是用的SWT設(shè)計(jì)的圖形。

    1、 連線的簡(jiǎn)化流程

    獲得起始圖形,計(jì)算出連線的起點(diǎn)

    獲得指向圖形,計(jì)算出連線的終點(diǎn)

    根據(jù)起點(diǎn)和終點(diǎn)來(lái)建立連線

    2、 解決Canvas與Panel之間的兼容問(wèn)題

    因?yàn)槲覀兊慕⒃谝粋€(gè)畫(huà)布(Canvas)上的,而連線則要建立在一個(gè)(Panel)上。因此我們要將兩者聯(lián)系起來(lái),才能實(shí)現(xiàn)圖形間的連線。這里需要用到輕量級(jí)系統(tǒng)(LightweightSystem)

    lws=new LightweightSystem(editPlace);

    圖形所在的面板

    然后就可以新建Panel,并將他設(shè)為輕量級(jí)系統(tǒng)的內(nèi)容

    panel=new Figure();

    lws.setContents(panel);

    這樣我們就可以在panel上添加我們的連線了

    2.2 在面板上畫(huà)曲線

    1、 這個(gè)曲線也同樣要建立在Panel之上,因此也要像上面一樣建立Panle,這里不再重復(fù)

    2、要?jiǎng)?chuàng)建曲線則要用到PolylineConnection(),我們先創(chuàng)建一個(gè)PolylineConnection的對(duì)象pc.

    3、 如果要顯示箭頭,則可以給pc添加修飾,

    p2.setTargetDecoration(new PolygonDecoration());

    4、接下來(lái)就是設(shè)置pc上的關(guān)鍵點(diǎn),包括起點(diǎn),終點(diǎn),拐點(diǎn)。確定這些點(diǎn)后,從起點(diǎn)到終點(diǎn)依次排列即可

    p2.setPoints(new PointList(new int[]{p1, p2,p3,…}));

    5、 這樣就可以建立了曲線,不過(guò)線上的個(gè)關(guān)鍵點(diǎn)的確定是一個(gè)難點(diǎn),根據(jù)不同的情況會(huì)有不同的確定方法,這里不能一一列出了

    3。圖像常用處理與Canvas

    3.1 如何在Canvas上添加圖像

    要在一個(gè)畫(huà)布Canvas上添加,需要注冊(cè)畫(huà)布的畫(huà)圖事件,代碼如下:

    canvas.addPainListener(new PaintListener(){

    public void paintControl(PaintEvent e){

    e.gc.drawImage(image,10,10);

    }

    }

    3.2 圖像的創(chuàng)建

    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)

    3.3 圖像的放大或縮小

       通過(guò)ImageData的scaledTo可意見(jiàn)圖像放大或縮小,在這里是新建另一個(gè)圖像,而不是直接改變?cè)瓉?lái)的圖像。

    ImageData data = image.getImageData();

    ImageDate newData = data.scaledTo(newWidth,newHeight);

    Image newImage = new Image(display, newData);

    3.4 圖像的保存

    因?yàn)橐粋€(gè)動(dòng)態(tài)的圖片可能有多個(gè)圖片組成,所以用數(shù)組

    4文件的過(guò)濾

    這里所說(shuō)的文件的過(guò)濾不是上面說(shuō)的文件對(duì)話框中的文件的過(guò)濾,在這里我們?cè)O(shè)置了一個(gè)樹(shù),讓它來(lái)顯示工程下已有的文件,在這里我們只希望看到(.grh)的文件,因此需要給它設(shè)置過(guò)濾器。先來(lái)看看我們?cè)趺磳?shí)現(xiàn)顯示文件的;

    在這里使用的是TreeViewer,TreeViewer的構(gòu)建步驟如下:

    1、 創(chuàng)建新對(duì)象,例如TreeViewer tv=new TreeViewer(fileComposite,SWT.NONE);

    2、 設(shè)置內(nèi)容管理器,如tv.setContentProvider( new FileTreeContentProvider());

    3、設(shè)置標(biāo)簽提供器,如tv.setLabelProvider(new FileTreeLabelProvider());

    4、設(shè)定TreeViewer的輸入數(shù)據(jù),如tv.setInput(new File("e:\"));

    其中FileTreeContentProvide,F(xiàn)ileTreeLabelProvider分別是implements了ItreeContentProvider和ILabelProvider兩個(gè)接口的。

    FileTreeContentProvide中有幾個(gè)重要的方法。

    ① getElements();"public Object[] getElements(Object inputElement)",當(dāng)程序開(kāi)始構(gòu)建樹(shù)時(shí),首先調(diào)用它返回一個(gè)數(shù)組,此數(shù)組對(duì)象表示樹(shù)的根節(jié)點(diǎn),

    ② hasChildren();"public boolean hasChildren(Object element)",當(dāng)TreeViewer顯示一個(gè)節(jié)點(diǎn)(element)后會(huì)調(diào)用該函數(shù)判斷當(dāng)前節(jié)點(diǎn)是否有子節(jié)點(diǎn),若有則顯示“+”;

    ③ getChildren();"public Object[] getChildren(Object parentElement)",當(dāng)用戶選擇節(jié)點(diǎn)打開(kāi)子節(jié)點(diǎn)時(shí),會(huì)調(diào)用此函數(shù)返回下一層子節(jié)點(diǎn),parentElement參數(shù)為選擇的節(jié)點(diǎn);

    ④ getparent();"public Object getParent(Object element)"

    還有幾個(gè)方法就不在此敘述,

    在程序里不需要顯示根目錄的位置,只要顯示在工程目錄下有用的文件,在getElements()方法中,我們返回getChildren()中的值,這樣,我們就可以不得到輸入的路徑這個(gè)根節(jié)點(diǎn),而把該路徑下的符合條件的文件作為根節(jié)點(diǎn);

    public Object[] getElements(Object element) {

    return getChildren(element);

    }

    在getChildren方法中,我們通過(guò)一個(gè)數(shù)組列出給定路徑下的文件,然后通過(guò)一個(gè)ArrayList來(lái)存儲(chǔ)符合條件的文件對(duì)象:

    Object[] kids = ((File) element).listFiles();

    ArrayList<Object> outs = new ArrayList<Object>();

    當(dāng)kids不是空的時(shí)候,我們就看kids中的文件后綴是不是符合我們的要求,如果是,就添加到outs中

    for(int i = 0;i<kids.length;i++){

    if(((File)kids[i]).getName().endsWith(".wsdl")||

    ((File)kids[i]).getName().endsWith(".bpel")||

    ((File)kids[i]).getName().endsWith(".grh")){

    int j = 0;

    outs.add(j,kids[i]);

    j++;

    }

    }

    現(xiàn)在我們已經(jīng)得到了我們需要得到的所有的對(duì)象,因?yàn)檫@個(gè)函數(shù)的返回值是個(gè)數(shù)組,再把outs中的元素復(fù)制到一個(gè)數(shù)組中即可;

    f(outs.size()!=0){

    Object[] out = new Object[outs.size()];

    for(int i= 0;i<outs.size();i++){

    out[i] = outs.get(i);

    }

    return out;

    }

    5。關(guān)于序列化保存

    1) 關(guān)于保存

    序列化的問(wèn)題是由保存引起的,要保存一個(gè)對(duì)象就必須為相關(guān)的類實(shí)現(xiàn)序列化,這本沒(méi)有什么問(wèn)題,只需要把相關(guān)的類繼承并實(shí)現(xiàn)Serializable接口就可以了,但是,在工程里用到了一些類。例如org.eclipse.swt.widgets.graphics.Image這個(gè)類,它是一個(gè)final類,不可以被繼承,但是他是節(jié)點(diǎn)的一部分,必須要顯示出來(lái);我們可以把它作為一個(gè)參數(shù)傳到節(jié)點(diǎn)的setNodeLocation函數(shù)中,它是初始化節(jié)點(diǎn)時(shí)負(fù)責(zé)顯示的函數(shù)。每創(chuàng)建一個(gè)新的節(jié)點(diǎn)時(shí)就需要先創(chuàng)建一個(gè)Image實(shí)例。

    2) 關(guān)于恢復(fù)

    保存成功了還需要恢復(fù)圖像,恢復(fù)圖像是個(gè)比較復(fù)雜的過(guò)程,我們要保證圖像的位置和數(shù)據(jù)等許多東西保持不變;首先找到開(kāi)始節(jié)點(diǎn),從開(kāi)始節(jié)點(diǎn)開(kāi)始逐個(gè)恢復(fù),如沒(méi)有開(kāi)始節(jié)點(diǎn),那么這個(gè)圖是不完整的,就沒(méi)有辦法完整的恢復(fù)它;恢復(fù)時(shí),不能用原來(lái)的對(duì)象,因?yàn)樵械膶?duì)象都已經(jīng)被dispose();了,并且不可以用到任何有關(guān)顯示的方法,否則就會(huì)出現(xiàn)促發(fā)異常;所以要得到節(jié)點(diǎn)的大小和位置就要另想辦法;

    為了得到node原來(lái)的位置,在node中設(shè)置了一個(gè)point變量來(lái)記載node的位置,并在node的位置更改后更改point的值,這樣就可以得到node原來(lái)的位置;同理,我們可以得到保存時(shí)node的大小了;

    我們可以從保存的圖中找到與開(kāi)始節(jié)點(diǎn)相關(guān)聯(lián)的下一個(gè)節(jié)點(diǎn),回復(fù)這個(gè)節(jié)點(diǎn)后再找下一個(gè)節(jié)點(diǎn),這樣可以通過(guò)一個(gè)循環(huán)一直找到結(jié)束節(jié)點(diǎn),并把這些節(jié)點(diǎn)加到一個(gè)新建的graph中,然后把相關(guān)的信息都通過(guò)已有的set和get方法添加的節(jié)點(diǎn)中去,這樣,整個(gè)圖的所有的節(jié)點(diǎn)都恢復(fù)出了;

    因?yàn)槊總€(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)有不同的可能,用一個(gè)if else組合來(lái)判斷到底是哪一個(gè)節(jié)點(diǎn),然后不同的節(jié)點(diǎn)有不同的代碼;簡(jiǎn)單的節(jié)點(diǎn)如taskNode的恢復(fù)比較簡(jiǎn)單,基本的過(guò)程和創(chuàng)建一個(gè)新的節(jié)點(diǎn)相同,只是注意把原節(jié)點(diǎn)的信息傳遞給新的節(jié)點(diǎn)即可。
       具體的過(guò)程可以簡(jiǎn)化為

    獲得要復(fù)制的節(jié)點(diǎn)的引用

    點(diǎn)擊粘貼,新建一個(gè)與要復(fù)制節(jié)點(diǎn)類型相同的節(jié)點(diǎn)

    把要復(fù)制節(jié)點(diǎn)的信息傳遞到新的節(jié)點(diǎn)中去

    判斷節(jié)點(diǎn)是不是容器節(jié)點(diǎn),是繼續(xù),不是結(jié)束

    新建容器節(jié)點(diǎn)中的子節(jié)點(diǎn),給子節(jié)點(diǎn)傳遞信息

    以下是粘貼后初始化一個(gè)工作節(jié)點(diǎn)的例子;

    wfNode = new TaskNode(node.getName(), gra, web);

    wfNode.setId(node.getId());

    wfNode.setNodeInView(c, workspace.getPanel(), attr,workspace,web); BaseWFNodeText.setCanvasText(wfNode);

    wfNode.setNodeLocation(node.getPoint().x, node.getPoint().y, image1);

    gra.addNode(wfNode);

    若下一個(gè)節(jié)點(diǎn)是復(fù)雜節(jié)點(diǎn),首先恢復(fù)復(fù)雜節(jié)點(diǎn)本身,然后判斷該節(jié)點(diǎn)是否有子節(jié)點(diǎn),若存在子節(jié)點(diǎn),則依次恢復(fù)其子節(jié)點(diǎn),通過(guò)一個(gè)foreach循環(huán)就可以把所有的子節(jié)點(diǎn)恢復(fù);注意的是每個(gè)父節(jié)點(diǎn)的子節(jié)點(diǎn)形式可能不同,而且他們需要傳遞的信息也不完全相同。部分代碼如下

    wfNode.getCanvas().setSize(node.getSize());

    //設(shè)置節(jié)點(diǎn)的大小

    wfNode.setSize(node.getSize().x, node.getSize().y);

    //記錄節(jié)點(diǎn)的大小

    gra.addNode(wfNode);

    節(jié)點(diǎn)的信息如下

    wfNode.setBpelOperation(node.getBpelOperation());

    wfNode.setSuppressJionFaliare(node.getSuppressJionFaliare());

    wfNode.setJionCondition(node.isJionCondition());

    wfNode.setOporation(node.getOporation());

    wfNode.setLink(node.getLink());

    //以上為所有節(jié)點(diǎn)都有的屬性

    wfNode.setCondition(node.getCondition());

    //FlowNode和WhileNode有的屬性

    wfNode.setCaseCondiction(node.getCaseCondiction());

    //FlowNodeµÄ×Ó½ÚµãÓеÄÊôÐÔ

    childNode.setFromPart(element.getFromPart());

    childNode.setFromVar(element.getFromVar());

    childNode.setToPart(element.getToPart());

    childNode.setToVar(element.getToVar());

    //以上四個(gè)是copy有的節(jié)點(diǎn)

    6。圖形的復(fù)制與粘貼

    1) 為各個(gè)節(jié)點(diǎn)以及底層面板創(chuàng)建菜單項(xiàng),包括復(fù)制,粘貼,刪除;在工具欄以及菜單欄創(chuàng)建相應(yīng)的項(xiàng);

    2) 關(guān)于復(fù)制

    復(fù)制的方法比較簡(jiǎn)單,就是把一個(gè)新的變量指向要復(fù)制的對(duì)象,然后把這個(gè)變量通過(guò)get方法,讓外界可以獲得它;

    public void copy(BaseWFNode node){

    midNode = node;

    }

    3) 關(guān)于粘貼

    粘貼的過(guò)程是創(chuàng)建一個(gè)新的節(jié)點(diǎn),他所攜帶的信息和復(fù)制的節(jié)點(diǎn)相同

    1、 獲得要粘貼節(jié)點(diǎn)的引用;判斷是否為空,是就繼續(xù),否則就什么也不做;

    2、 構(gòu)建一個(gè)新的節(jié)點(diǎn),確定節(jié)點(diǎn)的id,位置等于聲稱代碼無(wú)關(guān)的信息;

    3、 判斷節(jié)點(diǎn)具體是哪一種節(jié)點(diǎn),并把原節(jié)點(diǎn)的信息賦給新的節(jié)點(diǎn);

    4、 Gragh中添加這個(gè)節(jié)點(diǎn);

    5、 根據(jù)第三步,若這個(gè)節(jié)點(diǎn)是某個(gè)復(fù)雜節(jié)點(diǎn),就把它的子節(jié)點(diǎn)也構(gòu)建出來(lái),并賦予相應(yīng)的信息;實(shí)現(xiàn)的過(guò)程和恢復(fù)圖形類似;

    4) 工具欄復(fù)制的實(shí)現(xiàn)

    1、 這里添加監(jiān)聽(tīng)的時(shí)候用了一個(gè)標(biāo)記,當(dāng)雙擊一個(gè)節(jié)點(diǎn)的時(shí)候,就記錄這個(gè)標(biāo)記為1,然后讓一個(gè)中間的變量指向這個(gè)節(jié)點(diǎn),

    public void mouseDoubleClick(MouseEvent e){

    WSCAttribute.showWind(work, node);

    deleteFlag = 1;//當(dāng)點(diǎn)擊其他地方時(shí)設(shè)為0;

    preDelNode = node;

    }

    2、點(diǎn)擊復(fù)制的時(shí)候判斷標(biāo)記是否為1,判斷PreDelNode是不是空,不是就根據(jù)上面說(shuō)的復(fù)制來(lái)執(zhí)行;刪除節(jié)點(diǎn)也是用這個(gè)思想;

    3、 點(diǎn)擊粘貼,判斷中間節(jié)點(diǎn)是否時(shí)空,不是就在底層面板的起始處將節(jié)點(diǎn)復(fù)制下來(lái);否則就什么也不做;



    客戶虐我千百遍,我待客戶如初戀!

    posted on 2007-12-25 14:21 阿南 閱讀(1259) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 暖暖免费高清日本一区二区三区| 亚洲欧美日韩中文字幕一区二区三区 | 特级做a爰片毛片免费看| 亚洲网红精品大秀在线观看| 亚洲国产成人久久综合碰| 国产精品无码免费播放| 91高清免费国产自产拍2021| 福利免费在线观看| 免费一级特黄特色大片| 亚洲精品动漫免费二区| 亚洲黄色激情视频| 亚洲精品美女视频| 久久久久亚洲AV成人无码网站| 亚洲精品97久久中文字幕无码| 国产高清在线精品免费软件| 在线视频精品免费| 精品无码无人网站免费视频| 久久国产乱子伦精品免费强| 2022国内精品免费福利视频| 欧洲乱码伦视频免费国产 | 国产精品久久久久影院免费| 成人AV免费网址在线观看| 亚洲第一网站免费视频| 久久99毛片免费观看不卡| 免费在线观影网站| 人妻免费一区二区三区最新| 免费在线观影网站| 久久一本岛在免费线观看2020| 久久精品国产免费一区| 久久久国产精品无码免费专区| 免费看少妇高潮成人片| 中国一级全黄的免费观看| 三上悠亚在线观看免费| 两个人看的www免费| 国产麻豆一精品一AV一免费 | 亚洲天天在线日亚洲洲精| 亚洲AV无码久久| 精品日韩亚洲AV无码一区二区三区 | 国产精品美女自在线观看免费| 国产成人精品免费视频软件| 免费理论片51人人看电影|