简体   繁体   English

PyQt5 更新/替换 QScrollArea 内的 QTableWidget

[英]PyQt5 update/replace a QTableWidget inside a QScrollArea

I have a problem with a python GUI based on Qt5.我对基于 Qt5 的 python GUI 有疑问。 I have an element to select a path and then a QScrollArea where a QTable is displayed with the files of the directory.我有一个元素到 select 一个路径,然后是一个 QScrollArea ,其中 QTable 与目录的文件一起显示。 This works fine when the directory is selected the first time, but when a new directory is selected the table is not updated, I get the following error: "QLayout: Attempting to add QLayout "" to QScrollArea "", which already has a layout" This works fine when the directory is selected the first time, but when a new directory is selected the table is not updated, I get the following error: "QLayout: Attempting to add QLayout "" to QScrollArea "", which already has a layout "

I understand so far that I have to delete the parent, but I do not find a solution (sorry I am new to Qt).到目前为止,我知道我必须删除父级,但我没有找到解决方案(对不起,我是 Qt 新手)。 Any help is appreciated.任何帮助表示赞赏。

Thanks, Alex谢谢,亚历克斯

Here is the working example:这是工作示例:

import sys
import tempfile
import time
import ntpath
import os
from os import listdir
from os.path import isfile, join
import platform
import subprocess
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QPushButton, QScrollArea, QVBoxLayout, QCheckBox, QInputDialog, QLineEdit, QComboBox, QMessageBox, QWidget, QDialog
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import QTableWidget,QTableWidgetItem, QLabel
from PyQt5.QtGui import QPixmap, QIcon


LastStateRole = QtCore.Qt.UserRole

class Ui_brows(object):
    def createFileTable(self, fileList):
        self.fileTable = QTableWidget()
        self.fileTable.setRowCount(len(fileList))
        self.fileTable.setColumnCount(4)
        self.fileTable.setHorizontalHeaderLabels(['Include', 'Target','Name', 'Path'])
        for l in range (len(fileList)):
            item = QtWidgets.QTableWidgetItem()
            item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            item.setCheckState(QtCore.Qt.Checked)
            item.setData(LastStateRole, item.checkState())
            self.fileTable.setItem(l,0,item)
            self.fileTable.setItem(l,1,QTableWidgetItem(""))
            nameString = ntpath.basename(fileList[l])
            self.fileTable.setItem(l,2,QTableWidgetItem(nameString))
            self.fileTable.setItem(l,3,QTableWidgetItem(fileList[l]))
        self.fileTable.setColumnWidth(0,40)
        self.fileTable.setColumnWidth(0,80)    
        self.layout = QVBoxLayout(self.scrollArea)
        self.layout.addWidget(self.fileTable)

    def _open_file_dialog(self):
        directory = str(QtWidgets.QFileDialog.getExistingDirectory())
        fileList = []
        for f in listdir(directory):
            fileList.append(f)
        self.createFileTable(fileList)

    def setupUi(self, brows):
        brows.setObjectName("MyApp")
        brows.resize(900, 600)
        
        #### line 1
        self.toolButtonOpenDialog = QtWidgets.QToolButton(brows)
        self.toolButtonOpenDialog.setGeometry(QtCore.QRect(310, 10, 35, 19))
        self.toolButtonOpenDialog.setObjectName("toolButtonOpenDialog")
        self.toolButtonOpenDialog.clicked.connect(self._open_file_dialog)

        self.importPath = QtWidgets.QLineEdit(brows)
        self.importPath.setEnabled(False)
        self.importPath.setGeometry(QtCore.QRect(110, 10, 191, 20))
        self.importPath.setObjectName("importPath")
        
        self.label1 = QtWidgets.QLabel(brows)
        self.label1.setText('Folder to scan')
        self.label1.setGeometry(QtCore.QRect(10,10,90,20))
        self.label1.setObjectName("Label1")
        
        self.label11 = QtWidgets.QLabel(brows)
        self.label11.setText('Scan Depth')
        self.label11.setGeometry(QtCore.QRect(370,10,90,20))
        self.label11.setObjectName("Label11")
        
        self.folderDepth = QComboBox(brows)
        self.folderDepth.addItems(['1','2','3','>3'])
        self.folderDepth.setGeometry(QtCore.QRect(450,8,50,25))
        self.folderDepth.setObjectName("FolderDepth")
        
        #### line 2
        self.label2 = QtWidgets.QLabel(brows)
        self.label2.setText('Local mount')
        self.label2.setGeometry(QtCore.QRect(10,50,90,20))
        self.label2.setObjectName("Label2")
        
        self.localMount = QtWidgets.QLineEdit(brows)
        self.localMount.setEnabled(True)
        self.localMount.setGeometry(QtCore.QRect(100, 50, 90, 20))
        self.localMount.setObjectName("localMount")
        
        self.label3 = QtWidgets.QLabel(brows)
        self.label3.setText('Remote mount')
        self.label3.setGeometry(QtCore.QRect(230,50,90,20))
        self.label3.setObjectName("Label3")
        
        self.remoteMount = QtWidgets.QLineEdit(brows)
        self.remoteMount.setEnabled(True)
        self.remoteMount.setGeometry(QtCore.QRect(330, 50, 80, 20))
        self.remoteMount.setObjectName("remoteMount")
        
        #### line 3
        self.scrollArea = QScrollArea(brows)
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setGeometry(QtCore.QRect(10, 100, 880, 400))

        self.retranslateUi(brows)
        QtCore.QMetaObject.connectSlotsByName(brows)

    def retranslateUi(self, brows):
        _translate = QtCore.QCoreApplication.translate
        brows.setWindowTitle(_translate("myApp", "MyApp"))
        self.toolButtonOpenDialog.setText(_translate("brows", "..."))

    
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    brows = QtWidgets.QDialog()
    ui = Ui_brows()
    ui.setupUi(brows)
    brows.show()

    sys.exit(app.exec_())

