熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

用JavaFX寫用戶界面控制器

2013-11-15 11:43:12  來源: JSP教程 

  在本文中我們關心的是BlueBill Mobile類尤其是管理所有Search Species屏幕之後邏輯的控制器;因此本文有助於你了解JavaFX的語言性能而且我們會舉出一些實例來闡述要介紹的技巧和典型JavaFX結構的陷阱

  筆者想應用程序中嵌入了更新的屏播視頻播放要求使用QucikTime

  這裡的概念是在搜索框中鍵入查詢時英文函數或科學名稱函數會對清單過濾此外當這些生效的時候BlueBill Mobile還可以執行自動完成輸入例如如果在鍵入查詢的時候你仔細查看視頻會發現只輸入了ardac來選擇Ardea Cinerea;或用於Pied Avocetpie< space>aBlueBill Mobile 會自動會剩余部分進行補充因為在某些情況下不存在其他選擇這是用來改善移動設備性能的重要功能你可以以較少的輸入達到相同目的

  按照MVC模式就非常有必要在單獨的控制器中概括這種模式;此外也很容易對這種模式進行單元測試

  首先讓我們看一下代表了分類群的模式類

  

        package ittidalwavebluebillmfxtaxonmodel;

  import javalangComparable;

  public class Taxon extends Comparable

  {

  publicread protected var displayName : String;

  publicread protected var scientificName : String;

  publicread protected var id : String;

  override function compareTo (other : Object)

  {

  return pareTo((other as Taxon)displayName);

  }

  override function toString()

  {

  return {displayName} ({scientificName}) ({id})

  }

  }

  public function displayNameGetter (taxon : Taxon): String

  {

  return taxondisplayName;

  }

  public function scientificNameGetter (taxon : Taxon): String

  {

  return taxonscientificName;

  }

  public def namePropertyGetters = [displayNameGetter scientificNameGetter];

  類托架外面定義的函數和變量相當於Java靜態分析

  這裡我們省略了一些不相關的實際項目基本上該模式暴露了三個屬性其中有意思的兩個分別是displayName和scientificName我們也可以定義兩個函數來處理這兩個問題我們會把這些函數放在namePropertyGetters序列中

  

         package ittidalwavebntroller;

  import ittidalwavebluebillmfxtaxonmodelTaxon;

  public class TaxonSearchController

  {

  public var selectedTaxon = bind if (selectedTaxonIndex < ) then null else filteredTaxons[selectedTaxonIndex];

  public var selectedTaxonIndex : Integer = ;

  public var taxons: Taxon[];

  public var filter = on replace

  {

  filteredTaxons = taxons[taxon | matches(taxon filter)];

  update();

  }

  publicread var autoCompleted = ;

  public var filteredTaxons: Taxon[];

  protected function matches (taxon : Taxon string: String) : Boolean

  {

  if (string == )

  {

  return true;

  }

  for (propertyGetter in TaxonnamePropertyGetters)

  {

  if (propertyGetter(taxon)toLowerCase()startsWith(filtertoLowerCase()))

  {

  return true;

  }

  }

  return false;

  }

  protected function update(): Void

  {

  def autoCompletedTry = commonLeadingSubstring(filteredTaxons findMatchingPropertyGetter());

  //

  // Sometimes it cant find a better autocompletion than the current filter since it searches the displayName

  // and the scientificName at the same time In this case we just ignore the new value

  //

  if (autoCompletedTrylength() > filterlength())

  {

  autoCompleted = autoCompletedTry;

  }

  selectedTaxonIndex = if (sizeof filteredTaxons == ) then else ;

  println(selectedTaxonIndex: {selectedTaxonIndex})

  }

  protected function findMatchingPropertyGetter(): function (:Taxon): String

  {

  for (taxon in filteredTaxons)

  {

  for (propertyGetter in TaxonnamePropertyGetters)

  {

  if (propertyGetter(taxon)toLowerCase()startsWith(filtertoLowerCase()))

  {

  return propertyGetter;

  }

  }

  }

  return null;

  }

  // some stuff later

  }

  這個類揭示了以下的屬性

  ·taxons你需要用完整的鳥類列表來填充

  ·filter: 字符串包括需要輸入到搜索欄中的文本

  ·filteredTaxons: 種類由filter字符串過濾

  ·autoCompleted: 控制器猜測的自動完成輸入字符串

  ·selectedTaxon: 如果filter向下細分種類它就會分配到這個變量

  ·selectedTaxonIndex: 如果無法獲取時selectedTaxon的索引

  最新的四種屬性由客戶代碼來綁定這樣做可以獲取更改提示

  Filter獲取了一個觸發事件也就是變量值更改時所執行的代碼觸發器用JavaFX運算符 ︳執行了過濾操作我們可以將觸發事件的第一行當作分配到taxons序列中的filteredTaxons來讀取在這一序列中matches()函數返回值為true第二行的代碼調用了接下來要介紹的update()函數

  出於某些原因這種方法並不一定奏效因為filteredTaxons通常會被整體掃描有多種方法可用來加速選擇過程但是本文不會在這一方法真正應用到手機前前作出過早的優化在筆記本上它可以加快個項目的速度

  Matches()函數在所有屬性上執行了一次迭代以獲取函數並檢查看相關屬性是否以過濾值啟動

  創建獲得屬性值函數的序列的一大好處是我們可以通過定義新的函數輕松添加新的匹配標准例如其他語言中的本地化名稱控制器可能會使用在搜索過程中使用這些名稱而我們則不需要再做多余修改

  Update()函數運算出了自動完成輸入提示它會提取filteredTaxons序列以及用於當前選擇的獲取屬性函數還會調用剛剛在字符串屬性的序列中找到了通用子字符串的commonLeadingSubstring()它不是每次都會作出很好的自動完成輸入猜想因此有時建議甚至比當前過濾器還短而這種情況我們大可忽略不計請不要忽視指定臨時變量的重要性由於自動完成輸入可能被綁定因此我們不想為其指定一個會迅速失效的值

  要明白這一點的重要性這不僅僅是避免無用更新還能避免程序被破壞在實際程序中自動完成輸入更改時TextBox會更新因此過濾器也會隨之更新已經輸入了cal再輸入一個i那麼TextBox暫時會顯示cali然後自動輸入完成的猜測失敗它會返回一個calTextBox中的字符串會變為cal這時候你要堅持自己的想法!綁定確實很強大但是它也同時具有負面效應

  最後一步操作中代碼會檢查看我們是否獲取單獨的已選定鳥類

  或許你對於自動完成輸入失敗的原因仍然感到很困惑畢竟我們正在逐步縮小項目列表因此如果你已經輸入了cali那麼所有經過過濾的種類會以cali開頭對嗎?如果你過濾的是一套單一名稱情況就應該是這樣;但是我們是同時對兩套名稱執行搜索那麼就會產生矛盾看看下例由cali過濾器選取的名稱組(英語科學的)(Calandra Lark Melanocorypha calandra) (Dunlin Calidris alpina) (California Quail Callipepla californica)

  另一個有意思的地方是findMatchPropertyGetter()它必須猜測當前過濾器是否是以英語科學名稱運行而且它還會返回相關的屬性獲取函數基本上控制器已經獲取了matches()函數中的這一信息但是我們會將其移走可能會有人思考讓matches()函數返回一個以上的布林值但是這是不可能的因為它是由運算符 ︳過濾序列的時候使用的該運算符需要一個布林值或許我們可以為稍後調用信息的操作指定一個成員變量不過此時的代碼應該會更具可讀性

  為了對文章進一步作補充說明這裡給大家列出了最後兩個忽略的函數

  

         protected function commonLeadingSubstring (taxons: Taxon[] propertyGetter: function (:Taxon): String): String

  {

  if (sizeof taxons == )

  {

  return ;

  }

  if (sizeof taxons == )

  {

  return propertyGetter(taxons[]);

  }

  var common = propertyGetter(taxons[]);

  for (other in taxons[])

  {

  common = commonLeadingSubstring(common propertyGetter(other));

  if (common == )

  {

  break; // dont waste time in further iterations its for sure the final result

  }

  }

  return root;

  }

  function commonLeadingSubstring (string : String string : String): String

  {

  return if (stringlength() > stringlength())

  {

  commonLeadingSubstring(string string);

  }

  else if (string == )

  {

  ;

  }

  else if (stringstartsWith(string))

  {

  string;

  }

  else

  {

  commonLeadingSubstring(stringsubstring( stringlength() ) string);

  }

  }

  這裡的邏輯很簡單通常主要的字符串搜索被分解成了臨近字符串對;而對於單一對的搜索則有遞歸執行

  這裡顯示了視圖類是如何綁定到控制器的

         package ittidalwavebluebillmfxtaxonview;

  public class TaxonSearchScreen

  {

  public var taxons : Taxon[];

  var filter = ;

  publicread def controller = TaxonSearchController

  {

  taxons: bind taxons

  filter: bind filter

  }

  def autoCompleted = bind controllerautoCompleted on replace

  {

  if (autoCompleted != )

  {

  filter = autoCompleted;

  }

  }

  def list = ListBox

  {

  items: bind controllerfilteredTaxons

  };

  def searchBox = TextBox

  {

  text: bind filter with inverse

  };

  }

  你必須用所有可得的種類加載taxon;ListBox會隨著過濾的種類自動更新TextBox與過濾器是雙重指令型綁定之所以需要雙重綁定是因為向搜索欄中輸入時一個指令用於給控制器發出新的選擇命令另一個則是自動完成輸入時的更新


From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19490.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.