首 页 | 新 闻 | Symbian | Android| Windows Mobile | J2ME | 下载中心 | 游戏策划招聘与求职 | 购书指南 | 视频教程
您现在的位置: 开发视界 >> Symbian英文资料 >> User Interface >> 正文
Creation of a high score table (Part III): Display in a ListBox
作者:佚名    文章来源:不详    更新时间:2006-5-7 11:19:30

After having created and stored our highscore table, we will now display it using one of the various Series60 listbox classes.

One of the best listbox style for doing this is the CAknDoubleNumberStyleListBox listbox, as shown on the picture. If you prefere a more compact list (typically to display bigger score tables), the very basic CAknSingleNumberStyleListBoxis also nice.

The basic (non-UI) handling of the high score table is done in the CScoreModel class which is 99% similar to the CGame class introduced in Part II article. This class does nothing related to UI so we will suppose you are familiar with it.

The key class here is the Application UI container (CScore5Container). It has a pointer to the score model through its iScore private member and another one to a CEikTextListBox object (iListBox):


class CScore5Container : public CCoeControl, MCoeControlObserver

{
public: // Constructors and destructor
   void ConstructL(const TRect& aRect,CScoreModel *aScore);
   ~CScore5Container();

public: // New functions
   void UpdateFromModel();

private:
   void ReplaceScoreL(TInt aPos,TScore* aScore);

// From CoeControl
   void SizeChanged();
   TInt CountComponentControls() const;
   CCoeControl* ComponentControl(TInt aIndex) const;
   void Draw(const TRect& aRect) const;
   void HandleControlEventL(CCoeControl* aControl,
                            TCoeEvent aEventType);
   TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,
                               TEventCode aType );

private: //data
   CEikTextListBox *iListBox;
   CScoreModel *iScore;
};

Construction of the ListBox

As usual, the listbox is fully constructed in the container second-phase constructor ConstructL():
  The ListBox object is allocated on the heap. This is the place where you decide the graphical layout of the list (here: CAknDoubleNumberStyleListBox):


 iListBox = new(ELeave)CAknDoubleNumberStyleListBox;
 iListBox->SetContainerWindowL(*this);

  Then it is initialised from the r_akn_score_list resource that should be declared in the application RSS file (the format will be explained below - notice the uppercase name in the cpp code and the lowercase name in the rss file):


 TResourceReader rr;
 iCoeEnv->CreateResourceReaderLC(rr,R_AKN_SCORE_LIST);
 iListBox->ConstructFromResourceL(rr);
 CleanupStack::PopAndDestroy(); //rr

  A Scroll bar is created:


 iListBox->CreateScrollBarFrameL(ETrue);
 iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(
       CEikScrollBarFrame::EOff,
       CEikScrollBarFrame::EAuto);

At this step, the listbox is created. You just have to expose it in the container CountComponentControls() and ComponentControl(), delete it in the container destructor and the list, as defined in the RSS file shall be displayed :


CScore5Container::~CScore5Container()
{
 delete iListBox;
}

TInt CScore5Container::CountComponentControls() const
{
 return 1;
}

CCoeControl* CScore5Container::ComponentControl(TInt aIndex) const
{
 switch ( aIndex )
 {
 case 0:
     return iListBox;
 default:
     return NULL;
 }
}

The ListBox RSS file definition

The definition of a ListBox in a RSS file is quite simple once you now the string format to use. You define a LISTBOX resource item (here named r_akn_score_list), decide of the flag to indicate the kind of interaction with the user (possible values are EAknListBoxSelectionList, EAknListBoxMenuList, EAknListBoxMarkableList, EAknListBoxMultiselectionList or EAknListBoxViewerFlags. Here I have choosen the EAknListBoxSelectionList because I want the user to be able to browse through the list and select an entry to display more details (ex: date, level reached, number of ennemies killed,...).

You will ned to include the avkon.hrh file in your RSS to allow proper recognition of the EAkn... constants by the resource compiler.

And last, you give the content for all the items of the list. The string value has a special format that is dependent of the ListBox style we have selected in the container constructor. For a CAknDoubleNumberStyleListBox, the format is in our case : "<Rank>,<Player Name>,<Score>"

The format for each style is described in the aknlists.h file located under Epoc32/Include directory.

Here is the full declaration of our ListBox:


RESOURCE LISTBOX r_akn_score_list
{
 array_id = r_akn_score_list_items;
 flags    = EAknListBoxSelectionList;
}

RESOURCE ARRAY r_akn_score_list_items
{
 items =
 {
   LBUF { txt = "1\t...\t00000"; },
   LBUF { txt = "2\t...\t00000"; },
   ...
   LBUF { txt = "9\t...\t00000"; }
 };
}

Adding Dynamic Content to the ListBox

Up to this point, we have just seen how to construct and display the ListBox. It is now time to add dynamic content to it. There is two main way to do this :
  use your own text array and provide it as the list model (you should use the MDesCArray to do this.
  use the text array provided by default as the list model.

Both have pros and cons. In this case, I have selected the second option because my CScoreModel does not have an array of string in ListBox format ( "<Rank>,<Player Name>,<Score>"). The list model is initialised from the score values at the end of the container ConstructL() by a call to the UpdateFromModelL() function :


void CScore5Container::UpdateFromModelL()
{
 int i,count=iScore->Count();
 for(i=0;i<count;i++)
 {
   ReplaceScoreL(i,iScore->At(i));
 }
}

This function takes each entry of the CScoreModel array and writes it at its rank in the ListBox model by a call to ReplaceScoreL(). The dirty work being made by this latter function:


void CScore5Container::ReplaceScoreL(TInt aPos,TScore* aScore)
{
 TBuf<20> str;
 CDesCArray* array=static_cast<CDesCArray*>(iListBox->Model()->ItemTextArray());
 str.Format(_L("%d\t%S\t%d"),
            aPos+1,
            aScore->Name(),
            aScore->Score());
 array->InsertL(aPos,str);
 array->Delete(aPos+1);
 iListBox->HandleItemAdditionL();
}

The function:
  gets a pointer on the list box internal model (array).
  format the TScore score entry properly in the str descriptor
  inserts the descriptor in the ListBox model
  delete the one that was previously at the same position
  and request the listbox to handle the change.

This is definitely not the most optimized way to do this (typically the HandleItemAdditionL() call should be moved into UpdateFromModelL() to avoid it being called nine times. But I was too lazy to fix it for now...

 
 

Score5.zip

 


<<Creation of a high score table (Part II): saving to a file store


相关文章:
Creation of a high score table (Part II): saving to a file store
Creation of a high score table (Part I): using a CArray
Creation of a high score table (Part III): Display in a ListBox
 

站点地图 | 加入收藏 | 联系站长 | 广告服务 |
QQ:280529124  Tel:0592-8271361 辽ICP备05021703号