QTableWidget already has a scroll area inside, you don't need to create another one. QTableWidget 里面已经有了滚动区域,不需要再创建一个。 See code below.请参阅下面的代码。

In case you still want to place additional scroll area outside of the table.如果您仍想在表格之外放置额外的滚动区域。 You may check example how to use one correctly in structure:您可以查看示例如何在结构中正确使用一个:

Top_Level_Widget->Top_Level_Layout Top_Level_Widget->Top_Level_Layout
Second_Level_QScrollArea Second_Level_QScrollArea
Third_Level_Widget_For_QScrollArea->Third_Level_Layout_of_ScrollArea_Widget Third_Level_Widget_For_QScrollArea->Third_Level_Layout_of_ScrollArea_Widget
Fourth_Level_Contents_Inside. Fourth_Level_Contents_Inside。

https://github.com/baoboa/pyqt5/blob/master/examples/draganddrop/delayedencoding/delayedencoding.py https://github.com/baoboa/pyqt5/blob/master/examples/draganddrop/delayedencoding/delayedencoding.py

import sys
import tempfile
import time
import ntpath
import os
from os import listdir
from os.path import isfile, join
import platform
import subprocess
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QPushButton, QScrollArea, QVBoxLayout, QCheckBox, QInputDialog, QLineEdit, QComboBox, QMessageBox, QWidget, QDialog
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import QTableWidget,QTableWidgetItem, QLabel
from PyQt5.QtGui import QPixmap, QIcon


LastStateRole = QtCore.Qt.UserRole

