【问题标题】:I want to get working QFileSystemModel in Tree view?我想在树视图中使用 QFileSystemModel 吗?
【发布时间】:2019-09-26 06:53:07
【问题描述】:

我正在制作一个我想要一个 FileTree 的程序(我已经有了这个,但没有 QfileSystemMoodle,这使得以后做事变得更加困难)。在这里,我必须能够在活动文件夹(我还不能选择,所以现在是硬编码的)中输入的文件名(这工作)录制一些声音,然后必须更新文件树。我更喜欢为此使用 QFileSystemModel,因为它使之后的编辑变得更容易。

所以我的问题是:带有 QFileSystemModel 的树视图,活动/选定路径作为记录位置并在记录或其他修改后更新。

这个我试过了,但我不能让它工作,我不需要过滤器:

import os, sys
import sounddevice as sd
from scipy.io.wavfile import write
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QTreeWidgetItem, QFileSystemModel
from pathlib import Path

qtcreator_file  = "mainwindow.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtcreator_file)

class MyWindow(QtWidgets.QMainWindow, QtWidgets.QFileSystemModel, Ui_MainWindow):

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self, parent=None)
        Ui_MainWindow.__init__(self)
        QtGui.QFileSystemModel.__init__(self, None)
        self.checks = {}
        self.FileStruckture
        self.setupUi(self)
        self.opnemen.clicked.connect(self.capture)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.CheckStateRole:
            return QtGui.QFileSystemModel.data(self, index, role)
        else:
            if index.column() == 0:
                return self.checkState(index)

    def flags(self, index):
        return QtGui.QFileSystemModel.flags(self, index) | QtCore.Qt.ItemIsUserCheckable

    def checkState(self, index):
        if index in self.checks:
            return self.checks[index]
        else:
            return QtCore.Qt.Checked

    def setData(self, index, value, role):
        if (role == QtCore.Qt.CheckStateRole and index.column() == 0):
            self.checks[index] = value
            self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index)
            return True 
        return QtGui.QFileSystemModel.setData(self, index, value, role)

    self.dirTreeView = QtWidgets.QTreeWidget(self.FileStruckture)
    self.dirModel = CheckableDirModel()
    self.dirTreeView.setModel(self.dirModel)

    def capture(self):

        fs = 44100  # Sample rate
        seconds = 6  # Duration of recording

        myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
        sd.wait()  # Wait until recording is finished
        locatie = "D:/DemoGIPhoofdmap/bedrijf 08"
        locatiepath = Path(locatie)
        file_name = "/" + (self.filename.text()) + ".wav"
        write_path = locatie + file_name
        write(write_path, fs, myrecording)  # Save as WAV file

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

这是最有效的,但它不适用于 QFileSystemMoodle,它不会更新,我无法从中获取活动路径:

import os, sys
import sounddevice as sd
from scipy.io.wavfile import write
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtWidgets import QTreeWidgetItem
from PyQt5.QtGui import QIcon
from pathlib import Path

qtcreator_file  = "mainwindow.ui" # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtcreator_file)

class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)
        self.FileStruckture
        self.file_tree("D:/DemoGIPhoofdmap", self.FileStruckture)
        self.opnemen.clicked.connect(self.capture)


    def file_tree(self, startpath, tree):
        startpath = Path(startpath)
        for element in os.listdir(startpath):
            path_info = startpath / element
            parent_itm = QTreeWidgetItem(tree, [os.path.basename(element)])
            if os.path.isdir(path_info):
                self.file_tree(path_info, parent_itm)
                parent_itm.setIcon(0, QIcon('assets/folder.ico'))
            else:
                parent_itm.setIcon(0, QIcon('assets/file.ico'))

    def capture(self):

        fs = 44100  # Sample rate
        seconds = 6  # Duration of recording

        myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
        sd.wait()  # Wait until recording is finished
        locatie = "D:/DemoGIPhoofdmap/bedrijf 08"
        locatiepath = Path(locatie)
        file_name = "/" + (self.filename.text()) + ".wav"
        write_path = locatie + file_name
        write(write_path, fs, myrecording)  # Save as WAV file

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MyWindow()
    window.show()
    sys.exit(app.exec_())

这是来自 QT Creator 的 XML 代码

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
    <x>0</x>
    <y>0</y>
    <width>827</width>
    <height>622</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="opnemen">
    <property name="geometry">
    <rect>
    <x>320</x>
    <y>60</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>Capture</string>
    </property>
</widget>
<widget class="QPushButton" name="importeer">
    <property name="geometry">
    <rect>
    <x>400</x>
    <y>60</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>Inport</string>
    </property>
</widget>
<widget class="QTreeWidget" name="FileStruckture">
    <property name="geometry">
    <rect>
    <x>10</x>
    <y>10</y>
    <width>301</width>
    <height>561</height>
    </rect>
    </property>
</widget>
<widget class="QLabel" name="label">
    <property name="geometry">
    <rect>
    <x>320</x>
    <y>10</y>
    <width>131</width>
    <height>16</height>
    </rect>
    </property>
    <property name="text">
    <string>File name for new item:</string>
    </property>
</widget>
<widget class="QLineEdit" name="filename">
    <property name="geometry">
    <rect>
    <x>320</x>
    <y>30</y>
    <width>151</width>
    <height>20</height>
    </rect>
    </property>
</widget>
<widget class="QPushButton" name="nieuwemap">
    <property name="geometry">
    <rect>
    <x>320</x>
    <y>90</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>New folder</string>
    </property>
