2011-11-07 13 views
1

我正在開發一個GWT應用程序(我對GWT相當陌生,所以這是最佳實踐的要求;我還沒有在SO或其他地方找到任何相關的答案)在需要時間軸的地方。此時間線(帶有說明,標籤,交互句柄和圖表)位於其自己的容器中(Panel)。在GWT頁面中重繪容器或單個動態元素?

  [<] [now] [>]    // Interaction (navigation) 
      2007 2008 2009 2010  // Labels 
      | | | | 
+ Group 1       // Collapsible groups 
- Group 2 
    Item 2a ===== ==    // Item with plots (plots are wrapped in container per Item) 
    Item 2b =====  === = 
-Group 3 
    Item 3a === 
    Item 3b  === 

現在,當用戶的瀏覽時間線(使用按鈕向前或向後),我需要重新計算佈局的一些元素:

  • 標籤需要重新計算/重新定位
  • 地塊需要重新計算/重新定位。繪圖基於一組Timeslot元素(擴展Widget,屬性dateStartdateEnd),這些元素已經與Item相關,其與Group有關。

可摺疊面板爲DisclosurePanel s。

至於我可以告訴大家,我現在已經爲處理導航兩種選擇:

  1. 我可以clear()容器板,做一個完整的重繪。爲此,我需要保留所有組的狀態(摺疊/展開)。 (順便說一句,組和項目在整個期間都是靜態的!)這會給一個大的重繪
  2. 我可以讓劇情容器(每個Item都有自己的TimeslotContainer這是一個FlowPanel)持有其所有Timeslot個引用,然後讓每一個TimeslotContainer重繪自身(即,過濾器和位置相關的Timeslot S)基於當前時間跨度。這將給幾個小的重繪(每Item每擴展Group一個),其優點是,將保留,從而保持其自己的狀態。

我傾向於採用第二種解決方案。但是有沒有這方面的最佳做法?我是否缺少一些常見的陷阱?

回答

0

我繼續並實施了第二個解決方案的一個版本,如果第二個解決方案沒有充分發揮作用,那麼將嘗試第一個解決方案。 (但是,這從來沒有實現過,因爲第二種解決方案表現得非常令人滿意)。

我在問題中問的主要是參考GWT方式來做到這一點。我仍然沒有發現任何關於這個問題的書面信息,因此懷疑沒有人會錯過這些指南:)爲了結束我的搜索,我將自我回答這個問題,概述我最終與(假設的)專業人員一起實施的方式,利弊。感謝@Ümit支持我的直覺。以下部分旨在解決關於繪製方法的複雜性@Ümit's answer的最後一段。


我結束了讓TimeslotContainer S(含有TimeSlot S上的面板),LabelPanel(面板與所生成的HTML元素),和NavigationPanel實現一個簡單的接口:

public interface IReceivesPeriodChangedEvents { 
    public void periodChanged(); 
} 

簡單EventBus處理這些IReceivesPeriodChangedEvents實例的通知過程:

public class EventBus { 
    private static EventBus instance; 

    private Set<IReceivesPeriodChangedEvents> receivers; 

    private EventBus() { 
     this.receivers = new HashSet<IReceivesPeriodChangedEvents>(); 
    } 

    public static EventBus getInstance() { 
     if (instance == null) { 
      instance = new EventBus(); 
     } 

     return instance; 
    } 

    public void addReceiver(IReceivesPeriodChangedEvents receiver) { 
     this.receivers.add(receiver); 
    } 

    public void notifyPeriodChanged() { 
     for (IReceivesPeriodChangedEvents receiver : this.receivers) { 
      receiver.periodChanged(); 
     } 
    } 
} 

每當TimeslotContainerLabelPanelNavigationPanel一個被實例化(每秒一次頁面加載,這些對象在整個頁面的生命週期重用),他們確信訂閱EventBus

public class TimeslotContainer extends FlowPanel implements IReceivesPeriodChangedEvents { 
    public TimeslotContainer(/* ... */) { 
     // ... 
     EventBus.getInstance().addReceiver(this); 
    } 
    // ... 
} 

爲了處理我簡單地創建了一個方法(buildFromStore())來添加相關的Widget(例如,在TimeslotContainers上新創建的Timeslot對象)。這導致繪製方法的重複使用:

public class NavigationPanel extends FlowPanel implements IReceivesPeriodChangedEvents { 
    public NavigationPanel() { 
     // ... 
     buildFromStore(); 
     EventBus.getInstance().addReceiver(this); 
    } 

    private void buildFromStore() { 
     // Add lots of HTML elements here 
    } 

    @Override 
    public void periodChanged() { 
     clear(); 
     buildFromStore(); 
    } 
} 

就這麼簡單!


結論:
沒有陷阱中遇到。許多小的重繪似乎沒有問題(但我從來沒有實施過解決方案)。繪製方法可以重用(在這種情況下,至少)。可摺疊的DisclosurePanel從來沒有失去他們的狀態,因爲他們從來沒有被取代(只有他們的內容)。

+0

我喜歡你的方法。 只有3條評論: - 爲什麼你沒有使用GWT的EventBus之一(http://google-web-toolkit.googlecode.com/svn/javadoc/latest/com/google/gwt/event/shared/EventBus .html)的實現(即SimpleEventBus)?您可以將它們用作TimeslotContainer的本地EventBus。 - 如果您的buildFromStore()方法在檢索包含/父容器的大小上進行depdends,那麼您可能會遇到問題並且必須將實際佈局推遲到最後(使用Scheduler.get()。scheduleDeferred())。 - 您也可以實現RequireResize接口來調整事件大小。 –

+0

@Ümit好問題! 1)是的,使用現有的「EventBus」是有意義的。不過,我現在只需要這個功能,並且在解決方案插入到現有項目(我們已經使用增強的EventBus)時將重寫這些代碼。 2)和3)實際的尺寸和位置按百分比設置,因此根據容器通過CSS佈置。因此,我能夠做到這一切,沒有任何鉤子調整大小處理程序等(我敢打賭,這是什麼使最終這麼簡單:)) – jensgram

+1

感謝您的更新。我還喜歡尺寸爲百分比(流體/柔性設計)。然而不幸的是有時候這是不可能的。例如,如果您使用Google可視化圖表,則需要明確的像素大小,並且這些必須動態計算。我遇到了很多麻煩,直到我偶然發現[HeaderPanel]的代碼(http://www.google.com/codesearch#A1edwVHBClQ/user/src/com/google/gwt/user/src/com/google/gwt/user/client/ui/HeaderPanel的.java&q = HeaderPanel%20package:HTTP://google-web-toolkit%5C.googlecode%5C.com&type=cs)。只是爲了記錄,如果你碰到相同的問題;-) –

1

如果組和項目是靜態的,我還會推薦第二種方法。
DOM操作(構造等)適合GWT應用程序中最昂貴的功能(性能明智),因此這些DOM操作應保持在最低限度。
但是,我不認爲性能可能是一個大問題,因爲DOM元素的數量相對較少。

儘管如此,我仍然認爲第二種方法更好。您不必爲組和項目存儲狀態,因爲它們是靜態的,重繪它們並不合理。

我只能想到第一種方法的一個優點: 只有一個相對容易的繪圖功能。在第二種方法中,所有的TimesSlotContainer必須實現一個函數來重繪自己,並且還要考慮Timespan的位置和上下文。這個功能可能比一個大的重畫功能更復雜。