2015-11-06 65 views
3

在雙窗格的文件管理器的context,我有兩個並列的TabView項目方面,均含有當然的多個選項卡,並顯示的內容各Tab加載一個TableView具體目錄使用FolderListModel獲取活動標籤和更改項目性質

SplitView 
    TabView 
     Tab 
     Tab 
    TabView 
     Tab 

我現在的任務就是實現一個工具欄按鈕來切換在活躍標籤所示的FolderListModel實例的showHidden財產。因此,我需要一種方法來查明當前活動選項卡是什麼。

接下來,一旦我得到有效Tab,我需要改變Tab.item.some_property,特別感興趣的性質是show_hidden,這是一個別名底層FolderListModelshowHidden財產。例如,一個硬編碼的情況是:

ToolButton { 
    onClicked: { 
     tab1.item.show_hidden = false; 
     tab1.destroy(); // need "refresh" instead 
    } 
} 

首先,我需要根據它是否處於活動狀態得到tab1,和第二,我改變show_hidden後,認爲自身不刷新,所以我需要調用某種重載功能,但是哪一個?或者重新加載不是最好的辦法嗎?是否可以使用自定義信號處理程序來完成? (同樣我只能認爲在概念上不知道如何實現它。)

至於建議我張貼下面運行的例子:

/* main.qml */ 
import QtQuick 2.4 
import QtQuick.Controls 1.4 
import QtQuick.Layouts 1.1 

ApplicationWindow { 
    visible: true 
    width: 1280 
    height: 700 

    toolBar: ToolBar { 
     RowLayout { 
      anchors.fill: parent 

      ToolButton { 
       onClicked: { // TODO toggle folderModel.showHidden property 
        tab1A.item.show_hidden = false; 
//     tab1A.destroy(); // fixme how to refresh the view? 
       } 
      } 
     } 
    } 

    Item { 
     anchors.fill: parent 

     SplitView { 
      id: splitView 
      anchors.fill: parent 

      TabView { 
       id: tabView1 
       width: splitView.width/2 

       Tab { 
        id: tab1A 

        title: qsTr("Home") 
        source: "dirview.qml" 

        onLoaded: { 
         item.folder_url = "file:///tmp"; 
        } 
       } 

       Tab { 
        title: qsTr("Folder") 
        source: "dirview.qml" 
        onLoaded: { 
         item.folder_url = "file:///home"; 
        } 
       } 
      } 

      TabView { 
       id: tabView2 

       Tab { 
        title: qsTr("Home") 
        source: "dirview.qml" 
        onLoaded: { 
         item.folder_url = "file:///home"; 
        } 
       } 
      } 
     } 
    } 
} 

/* dirview.qml */ 
import QtQuick 2.4 
import QtQuick.Controls 1.4 
import Qt.labs.folderlistmodel 2.1 

TableView { 
    property alias folder_url: folderModel.folder 
    property alias show_hidden: folderModel.showHidden 

    id: tableView 
    anchors.fill: parent 

    TableViewColumn { 
     role: "fileName" 
     title: qsTr("Name") 
     width: tableView.width * 0.7 
    } 

    TableViewColumn { 
     role: "fileSize" 
     title: qsTr("Size") 
     width: tableView.width * 0.2 
    } 

    FolderListModel { 
     id: folderModel 
     nameFilters: ["*"] 
     showHidden: true 
     showDirsFirst: true 
     showDotAndDotDot: true 
    } 

    model: folderModel 
} 

謝謝。


發現了一些奇怪的:Tab.item.folder_url有正確的信息,但是,Tab.item.show_hidden總是false,即使我刪除,我手動將它設置爲false行。這很難理解,因爲我最初在dirview.qml中設置了FolderListModel.showHiddentrue

ToolButton { 
    onClicked: { // TODO toggle folderModel.showHidden property 
     var cur_tab_idx = tabView1.currentIndex; 

     console.log(tabView1.getTab(cur_tab_idx).item.folder_url); 
     console.log(tabView1.getTab(cur_tab_idx).item.show_hidden); 
    } 
} 
+0

我想你必須提供一個最小的運行示例。與*一個* TabView'的東西,以便我們可以看到什麼不是「刷新」。第一個問題的答案是:http://doc.qt.io/qt-5/qml-qtquick-controls-tabview.html#currentIndex-prop – Mitch

+0

@Mitch感謝您關於活動選項卡的提示。但是我意識到,由於工具欄按鈕由兩個「窗格」(「TabView」)共享,因此在獲取活動選項卡之前,我需要知道哪個窗格處於活動狀態,在「SplitView」下。我沒有看到後者提供任何方法來找出哪些孩子是活躍的? – treslumen