class Ui_brows(object):
    def createFileTable(self, fileList):
        self.fileTable = QTableWidget()
        self.fileTable.setRowCount(len(fileList))
        self.fileTable.setColumnCount(4)
        self.fileTable.setHorizontalHeaderLabels(['Include', 'Target','Name', 'Path'])
        for l in range (len(fileList)):
            item = QtWidgets.QTableWidgetItem()
            item.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            item.setCheckState(QtCore.Qt.Checked)
            item.setData(LastStateRole, item.checkState())
            self.fileTable.setItem(l,0,item)
            self.fileTable.setItem(l,1,QTableWidgetItem(""))
            nameString = ntpath.basename(fileList[l])
            self.fileTable.setItem(l,2,QTableWidgetItem(nameString))
            self.fileTable.setItem(l,3,QTableWidgetItem(fileList[l]))
        self.fileTable.setColumnWidth(0,40)
        self.fileTable.setColumnWidth(0,80)
        if self.table_place_holder_layout.count():
            self.table_place_holder_layout.takeAt(0).widget().deleteLater()
        self.table_place_holder_layout.addWidget(self.fileTable)

    def _open_file_dialog(self):
        directory = str(QtWidgets.QFileDialog.getExistingDirectory())
        if not directory:
            return
        fileList = []
        for f in listdir(directory):
            fileList.append(f)
        self.createFileTable(fileList)

    def setupUi(self, brows):
        brows.setObjectName("MyApp")
        brows.resize(900, 600)

        #### line 1
        self.toolButtonOpenDialog = QtWidgets.QToolButton(brows)
        self.toolButtonOpenDialog.setGeometry(QtCore.QRect(310, 10, 35, 19))
        self.toolButtonOpenDialog.setObjectName("toolButtonOpenDialog")
        self.toolButtonOpenDialog.clicked.connect(self._open_file_dialog)

        self.importPath = QtWidgets.QLineEdit(brows)
        self.importPath.setEnabled(False)
        self.importPath.setGeometry(QtCore.QRect(110, 10, 191, 20))
        self.importPath.setObjectName("importPath")

        self.label1 = QtWidgets.QLabel(brows)
        self.label1.setText('Folder to scan')
        self.label1.setGeometry(QtCore.QRect(10,10,90,20))
        self.label1.setObjectName("Label1")

        self.label11 = QtWidgets.QLabel(brows)
        self.label11.setText('Scan Depth')
        self.label11.setGeometry(QtCore.QRect(370,10,90,20))
        self.label11.setObjectName("Label11")

        self.folderDepth = QComboBox(brows)
        self.folderDepth.addItems(['1','2','3','>3'])
        self.folderDepth.setGeometry(QtCore.QRect(450,8,50,25))
        self.folderDepth.setObjectName("FolderDepth")

        #### line 2
        self.label2 = QtWidgets.QLabel(brows)
        self.label2.setText('Local mount')
        self.label2.setGeometry(QtCore.QRect(10,50,90,20))
        self.label2.setObjectName("Label2")

        self.localMount = QtWidgets.QLineEdit(brows)
        self.localMount.setEnabled(True)
        self.localMount.setGeometry(QtCore.QRect(100, 50, 90, 20))
        self.localMount.setObjectName("localMount")

        self.label3 = QtWidgets.QLabel(brows)
        self.label3.setText('Remote mount')
        self.label3.setGeometry(QtCore.QRect(230,50,90,20))
        self.label3.setObjectName("Label3")

        self.remoteMount = QtWidgets.QLineEdit(brows)
        self.remoteMount.setEnabled(True)
        self.remoteMount.setGeometry(QtCore.QRect(330, 50, 80, 20))
        self.remoteMount.setObjectName("remoteMount")

        #### line 3
        self.table_place_holder = QtWidgets.QWidget(brows)
        self.table_place_holder_layout = QVBoxLayout(self.table_place_holder)
        # self.scrollArea = QScrollArea(brows)
        # self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        # self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        # self.scrollArea.setWidgetResizable(True)
        # self.scrollArea.setGeometry(QtCore.QRect(10, 100, 880, 400))
        self.table_place_holder.setGeometry(QtCore.QRect(10, 100, 880, 400))

        self.retranslateUi(brows)
        QtCore.QMetaObject.connectSlotsByName(brows)

    def retranslateUi(self, brows):
        _translate = QtCore.QCoreApplication.translate
        brows.setWindowTitle(_translate("myApp", "MyApp"))
        self.toolButtonOpenDialog.setText(_translate("brows", "..."))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    brows = QtWidgets.QDialog()
    ui = Ui_brows()
    ui.setupUi(brows)
    brows.show()

    sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM