2013-01-16 64 views
1

我有,例如,這樣的模式在我的QML:試圖從ListElement在ListModel的QML調用自定義功能

ListModel{ 
    id: mainlist 
    ListElement 
    { 
     name: "Name1" 
     type: "subMenu" 
     toogle: false 
     iconSource: "" 

     function actionClick() 
     { 
      console.log("actionclick is passed for 0 item!") 
     } 
    } 
    ListElement 
    { 
     name: "Manage Favorites" 
     type: "subMenu" 
     toogle: false 
     iconSource: "image://provider/common/endless_menu/list_icons/fav" 

     function actionClick() 
     { 
      console.log("actionclick is passed for 1 item!") 
     } 
    } 
    ListElement 
    { 
     name: "Name2" 
     type: "subMenu" 
     toogle: false 
     iconSource: "image://provider/common/endless_menu/list_icons/active" 

     function actionClick() 
     { 
      console.log("actionclick is passed for 2 item!") 
     } 
    } 
    ListElement 
    { 
     name: "Name3" 
     type: "subMenu" 
     toogle: false 
     iconSource: "image://provider/common/endless_menu/list_icons/scan" 

     function actionClick() 
     { 
      console.log("actionclick is passed for 3 item!") 
     } 
    } 
    ListElement 
    { 
     name: "Manual Frequency Input" 
     type: "commonBtn" 
     toogle: false 
     iconSource: "" 

     function actionClick() 
     { 
      console.log("actionclick is passed for 4 item!") 
     } 
    } 

    function onStart(currIndex) 
    { 
     console.log("test is passed for " + currIndex + "item!") 
    } 
} 

所以,我有id: optionlist控制列表元素的ListView元素,ListDelegate。 我有幾個模型 - 爲項目中的菜單選項創建的所有這些元素。 因此,列表文件中的代碼onModelChanged: optionlist.model.onStart()完美工作。

問題是在MouseArea元素中從listDelegate腳本OnClicked調用actionClick()函數。是否有可能做到這一點? 類似這樣的:optionlist.model.ContentItem.children[currentIndex].actionClick()也許還有別的?

UPDATE: 對不起,艾米特Tomer的,也許我不解釋任務正確......所以,我需要元素與未來域模型:

name: - text for element 
type: - type of element (button, radio button, check button or submenu) - needed for corect action when user clicked on this item 
toogle: - boolean value for radio/check buttons state, and for some internal operations. 
iconSource: - path for icon, if it needed. 

function actionClick() - function, which will be execute when user clicked on this item. 

這一切都必須爲明確和容易實現填滿所有選項菜單樹。該菜單樹將被寫入單獨的文件中。

在下面的代碼我告訴工作模式:

Item{ 
    id: menuoptions 

    property ListModel prev: manageFavorites 
    property bool root: true 

//Main Menu 
    property alias mainlist: mainlist 
    ListModel{ 
     id: mainlist 
     ListElement 
     { 
      name: "Band: " 
      type: "subMenu" 
      toggle: false 
      iconSource: "" 
     } 
     ListElement 
     { 
      name: "Manage Favorites" 
      type: "subMenu" 
      toggle: false 
      iconSource: "image://provider/common/endless_menu/list_icons/fav" 
     } 
     ListElement 
     { 
      name: "Show: " 
      type: "subMenu" 
      toggle: false 
      iconSource: "image://provider/common/endless_menu/list_icons/active" 
     } 
     ListElement 
     { 
      name: "Scan" 
      type: "subMenu" 
      toggle: false 
      iconSource: "image://provider/common/endless_menu/list_icons/scan" 
     } 
     ListElement 
     { 
      name: "Manual Frequency Input" 
      type: "commonBtn" 
      toggle: false 
      iconSource: "" 
     } 

     function actionClick(currIndex) 
     { 
      switch(currIndex) 
      { 
       case 0: 
       { 
        prev = mainlist 
        menuList.model = bandlist 
        break 
       } 
      case 1: 
       { 
        prev = mainlist 
        menuList.model = manageFavorites 
        break 
       } 
      case 2: 
       { 
        prev = mainlist 
        menuList.model = showlist 
        break 
       } 
      case 3: 
       { 
        console.log("Scan started") 
        mainlist.setProperty(3, "name", getScan()) 
        break 
       } 
      case 4: 
       { 
        console.log("Speller for Manual Frequency Input open!") 
        break 
       } 
      } 
     } 

     function onStart() 
     { 
      console.log("root model loaded") 
      root = true 
      mainlist.setProperty(0, "name", "Band: " + getBand()) 
      mainlist.setProperty(2, "name", "Show: " + getShow()) 
      mainlist.setProperty(3, "name", getScan()) 
     } 
    } 

//First Lvl subMenu 
    property alias bandlist: bandlist 
    ListModel{ 
     id: bandlist 
     ... Analog menulist 
    } 

    property alias manageFavorites: manageFavorites 
    ListModel{ 
     id: manageFavorites 
     ... Analog menulist 
    } 

    property alias showlist: showlist 
    ListModel{ 
     id: showlist 
     ... Analog menulist 
    } 
} 

