PyQt5 update/replace QScrollArea 内的 QTableWidget
PyQt5 update/replace a QTableWidget inside a QScrollArea
我对基于 Qt5 的 python GUI 有疑问。
我有一个元素 select 一个路径,然后是一个 QScrollArea,其中 QTable 与目录的文件一起显示。当目录第一次被 selected 时,这工作正常,但是当新目录被 selected 时,table 没有更新,我收到以下错误:
“QLayout:正在尝试将 QLayout“”添加到已经有布局的 QScrollArea“”
到目前为止我明白我必须删除父级,但我没有找到解决方案(抱歉我是 Qt 的新手)。
感谢任何帮助。
谢谢,亚历克斯
这是工作示例:
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 内部已经有一个滚动区域,您不需要再创建一个。请参阅下面的代码。
以防您仍想在 table 之外放置额外的滚动区域。您可以检查示例如何在结构中正确使用一个:
Top_Level_Widget->Top_Level_Layout
Second_Level_QScrollArea
Third_Level_Widget_For_QScrollArea->Third_Level_Layout_of_ScrollArea_Widget
Fourth_Level_Contents_Inside.
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_())
我对基于 Qt5 的 python GUI 有疑问。 我有一个元素 select 一个路径,然后是一个 QScrollArea,其中 QTable 与目录的文件一起显示。当目录第一次被 selected 时,这工作正常,但是当新目录被 selected 时,table 没有更新,我收到以下错误: “QLayout:正在尝试将 QLayout“”添加到已经有布局的 QScrollArea“”
到目前为止我明白我必须删除父级,但我没有找到解决方案(抱歉我是 Qt 的新手)。 感谢任何帮助。
谢谢,亚历克斯
这是工作示例:
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 内部已经有一个滚动区域,您不需要再创建一个。请参阅下面的代码。
以防您仍想在 table 之外放置额外的滚动区域。您可以检查示例如何在结构中正确使用一个:
Top_Level_Widget->Top_Level_Layout
Second_Level_QScrollArea
Third_Level_Widget_For_QScrollArea->Third_Level_Layout_of_ScrollArea_Widget
Fourth_Level_Contents_Inside.
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_())