熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

Java中輕松實現界面跳轉

2022-06-13   來源: Java核心技術 

  假設這樣一種情況我們的系統的界面使用javaxswing包構建界面的基礎是BaseView他是一個容器當然他應當提供獲取控件元素的功能比如得到按鈕下拉框表格等當然僅僅是一個容器而已而我們的界面的元素全部部署在JPanel上

  描述為:

  一個界面就是一個BaseView他只包含一個JPanel這個包含JPanel包含所有我們的Swing控件例如JButtonJLable等等

  問題出現了:我們通常因為業務的需要完成一個界面的操作要自動跳轉到下一個界面完成下一個界面又能跳回來(題外話:由於我們的操作是基於GUI的所以往往能保存Session信息而Web卻做不到)而這往往成為系統實現過程中效率低下的一個因素我就見到我現在的系統中有人用行代碼判斷上一個界面應該是哪一個來跳轉過來因為很多界面都可以跳到當前界面

  當然有一種做法是在下一個界面類中包含指向上一個界面的變量我們說這不方便也增加了依賴性這對軟件是不利的

  接下來我給出我的解決方法希望對采用這種界面結構的朋友有所裨益

  (以下全部用簡化模型來講述)

  簡單點我們假設BaseView繼承JWindow當然可以是別的容器(依據你的實現)大概象這樣:

  public abstract class BaseView extends JWindow{

  

  (實現一些取得界面控件和界面信息的方法)

  }

  每個界面類都象這樣定義:

  public class MyView extends BaseView{

  JPanel myPanel;

  public void playoutPanel(){

  JButton myButton = new JButton(OK);

  myPaneladd(myButton);

  

  (添加你需要的控件和布局到myPanel上)

  }

  }

  假設有其他的界面OneViewTwoViewThreeView處理完操作後都需要跳轉到myView在myView中的ok按鈕按下的時候需要回到原始界面

  原來臃腫的代碼需要在myView中添加一個變量BaseView anyView;用來存放轉來的那個界面anyView賦值在三者中的跳轉代碼中引用myView來設定跳轉代碼象這樣:

  public void jump(){

  MyView myView = new MyView();

  myViewanyView = this;

  thisremove(thisxxPanel);

  thisadd(myViewgetPanel());

  thisrepaint();

  }

  看起來還不錯雖然需要引用MyView類並調用他的變量和方法但是跳轉回來卻不那麼容易否則怎麼會用行!

  大概象這樣:(這已經是被我簡化的)

  public void goBack(){

  if(anyView instanceof OneView){

  anyViewremove(thismyView);

  OneView ov = (OneView)anyView;

  anyViewadd(ovgetPanel());

  anyViewrepaint();

  }

  if(anyView instanceof TwoView){

  

  }

  

  }

  不經大量應用別的業務用例界面這種編譯依賴性真不是什麼好事更何況用了大量的低效的instanceof判斷和轉型操作

  為了優化這種情形徹底解決這個問題我想應該設計一個第三方類來消除這種依賴性並且讓界面跳轉不要這麼費勁這個第三方的類是這樣設計的:

  在這個類中必須有一個變量來保存某一個界面跳轉的路徑如A>B>C路徑一旦被保存你就擁有了控制顯示任何一個界面的權利了在這個鏈中第一個位置的界面應該是這次跳轉的第一站最後一個位置是當前站這裡存在一個因果關系:只有跳轉了才可以跳回去這樣使得我們可以用數組來保存這個路徑現實中跳轉的情形應該不會超過所以我們把路徑長度設為(當然你可以根據需要更改)這個類的樣子大概象這樣:

  class ViewPath{

  JPanel[] pnlPath = null; //跳轉的界面路徑界面跳轉最大個層次吧!!!

  int index = ; //路徑中的當前下標

  BaseView bsView = null; //當前路徑所在的同一個View

  //在路徑中尋找目標的方法

  public int find(JPanel pnl){ //該路徑下是否有某個Panel有的話返回下標沒有的話返回

  if(bsView==null) return ; //沒有初始化該路徑下沒有任何Panel

  for(int i=;i  if(pnl==pnlPath[i]){

  index = i;

  return i; //如果找到了則返回位置並且把當前位置設為目標位置

  }

  }

  return ; //沒有找到返回

  }

  //構造函數

  ViewPath(JPanel myPanelBaseView myView){

  pnlPath = new JPanel; //設置路徑最大長度為

  bsView = myView; //設置該路徑所屬的那個View

  pnlPath[] = myPanel; //設立起始站

  index = ; //設立起始站索引

  }

  }

  這樣一個類就完成了保存一次跳轉路徑的作用(當然是否應該在find方法中設立目標位置是否合適有待商榷)

  那麼我們如何使用這樣一個路徑?

  我們設立一個輔助類來完成這個工作我們命名為ViewJump我們知道作為輔助的類最好是不要有實例特別是象這樣的起接口作用的類只提供靜態方法它的框架象這樣:

  public class ViewJump{

  private static ViewPath[] viewPath = null; //路徑池系統多處使用靜態但私有因為供內部用

  private ViewJump(){} //私有構造方法輔助類只提供靜態方法

  private static int find(JPanel pnl); //尋找給定的Panel是否在已有路徑中私有

  private static int newPath(JPanel myPanelBaseView myView); //建立一個新路徑私有

  /**

  * 每個類需要使用該輔助類時都需要第一步注冊自己然後才能做其他操作

  * 返回一個注冊碼id輔助類需要使用這個注冊碼進行其他操作

  */

  public static int registerPath(JPanel myPanelBaseView myView);

  /**

  * 設立下一個界面

  */

  public static void setNext(int idJPanel aim);

  /**

  * 回到上一個界面

  */

  public static void back(int id);

  /**

  * 回到第一個界面

  */

  public static void backHome(int id);

  /**

  * 跳轉到下一個界面

  */

  public static void jump(int id);

  }

  完成這樣一個類的代碼量並不多一百多行但是卻使得用戶完全脫離了處理不同界面的煩惱稍後會把該類的源碼附上值得一提的是這個類的實現固然可以用到類似的實現當中但是如果用戶的界面結構並不是如此搭建你就需要更改參數類型了如果能把這些抽象出來得到一個抽象類或接口參數用Object類型用戶根據自己的需要去實現這些方法豈不妙哉!

  使用這個類你可以簡便的多的完成諸如上面的任務:

  OneView中:

  public void jump(){

  MyView myView = new MyView();

  int id = ViewJumpregisterPath(thisxxPanelthis);

  ViewJumpsetNext(idmyViewgetPanel());

  ViewJumpjump(id);

  }

  MyView中退回的部分:

  protected void goBack(){

  int id = ViewJumpregisterPath(thismyPanelthis);

  ViewJumpback(id);

  }

  天哪這並不神奇行代碼僅僅用了兩行就實現了!

  好了我就說這麼多了一切都掌握在你手中用你的智慧來優化我們的冗余代碼吧因為這樣它看起來相當不錯

  附:完整代碼:(我把ViewPath類放在同一個文件ViewJumpjava裡代碼上面已經給出)

  public class ViewJump{

  private static ViewPath[] viewPath = null;

  //私有構造函數

  private ViewJump(){}

  //尋找該Panel是不是在路徑中

  /**

  * 找到了返回在實例數組中的下標

  * 沒有找到返回

  * @param pnl

  * @return

  */

  private static int find(JPanel pnl){

  // Systemoutprintln(執行find() in ViewJump);

  if(viewPath == null || viewPathlength==) return ;

  for(int i = ;i   ViewPath vp = viewPath[i]; //對該路徑檢查

  if(vpfind(pnl) != ){

  return i;

  }

  }

  return ;

  }

  //建立一個新的路徑

  /**

  *

  * @param myPanel

  * @param myView

  */

  private static int newPath(JPanel myPanelBaseView myView){

  Systemoutprintln(執行newPath() in ViewJump);

  //檢驗一下看有沒有無效的路徑有則清除

  if(viewPath == null || viewPathlength==) {

  viewPath = new ViewPath[]{new ViewPath(myPanelmyView)};

  return ;

  }

  ViewPath[] vjArr = new ViewPath[viewPathlength];

  int count = ;

  for(int i = ;i   if(viewPath[i]bsView!=null){ //把不為空的值取出來

  vjArr[count++] = viewPath[i];

  }

  }

  viewPath = new ViewPath[count+];

  Systemarraycopy(viewPathvjArrcount); //復制到原來的數組變量中

  //最後一個位置留給新加入的元素

  viewPath[count] = new ViewPath(myPanelmyView);

  return count;

  }

  //獲得實例的方法

  /**

  * 必須檢查該Panel是不是已經在路徑中了如果在路徑中

  * 則返回注冊的編號用此編號扁可以訪問到正確的類型了

  * 如果不在路徑中則以此為開始新建一個新的路徑

  * 本來檢查路徑的時候沒有必要檢查路徑的第一個元素

  * 因為一個元素不可能是開端但是為了防止用戶連續兩次registerPath的錯誤

  * 請把第一個元素也給檢查一下

  * myView 參數只有當該界面為跳轉的起始點時才需要否則保持原始的View

  * @param me

  * @param other

  * 返回實例數組的下標

  */

  public static int registerPath(JPanel myPanelBaseView myView){

  Systemoutprintln(執行registerPath() in ViewJump);

  int idx = find(myPanel);

  Systemoutprintln(idx=+idx);

  if(idx==){ //返回表示沒有找到建立一個新的路徑

  Systemoutprintln(新建一個路徑);

  idx = newPath(myPanelmyView);

  }

  Systemoutprintln(執行完注冊路徑);

  return idx; //返回實例下標

  }

  //設定要跳轉的下一個目標

  public static void setNext(int idJPanel aim){

  if(id<||id>=viewPathlength){

  return;

  }

  ViewPath vp = viewPath[id];

  //設定目標從這裡看這是存在安全漏洞的如果使用者亂傳遞id進來的話

  JPanel[] path = vppnlPath;

  path[vpindex+] = aim;

  }

  //回到上一個

  public static void back(int id){

  if(id<||id>=viewPathlength){

  return;

  }

  ViewPath vp = viewPath[id];

  //回到上一個界面

  if(vpindex>){ //只有當前面有路徑時才作

  vpbsViewremove(vppnlPath[vpindex]); //移去當前的

  vpindex; //游標往前走一步

  vpbsViewadd(vppnlPath[vpindex]BorderLayoutCENTER); //增加當前的到界面

  vpbsViewvalidate();

  vpbsViewrepaint();

  }

  }

  //回到起源處

  public static void backHome(int id){

  if(id<||id>=viewPathlength){

  return;

  }

  ViewPath vp = viewPath[id];

  //直接回到第一步需要清除該路徑嗎?中途斷裂怎麼辦?辦法是檢查View是否已為空

  //選擇不清除每次在建立新的路徑時檢查路徑是不是已經無效了

  vpbsViewremove(vppnlPath[vpindex]); //移去當前的

  vpindex = ; //游標往前走一步

  vpbsViewadd(vppnlPath[vpindex]BorderLayoutCENTER); //增加當前的到界面

  vpbsViewvalidate();

  vpbsViewrepaint();

  }

  //跳轉到下一處

  public static void jump(int id){

  if(id<||id>=viewPathlength){

  return;

  }

  ViewPath vp = viewPath[id];

  if(vppnlPath[vpindex+]==null){

  return; //下一步根本沒有設置

  }

  vpbsViewremove(vppnlPath[vpindex]); //移去當前的

  vpindex++;

  vpbsViewadd(vppnlPath[vpindex]BorderLayoutCENTER);

  vpbsViewvalidate();

  vpbsViewrepaint();

  }

  }


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26870.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.