+0

我不明白。你只有'SplitView'中的一個孩子.. – Mitch

回答

0

這是我如何使它工作的解釋。

我用focus標誌解決了第一個問題。噹噹前TabTabView更改一個Tab獲得重點和另一個失去。因此,通過使用onFocusChanged()信號,您可以確切知道一個Tab何時變爲活動或非活動狀態。
當整個TabView的焦點改變時,Tab的焦點不會改變。因此,我創建了Array(在代碼中命名爲標籤),其中包含對其包含的每個TabViewTab的引用。有了這個,當TabView變爲不活動時,我可以使用簡單的for將其Tab對象的focus設置爲false

第二個問題更棘手。我看到沒有其他選擇將showHidden標誌關閉,而不是銷燬並創建新的FolderListModel。我們不能(或者我不能:))動態地提供modelTableView,所以我做了ListModel。與FolderListModel相比,常規ListModel的優勢在於可以清除並重新填充數據。每次更改folder_urlshow_hidden,我銷燬當前FolderListModel並創建一個新的。創建後,我將其數據重寫爲ListModel


這裏是工作代碼。

main.qml

/* main.qml */ 
import QtQuick 2.4 
import QtQuick.Controls 1.4 
import QtQuick.Layouts 1.1 

ApplicationWindow { 
    visible: true 
    width: 1280 
    height: 700 

    property var tabs: [ 
     [tabView1, [tab1A, tab1B]], 
     [tabView2, [tab2A]] 
    ] 

    toolBar: ToolBar { 
     RowLayout { 
      anchors.fill: parent 

      ToolButton { 
       onClicked: { // TODO toggle folderModel.showHidden property 
        tab1A.item.show_hidden = false; 
//     tab1A.destroy(); // fixme how to refresh the view? 
       } 
      } 
     } 
    } 

    Item { 
     anchors.fill: parent 

     SplitView { 
      id: splitView 
      anchors.fill: parent 

      TabView { 
       id: tabView1 
       width: splitView.width/2 

       Tab { 
        id: tab1A 

        title: qsTr("Home") 
        source: "dirview.qml" 

        onLoaded: { 
         item.folder_url = "file:///tmp"; 
        } 
        onFocusChanged: { 
         item.show_hidden = focus 
        } 
       } 
       onFocusChanged: { 
        if (!focus) 
         for (var i = 0 ; i < tabs[0][1].length ; i++) 
          tabs[0][1][i].focus = false 
       } 

       Tab { 
        id: tab1B 
        title: qsTr("Folder") 
        source: "dirview.qml" 
        onLoaded: { 
         item.folder_url = "file:///home"; 
        } 
        onFocusChanged: { 
         item.show_hidden = focus 
        } 
       } 
      } 

      TabView { 
       id: tabView2 

       Tab { 
        id: tab2A 
        title: qsTr("Home") 
        source: "dirview.qml" 
        onLoaded: { 
         item.folder_url = "file:///tmp"; 
        } 
        onFocusChanged: { 
         item.show_hidden = focus 
        } 
       } 
       onFocusChanged: { 
        if (!focus) 
         for (var i = 0 ; i < tabs[1][1].length ; i++) 
          tabs[1][1][i].focus = false 
       } 
      } 
     } 
    } 
} 

dirview.qml

/* dirview.qml */ 
import QtQuick 2.4 
import QtQuick.Controls 1.4 
import Qt.labs.folderlistmodel 2.1 

TableView { 
    property string folder_url 
    property bool show_hidden 

    id: tableView 
    anchors.fill: parent 

    TableViewColumn { 
     role: "fileName" 
     title: qsTr("Name") 
     width: tableView.width * 0.7 
    } 

    TableViewColumn { 
     role: "fileSize" 
     title: qsTr("Size") 
     width: tableView.width * 0.2 
    } 

    ListModel { 
     id: secondListModel 
    } 

    property var fm 
    property int folderModelCount 

    onFolder_urlChanged: { 
     reloadFolderModel() 
    } 
    onShow_hiddenChanged: { 
     reloadFolderModel() 
    } 

    onFolderModelCountChanged: { 
     resetSecondListModel() 
    } 

    function reloadFolderModel() { 
     folderModelCount = 0 
     if (typeof(fm) !== "undefined") 
      fm.destroy() 

     var component = Qt.createComponent("foldermodel.qml") 
     if (component.status === Component.Ready) 
      fm = component.createObject(
         tableView, {"folder_url": folder_url, "show_hidden": show_hidden}) 
     else 
      console.error(component.errorString()) 

     folderModelCount = 
       Qt.binding(function(){return fm.folderModel.count}) 
    } 

    function resetSecondListModel() { 
     secondListModel.clear() 
     for (var i = 0 ; i < folderModelCount ; i++) { 
      secondListModel.append({ 
             "fileName": fm.folderModel.get(i, "fileName"), 
             "filePath": fm.folderModel.get(i, "filePath"), 
             "fileURL": fm.folderModel.get(i, "fileURL"), 
             "fileBaseName": fm.folderModel.get(i, "fileBaseName"), 
             "fileSuffix": fm.folderModel.get(i, "fileSuffix"), 
             "fileSize": fm.folderModel.get(i, "fileSize"), 
             "fileModified": fm.folderModel.get(i, "fileModified"), 
             "fileAccessed": fm.folderModel.get(i, "fileAccessed"), 
             "fileIsDir": fm.folderModel.get(i, "fileIsDir") 
            }) 
     } 
    } 

    model: secondListModel 
} 