</widget>
<widget class="QPushButton" name="verwijderen">
    <property name="geometry">
    <rect>
    <x>320</x>
    <y>120</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>Delete</string>
    </property>
</widget>
<widget class="QPushButton" name="hernoem">
    <property name="geometry">
    <rect>
    <x>400</x>
    <y>90</y>
    <width>75</width>
    <height>23</height>
    </rect>
    </property>
    <property name="text">
    <string>Rename</string>
    </property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
    <rect>
    <x>0</x>
    <y>0</y>
    <width>827</width>
    <height>21</height>
    </rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

【问题讨论】:

    标签: python pyqt pyqt5 qfilesystemmodel


    【解决方案1】:

    如果你想使用 QFileSystemModel,你必须使用 QTreeView,但是你的 .ui 没有实现它,所以修改你的 .ui。另一方面,sd.wait() 正在阻塞冻结 GUI,以避免此任务必须在另一个线程中执行。

    综合以上,解决办法是:

    *.ui

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="QMainWindow" name="MainWindow">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>615</width>
        <height>598</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>MainWindow</string>
      </property>
      <widget class="QWidget" name="centralwidget">
       <layout class="QHBoxLayout" name="horizontalLayout">
        <item>
         <widget class="QTreeView" name="filestruckture"/>
        </item>
        <item>
         <layout class="QGridLayout" name="gridLayout">
          <item row="1" column="0" colspan="2">
           <widget class="QLineEdit" name="filename"/>
          </item>
          <item row="3" column="0">
           <widget class="QPushButton" name="nieuwemap">
            <property name="text">
             <string>New folder</string>
            </property>
           </widget>
          </item>
          <item row="4" column="0">
           <widget class="QPushButton" name="verwijderen">
            <property name="text">
             <string>Delete</string>
            </property>
           </widget>
          </item>
          <item row="2" column="1">
           <widget class="QPushButton" name="importeer">
            <property name="text">
             <string>Inport</string>
            </property>
           </widget>
          </item>
          <item row="0" column="0" colspan="2">
           <widget class="QLabel" name="label">
            <property name="text">
             <string>File name for new item:</string>
            </property>
           </widget>
          </item>
          <item row="3" column="1">
           <widget class="QPushButton" name="hernoem">
            <property name="text">
             <string>Rename</string>
            </property>
           </widget>
          </item>
          <item row="2" column="0">
           <widget class="QPushButton" name="opnemen">
            <property name="text">
             <string>Capture</string>
            </property>
           </widget>
          </item>
          <item row="5" column="0">
           <spacer name="verticalSpacer">
            <property name="orientation">
             <enum>Qt::Vertical</enum>
            </property>
            <property name="sizeHint" stdset="0">
             <size>
              <width>20</width>
              <height>40</height>
             </size>
            </property>
           </spacer>
          </item>
         </layout>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>615</width>
         <height>30</height>
        </rect>
       </property>
      </widget>
      <widget class="QStatusBar" name="statusbar"/>
     </widget>
     <resources/>
     <connections/>
    </ui>
    

    *.py

    import os
    import sys
    from pathlib import Path
    
    from functools import partial
    
    import sounddevice as sd
    from scipy.io.wavfile import write
    
    from PyQt5 import QtCore, QtGui, QtWidgets, uic
    
    qtcreator_file = "mainwindow.ui"  # Enter file here.
    Ui_MainWindow, QtBaseClass = uic.loadUiType(qtcreator_file)
    
    
    class CaptureWorker(QtCore.QObject):
        started = QtCore.pyqtSignal()
        finished = QtCore.pyqtSignal()
    
        @QtCore.pyqtSlot(str)
        def save_to(self, path):
            self.started.emit()
            fs = 44100  # Sample rate
            seconds = 6  # Duration of recording
            myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
            sd.wait()
            write(path, fs, myrecording)
            self.finished.emit()
    
    
    class MyWindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None):
            super(MyWindow, self).__init__(parent)
            self.setupUi(self)
    
            self.root_path = "D:/DemoGIPhoofdmap/bedrijf 08"
    
            model = QtWidgets.QFileSystemModel(self)
            self.filestruckture.setModel(model)
            model.setRootPath(self.root_path)
            self.filestruckture.setRootIndex(model.index(model.rootPath()))
    
            thread = QtCore.QThread(self)
            thread.start()
    
            self.capture_worker = CaptureWorker()
            self.capture_worker.moveToThread(thread)
    
            self.capture_worker.started.connect(partial(self.opnemen.setEnabled, False))
            self.capture_worker.finished.connect(partial(self.opnemen.setEnabled, True))
    
            self.opnemen.clicked.connect(self.capture)
    
        def capture(self):
            name = self.filename.text()
            if name:
                locatie = self.root_path
                locatiepath = Path(locatie)
                file_name = os.path.join(locatiepath, name + ".wav")
                wrapper = partial(self.capture_worker.save_to, file_name)
                QtCore.QTimer.singleShot(0, wrapper)
            else:
                print("set the filename")
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        window = MyWindow()
        window.show()
        sys.exit(app.exec_())
    

    【讨论】:

    • 非常感谢您,这是我得到的最佳答案。只有一个问题:我不想保存在根目录中,而是保存在 clicked / highlithed 目录中。因为self.root_path = "D: / DemoGIP main folder /" 是目录,并且在该文件夹中有子文件夹。
    猜你喜欢
    • 2019-04-22
    • 2018-12-22
    • 1970-01-01
    • 2013-03-15
    • 2022-08-14
    • 2018-04-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    相关资源
    最近更新 更多