2015-11-06 69 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 
      } 
     } 
    } 
}