foldermodel.qml(添加文件)

import QtQuick 2.4 
import QtQuick.Controls 1.4 
import Qt.labs.folderlistmodel 2.1 

Item { 
    property string folder_url 
    property bool show_hidden 
    property alias folderModel: folderModelObject 
    FolderListModel { 
     id: folderModelObject 
     nameFilters: ["*"] 
     folder: folder_url 
     showHidden: show_hidden 
     showDirsFirst: true 
     showDotAndDotDot: true 
    } 
} 

現在你明白爲什麼QML不是很靈活。 :)

+0

感謝您的幫助,瞭解如何在JavaScript中定義自定義事件處理程序。通過說「QML不是很靈活」,你的意思是比較在C++中使用Qt Widgets嗎?或者你在談論像FolderListModel這樣的模型的限制?在後一種情況下,在Qt/C++中定義自定義模型的麻煩較少?演示將非常感謝。 – treslumen

+0

我一直在想,而不是銷燬模型,有沒有辦法簡單地銷燬並重新創建視圖呢?從我的觀察來看,並不是'FolderListModel.showHidden'不能來回切換,但是'ShowView'更改爲'false'時,'TableView'無法正確更新其行(刪除隱藏條目)。有沒有辦法刷新視圖? – treslumen

+0

我不認爲Qt/C++優於QML。那麼使用QML就沒有意義。是的,我正在談論組件的侷限性。有時候除了解決問題外,沒有別的辦法。通過演示你的意思是工作示例?如果是這樣,您可以創建新項目,創建3個文件,並複製它們的正文。 –

0

解發現在活性TabView(窗格)當前Tab:聲明的SplitView一個屬性來存儲具有activeFocusTabView

A StatusBar已添加到演示此功能。

import QtQuick 2.4 
import QtQuick.Controls 1.4 
import QtQuick.Layouts 1.1 

ApplicationWindow { 
    visible: true 
    width: 1280 
    height: 700 

    toolBar: ToolBar { 
     RowLayout { 
      anchors.fill: parent 

      ToolButton { 
       onClicked: { // TODO toggle folderModel.showHidden property 
        // Demo: get the current tab of the active pane 
        var active_pane = splitView.activePane; 
        var cur_tab_idx = active_pane.currentIndex; 
        var cur_tab_item = active_pane.getTab(cur_tab_idx).item; 
        testLabel.text = cur_tab_item.folder_url; 
       } 
      } 
     } 
    } 

    SplitView { 
     id: splitView 

     property TabView activePane: tabView1 

     anchors.fill: parent 

     TabView { 
      id: tabView1 
      width: splitView.width/2 

      onActiveFocusChanged: { 
       if (activeFocus) { 
        splitView.activePane = tabView1; 
       } 
      } 

      Tab { 
       title: qsTr("tmp") 
       source: "dirview.qml" 
       onLoaded: { 
        item.folder_url = "file:///tmp"; 
       } 
      } 

      Tab { 
       title: qsTr("home") 
       source: "dirview.qml" 
       onLoaded: { 
        item.folder_url = "file:///home"; 
       } 
      } 
     } 

     TabView { 
      id: tabView2 

      onActiveFocusChanged: { 
       if (activeFocus) { 
        splitView.activePane = tabView2; 
       } 
      } 

      Tab { 
       title: qsTr("bin") 
       source: "dirview.qml" 
       onLoaded: { 
        item.folder_url = "file:///bin"; 
       } 
      } 
     } 
    } 
    statusBar: StatusBar { 
     RowLayout { 
      Label { 
       text: (splitView.activePane === tabView1) ? "Pane 1" : "Pane 2" 
      } 
      Label { 
       id: testLabel 
      } 
     } 
    } 
}