正如你看到的,我喜歡你說的寫的東西。沒關係,如果我找不到更好的解決方案。 Beter解決方案 - 刪除actionClick()一般函數,並將它的一部分(以塊爲單位的代碼)分別添加到ListElement。並在元素點擊時調用它。

我不知道如何從ListElement調用此函數。在WPF中,我只需創建自定義組件,即可重新使用ListElement,並且只需要所有組件!但我不知道QML是如何實現的。

我什麼都不清楚 - 請問。

更新:問題已解決。我的答案中的變體。謝謝大家。

+0

我認爲它現在變得更加困惑:-( –

+0

我什麼都不清楚 - 請問( – Corwin

回答

0

問題解決了。但起初並不像計劃那樣。

import QtQuick 2.0 

/* 
Elements of model: 
name - displayed text 
type - type of element, for clicked event 
toggle - state for radio and check btn 
iconSource - path to icon 

*/ 
/* 
TYPE: 
radioBtn 
checkBtn 
commonBtn 
subMenu 
*/ 
Item{ 
    id: menuoptions 

    //property ListModel prev: listmodel 

    property Item curr: mainList 

    //TEST FUNCTIONS 
    property string band: "AM" 
    property string show: "All" 
    //END TEST FUNCTION 

//Main Menu Radio 
    Item{ 
     id: mainList 
     property int count: 7 
     property Item prev 

     children: 
     [ 
      Item 
      { 
       property string name: "Band: " 
       property string type: "subMenu" 
       property bool toggle: false 
       property string iconSource: "" 

       property bool need: true 

       function onClick() 
       { 
        curr = bandList 
        loadModel() 
       } 
      }, 
      Item 
      { 
       property string name: "Manage Favorites" 
       property string type: "subMenu" 
       property bool toggle: false 
       property string iconSource: "image://provider/common/endless_menu/list_icons/fav" 

       property bool need: true 

       function onClick() 
       { 
        curr = manageFavList 
        loadModel() 
       } 
      }, 
      Item 
      { 
       property string name: "Show: " 
       property string type: "subMenu" 
       property bool toggle: false 
       property string iconSource: "image://provider/common/endless_menu/list_icons/active" 

       property bool need: true 

       function onClick() 
       { 
        curr = showList 
        loadModel() 
       } 
      }, 
      Item 
      { 
       property string name: "Scan" 
       property string type: "subMenu" 
       property bool toggle: false 
       property string iconSource: "image://provider/common/endless_menu/list_icons/scan" 

       property bool need: true 

       function onClick() 
       { 
        if (!listmodel.get(menuList.currentIndex).toggle) 
        { 
         listmodel.setProperty(menuList.currentIndex, "toggle", true) 
         listmodel.setProperty(menuList.currentIndex, "name", "Scan") 
        } 
        else 
        { 
         listmodel.setProperty(menuList.currentIndex, "toggle", false) 
         listmodel.setProperty(menuList.currentIndex, "name", "Stop") 
        } 

       } 
      }, 
//optional 
      Item 
      { 
       property string name: "Alternative Frequency" 
       property string type: "checkBtn" 
       property bool toggle: false 
       property string iconSource: "" 

       property bool need: false 

       function onClick() 
       { 
        if (listmodel.get(menuList.currentIndex).toggle) 
        { 
         listmodel.setProperty(menuList.currentIndex, "toggle", false) 
         listmodel.setProperty(menuList.currentIndex + 1, "toggle", false) 
        } 
        else 
        { 
         listmodel.setProperty(menuList.currentIndex, "toggle", true) 
        } 
       } 
      }, 
      Item 
      { 
       property string name: "Regionalization" 
       property string type: "checkBtn" 
       property bool toggle: false 
       property string iconSource: "image://provider/common/endless_menu/list_icons/scan" 

       property bool need: false 

       function onClick() 
       { 
        if (listmodel.get(menuList.currentIndex - 1).toggle) 
        { 
         if (listmodel.get(menuList.currentIndex).toggle) 
         { 
          listmodel.setProperty(menuList.currentIndex, "toggle", false) 
         } 
         else 
         { 
          listmodel.setProperty(menuList.currentIndex, "toggle", true) 
         } 
        } 

       } 
      }, 
//end optional 
      Item 
      { 
       property string name: "Manual Frequency Input" 
       property string type: "commonBtn" 
       property bool toggle: false 
       property string iconSource: "" 

       property bool need: true 

       function onClick() 
       { 
        console.log("Speller for Manual Frequency Input open!") 
       } 
      } 
     ] 
     function preLoad() 
     { 
      console.log("preload Func") 
      children[0].name = "Band: " + band 
      children[2].name = "Show: " + show 
      if (band == "SAT" || band == "AM") 
      { 
       children[4].need = false 
       children[5].need = false 
      } 
      if (band == "FM") 
      { 
       children[4].need = true 
       children[5].need = true 
      } 
     } 
    } 

//First Lvl subMenu Radio 
    Item{ 
     id: bandList 
     property int count: 3 
     property Item prev: mainList 

    //Analog as mainList 
    } 

    Item{ 
     id: manageFavList 
     property int count: 3 
     property Item prev: mainList 

    //Analog as mainList 
     function preLoad() 
     { 
      console.log("preload Func for Manage Favorite List") 
      //Insert into model fav stations from 0 item 
      //favcount = gateway.getFavCount() 
     } 
     function favClick() 
     { 
      console.log("Favorite item clicked") 
     } 
    } 

    Item{ 
     id: showList 
     property int count: 2 
     property Item prev: mainList 

    //Analog as mainList 
    } 



//Service Items 
    property alias listmodel: listmodel 
    ListModel{ 
     id: listmodel 
} 
    function loadModel() 
    { 
     console.log("loader menu") 
     favcount = 0; 
     listmodel.clear() 
     curr.preLoad() 
     for (var i=0;i<curr.count;i++) 
     { 
      if (curr.children[i].need){ 
       listmodel.append({"name": curr.children[i].name, 
            "type":curr.children[i].type, 
            "toggle":curr.children[i].toggle, 
            "iconSource":curr.children[i].iconSource}) 
      } 
     } 
    } 

    function actionClick(currIndex) 
    { 
     if (favcount == 0) 
      curr.children[currIndex].onClick() 
     else 
     { 
      if (currIndex <= favcount - 1) 
       curr.favClick() 
      else 
       curr.children[currIndex-favcount].onClick() 
     } 
    } 

    function toggled(index) 
    { 
     for (var i=0; i<listmodel.count; i++) 
      listmodel.setProperty(i, "toggle", false) 
     listmodel.setProperty(index, "toggle", true) 
    } 
} 

正如你看到的,通過改變從項目元素清洗模型和灌裝解決optionMenu。

每個項目 - 是一個屏幕。

服務項目 - 一般組件和功能。

現在我認爲,這將是尤爲明顯,以menuTree(項目組件)在其他文件分開,因爲將有3種不同的OptionMenu用不同的樹木。

0

這個如何:

import QtQuick 1.0 

Rectangle 
{ 
    color: "grey" 
    width: 800 
    height: 800 

    function actionClick(index) 
    { 
     if(0 == listModel.get(index).internalIndex) 
      functionForElement1() 
     else if(1 == listModel.get(index).internalIndex) 
      functionForElement2() 
     else if(2 == listModel.get(index).internalIndex) 
      functionForElement3() 
     else if(3 == listModel.get(index).internalIndex) 
      functionForElement4() 
     else if(4 == listModel.get(index).internalIndex) 
      functionForElement5() 
    } 

    functionForElement1() { console.log("Inside Function 1")  } 
    functionForElement2() { console.log("Inside Function 2")  } 
    functionForElement3() { console.log("Inside Function 3")  } 
    functionForElement4() { console.log("Inside Function 4")  } 
    functionForElement5() { console.log("Inside Function 5")  } 

    ListView 
    { 
     anchors.centerIn: parent 
     width: parent.width 
     height: parent.height 
     model: listModel 
     spacing: 10 
     delegate: Component 
     { 
      Rectangle 
      { 
       x: 350 
       y: 350 
       width: 100 
       height: 50 
       Text { text: name ; anchors.centerIn: parent } 

       MouseArea 
       { 
        anchors.fill: parent 
        onClicked: actionClick(index) 
       } 
      } 
     } 

     ListModel 
     { 
      id: listModel 

       ListElement { name: "Apple",   internalIndex: 1} 
       ListElement { name: "badApple" ,  internalIndex: 2} 
       ListElement { name: "goodApple" ,  internalIndex: 3} 
       ListElement { name: "worseApple" , internalIndex: 4} 
       ListElement { name: "spoilledApple" , internalIndex: 5} 
     } 
    } 
} 
+0

這不是一個選項,因爲有些元素是子菜單和函數重裝模型,所以我不能寫這樣的函數 - 每個項目在每一個模型中調用獨特的方法從beckend和perfom動作就像按鈕或進入子菜單,我只留下了console.log的功能,例如每個功能都是唯一的 – Corwin

+0

我已經編輯了您的要求的解決方案請檢查 –

+0

Now actionClick(index)我放在ListModel中,因爲onStart(currIndex)是。如你所知,actionClick用案例編寫。但是,只有在沒有可能性從元素調用函數時纔是正確的。因爲如果我更改模型中元素的位置 - 我需要更改actionClick。就像我告訴的那樣,這不好。我只需要知道 - 如果有任何可能性從元素調用函數,如我的例子。改變我的模型對我來說並不好。 – Corwin