PyQt5 QTreeView show parent directory [duplicate] - python

In my application I have a QTreeview. I have a folder named "test" that contains many subfolders. The treeview only shows the subfolders not the test forlder it self!
def create_treeview(self):
self.treeView = QTreeView()
self.treeView.setMinimumSize(QSize(250, 0))
self.treeView.setMaximumSize(QSize(250, 16777215))
self.treeView.setObjectName("treeView")
self.dirModel = QFileSystemModel()
self.dirModel.setRootPath(QDir.rootPath())
self.dirModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)
self.treeView.setModel(self.dirModel)
self.treeView.setRootIndex(self.dirModel.index("/home/data/test"))
self.treeView.setHeaderHidden(True)
self.treeView.clicked.connect(self.tree_click)
return self.treeView

The rootIndex of the QTreeView is hidden so it is not shown. One possible solution is to pass the parent of the path and use a QSortFilterProxyModel to hide the other directories and files.
import os
from PyQt5.QtCore import pyqtSlot, QDir, QModelIndex, QSize, QSortFilterProxyModel
from PyQt5.QtWidgets import QApplication, QFileSystemModel, QMainWindow, QTreeView
class ProxyModel(QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
self._root_path = ""
def filterAcceptsRow(self, source_row, source_parent):
source_model = self.sourceModel()
if self._root_path and isinstance(source_model, QFileSystemModel):
root_index = source_model.index(self._root_path).parent()
if root_index == source_parent:
index = source_model.index(source_row, 0, source_parent)
return index.data(QFileSystemModel.FilePathRole) == self._root_path
return True
#property
def root_path(self):
return self._root_path
#root_path.setter
def root_path(self, p):
self._root_path = p
self.invalidateFilter()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.create_treeview()
self.setCentralWidget(self.treeView)
def create_treeview(self):
path = "/home/data/test"
self.treeView = QTreeView()
self.treeView.setMinimumSize(QSize(250, 0))
self.treeView.setMaximumSize(QSize(250, 16777215))
self.treeView.setObjectName("treeView")
self.dirModel = QFileSystemModel()
self.dirModel.setRootPath(QDir.rootPath())
self.dirModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)
root_index = self.dirModel.index(path).parent()
self.proxy = ProxyModel(self.dirModel)
self.proxy.setSourceModel(self.dirModel)
self.proxy.root_path = path
self.treeView.setModel(self.proxy)
proxy_root_index = self.proxy.mapFromSource(root_index)
self.treeView.setRootIndex(proxy_root_index)
self.treeView.setHeaderHidden(True)
self.treeView.clicked.connect(self.tree_click)
#pyqtSlot(QModelIndex)
def tree_click(self, index):
ix = self.proxy.mapToSource(index)
print(
ix.data(QFileSystemModel.FilePathRole),
ix.data(QFileSystemModel.FileNameRole),
)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Related

How to draw a pushbutton to a tableview cell? [duplicate]

I am trying to add 'Share' and 'Delete' buttons to each row of the table using "table View" class of PySide.
But I am unable to do since I don't have much knowledge of PySide. Can any one please guide me how to add buttons to table view.
Expected Output:
My code:
import sys
import os
import csv
from PySide import QtGui, QtCore
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.dirPath = "/home/cioc/Documents/GPR/GRP"
self.filePath = ""
self.fileName =""
self.lay1 = QtGui.QVBoxLayout()
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setBackgroundRole(QtGui.QPalette.Light)
self.scrollArea.setWidgetResizable(True)
self.mainLayout =QtGui. QGridLayout()
self.mainLayout.addWidget(self.scrollArea,0,1)
self.setCentralWidget(QtGui.QWidget(self))
self.centralWidget().setLayout(self.mainLayout)
self.setGeometry(100,100,800,500)
self.w = QtGui.QWidget()
self.lay = QtGui.QVBoxLayout()
self.model =QtGui. QStandardItemModel(self)
self.tableView = QtGui.QTableView(self)
self.tableView.setModel(self.model)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.clicked[QtCore.QModelIndex].connect(self.onClick)
self.tableView.verticalHeader().setVisible(False)
self.appendRowItems(self.dirPath)
self.lay.addWidget(self.tableView)
self.w.setLayout(self.lay)
self.scrollArea.setWidget(self.w)
# self.btn_sell = QtGui.QPushButton('Delete')
# self.btn_sell.clicked.connect(self.delete)
def appendRowItems(self, dir):
for root, dirs, files in os.walk(dir):
if root == dir:
for file in files:
self.model.appendRow(QtGui.QStandardItem(file))
# def delete(self,index):
# self.model.clear()
def onClick(self, ind):
self.filePath = self.dirPath +"/"+ self.model.item(ind.row(), ind.column()).text()
print(self.filePath)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
eg = Example()
eg.show()
app.exec_()
One option is to implement a delegate:
import os
import sys
from PySide import QtGui, QtCore
class ViewWidget(QtGui.QWidget):
def __init__(self, x, index, parent=None):
super(ViewWidget, self).__init__(parent)
self.p_index = QtCore.QPersistentModelIndex(index)
self.content_button = QtGui.QWidget(self)
lay = QtGui.QHBoxLayout(self.content_button)
lay.setContentsMargins(0, 0, 0,0)
self.share_btn = QtGui.QPushButton("share")
self.share_btn.clicked.connect(self.share_clicked)
self.delete_btn = QtGui.QPushButton("delete")
self.delete_btn.clicked.connect(self.delete_clicked)
lay.addWidget(self.share_btn)
lay.addWidget(self.delete_btn)
self.content_button.move(x, 0)
#QtCore.Slot()
def delete_clicked(self):
model = self.p_index.model()
model.removeRow(self.p_index.row())
#QtCore.Slot()
def share_clicked(self):
text = self.p_index.data()
full_path = self.p_index.data(QtCore.Qt.UserRole+1)
print(text, full_path)
class ButtonsDelegate(QtGui.QStyledItemDelegate):
def paint(self, painter, option, index):
self.parent().openPersistentEditor(index)
super(ButtonsDelegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
return ViewWidget(300, index, parent)
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
dirPath = "/home/cioc/Documents/GPR/GRP"
self.setCentralWidget(QtGui.QWidget())
layout = QtGui. QGridLayout(self.centralWidget())
self.model =QtGui.QStandardItemModel(self)
self.tableView = QtGui.QTableView()
self.tableView.setModel(self.model)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.clicked.connect(self.onClick)
self.tableView.verticalHeader().hide()
self.appendRowItems(dirPath)
delegate = ButtonsDelegate(self.tableView)
self.tableView.setItemDelegate(delegate)
layout.addWidget(self.tableView)
self.resize(800,500)
def appendRowItems(self, dir_path):
for root, dirs, files in os.walk(dir_path):
if root == dir_path:
for file in files:
item = QtGui.QStandardItem(file)
item.setData(os.path.join(root, file))
self.model.appendRow(item)
#QtCore.Slot(QtCore.QModelIndex)
def onClick(self, ix):
it = self.model.itemFromIndex(ix)
print(it.data())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
eg = Example()
eg.show()
sys.exit(app.exec_())
Or setIndexWidget():
import os
import sys
from PySide import QtGui, QtCore
class ViewWidget(QtGui.QWidget):
def __init__(self, x, index, parent=None):
super(ViewWidget, self).__init__(parent)
self.p_index = QtCore.QPersistentModelIndex(index)
self.content_button = QtGui.QWidget(self)
lay = QtGui.QHBoxLayout(self.content_button)
lay.setContentsMargins(0, 0, 0,0)
self.share_btn = QtGui.QPushButton("share")
self.share_btn.clicked.connect(self.share_clicked)
self.delete_btn = QtGui.QPushButton("delete")
self.delete_btn.clicked.connect(self.delete_clicked)
lay.addWidget(self.share_btn)
lay.addWidget(self.delete_btn)
self.content_button.move(x, 0)
#QtCore.Slot()
def delete_clicked(self):
model = self.p_index.model()
model.removeRow(self.p_index.row())
#QtCore.Slot()
def share_clicked(self):
text = self.p_index.data()
full_path = self.p_index.data(QtCore.Qt.UserRole+1)
print(text, full_path)
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
dirPath = "/home/cioc/Documents/GPR/GRP"
self.setCentralWidget(QtGui.QWidget())
layout = QtGui. QGridLayout(self.centralWidget())
self.model =QtGui.QStandardItemModel(self)
self.tableView = QtGui.QTableView()
self.tableView.setModel(self.model)
self.tableView.horizontalHeader().setStretchLastSection(True)
self.tableView.clicked.connect(self.onClick)
self.tableView.verticalHeader().hide()
self.appendRowItems(dirPath)
layout.addWidget(self.tableView)
self.resize(800,500)
def appendRowItems(self, dir_path):
for root, dirs, files in os.walk(dir_path):
if root == dir_path:
for file in files:
item = QtGui.QStandardItem(file)
item.setData(os.path.join(root, file))
self.model.appendRow(item)
ix = self.model.indexFromItem(item)
self.tableView.setIndexWidget(ix, ViewWidget(300, ix))
#QtCore.Slot(QtCore.QModelIndex)
def onClick(self, ix):
it = self.model.itemFromIndex(ix)
print(it.data())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
eg = Example()
eg.show()
sys.exit(app.exec_())

How to print the file path when the mouse hovers over an item in this QTreeView with QFileSystemModel

I'm making a custom QTreeView with QFileSystem model, and I have a MouseMoveEvent set up to print the path of the item that is hovered over.
I'm way down the rabbit hole and doing all kinds of weird things to make this work.
Here is the latest minimal reproducible code:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.resize(500, 300)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.myList = CustomTreeWidget()
self.myList.model.setRootPath("/Volumes/Home/User/Desktop/testsrc")
self.myList.setObjectName("/Volumes/Home/User/Desktop/testsrc")
self.layout.addWidget(self.myList)
class CustomTreeWidget(QTreeView):
def __init__(self):
super().__init__()
self.model = QFileSystemModel()
self.model.setFilter(QDir.NoDotAndDotDot | QDir.Files)
self.setModel(self.model)
self.setAlternatingRowColors(True)
self.setDragDropMode(QAbstractItemView.DragDrop)
self.setIndentation(0)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setDragEnabled(True)
self.setAcceptDrops(True)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.setMouseTracking(True)
self.model.directoryLoaded.connect(self._runwhenloaded)
def _runwhenloaded(self):
self.setRootIndex(self.model.index(self.objectName()))
self.model.setRootPath(self.objectName())
def mouseMoveEvent(self, event):
prev = ""
if self.selectedIndexes():
prev = self.selectedIndexes()[0]
x = event.x()
y = event.y()
self.setSelection(QRect(x, y, 1, 1), QItemSelectionModel.ClearAndSelect)
self.setCurrentIndex(self.selectedIndexes()[0])
print(self.model.filePath(self.currentIndex()))
if prev:
self.setCurrentIndex(prev)
# pos = QCursor.pos()
# indexat = self.indexAt(pos).row() # why -1?
# print(indexat) # why -1?
# print(self.indexAt(pos).row())
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Obviously this example is not proper at all, as it destroys multiple selections and scrolls to the previously selected item whenever the mouse moves, and just a hack in general.
I've gone through many iterations and read everything I could put my hands on but I can't figure it out.
The closest answer seems to be HERE, but it's in C and I don't understand it.
So the question is: How to print the file path when the mouse hovers over an item in this QTreeView?
A possible solution is to create an event filter that tracks the hover events and, according to that information, emits a signal that has the QModelIndex:
import sys
from PyQt5.QtCore import (
pyqtSignal,
pyqtSlot,
Qt,
QDir,
QEvent,
QModelIndex,
QObject,
QPersistentModelIndex,
QStandardPaths,
)
from PyQt5.QtWidgets import (
QAbstractItemView,
QApplication,
QFileSystemModel,
QMainWindow,
QTreeView,
)
from PyQt5 import sip
class HoverViewHelper(QObject):
hovered = pyqtSignal(QModelIndex)
def __init__(self, view):
super().__init__(view)
self._current_index = QPersistentModelIndex()
if not isinstance(view, QAbstractItemView):
raise TypeError(f"The {view} must be of type QAbstractItemView")
self._view = view
self.view.viewport().setAttribute(Qt.WA_Hover)
self.view.viewport().installEventFilter(self)
#property
def view(self):
return self._view
def eventFilter(self, obj, event):
if sip.isdeleted(self.view):
return True
if self.view.viewport() is obj:
if event.type() in (QEvent.HoverMove, QEvent.HoverEnter):
p = event.pos()
index = self.view.indexAt(p)
self._update_index(index)
elif event.type() == QEvent.HoverLeave:
if self._current_index.isValid():
self._update_index(QModelIndex())
return super().eventFilter(obj, event)
def _update_index(self, index):
pindex = QPersistentModelIndex(index)
if pindex != self._current_index:
self._current_index = pindex
self.hovered.emit(QModelIndex(self._current_index))
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.model = QFileSystemModel()
self.model.setRootPath(QDir.rootPath())
self.view = QTreeView()
self.view.setModel(self.model)
path = QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation)
self.view.setRootIndex(self.model.index(path))
self.setCentralWidget(self.view)
helper = HoverViewHelper(self.view)
helper.hovered.connect(self.handle_hovered)
#pyqtSlot(QModelIndex)
def handle_hovered(self, index):
if not index.isValid():
return
path = self.model.filePath(index)
print(f"path: {path}")
def main():
app = QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
app.exec_()
if __name__ == "__main__":
main()

How to display folder content on a QTreeView with also the visible folder in PyQt5? [duplicate]

In my application I have a QTreeview. I have a folder named "test" that contains many subfolders. The treeview only shows the subfolders not the test forlder it self!
def create_treeview(self):
self.treeView = QTreeView()
self.treeView.setMinimumSize(QSize(250, 0))
self.treeView.setMaximumSize(QSize(250, 16777215))
self.treeView.setObjectName("treeView")
self.dirModel = QFileSystemModel()
self.dirModel.setRootPath(QDir.rootPath())
self.dirModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)
self.treeView.setModel(self.dirModel)
self.treeView.setRootIndex(self.dirModel.index("/home/data/test"))
self.treeView.setHeaderHidden(True)
self.treeView.clicked.connect(self.tree_click)
return self.treeView
The rootIndex of the QTreeView is hidden so it is not shown. One possible solution is to pass the parent of the path and use a QSortFilterProxyModel to hide the other directories and files.
import os
from PyQt5.QtCore import pyqtSlot, QDir, QModelIndex, QSize, QSortFilterProxyModel
from PyQt5.QtWidgets import QApplication, QFileSystemModel, QMainWindow, QTreeView
class ProxyModel(QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
self._root_path = ""
def filterAcceptsRow(self, source_row, source_parent):
source_model = self.sourceModel()
if self._root_path and isinstance(source_model, QFileSystemModel):
root_index = source_model.index(self._root_path).parent()
if root_index == source_parent:
index = source_model.index(source_row, 0, source_parent)
return index.data(QFileSystemModel.FilePathRole) == self._root_path
return True
#property
def root_path(self):
return self._root_path
#root_path.setter
def root_path(self, p):
self._root_path = p
self.invalidateFilter()
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.create_treeview()
self.setCentralWidget(self.treeView)
def create_treeview(self):
path = "/home/data/test"
self.treeView = QTreeView()
self.treeView.setMinimumSize(QSize(250, 0))
self.treeView.setMaximumSize(QSize(250, 16777215))
self.treeView.setObjectName("treeView")
self.dirModel = QFileSystemModel()
self.dirModel.setRootPath(QDir.rootPath())
self.dirModel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)
root_index = self.dirModel.index(path).parent()
self.proxy = ProxyModel(self.dirModel)
self.proxy.setSourceModel(self.dirModel)
self.proxy.root_path = path
self.treeView.setModel(self.proxy)
proxy_root_index = self.proxy.mapFromSource(root_index)
self.treeView.setRootIndex(proxy_root_index)
self.treeView.setHeaderHidden(True)
self.treeView.clicked.connect(self.tree_click)
#pyqtSlot(QModelIndex)
def tree_click(self, index):
ix = self.proxy.mapToSource(index)
print(
ix.data(QFileSystemModel.FilePathRole),
ix.data(QFileSystemModel.FileNameRole),
)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

PyQt5 draggable icons from a listview to another

I struggle to drag and drop icons from a listview (ViewMode set to IconMode) to another. It's similar to what I've found in the docs.
Scenario: A user drags the QIcon 1 from ListView 1 and drops it to ListView 2. ListView 2 should add QIcon 1 to its model. Moreover I want to do some background work when a specific QIcon is added to ListView 2. How do I know that QIcon 1 was dropped to ListView 2 and not QIcon 2?
mainwindow (sets up the layout, loads the images into listview 1):
class Ui_MainWindow(object):
...
def loadImages(self):
model = QStandardItemModel()
images = Path("images").glob("*.*")
for image in images:
item = QStandardItem()
item.setIcon(QIcon(str(image)))
model.appendRow(item)
self.listView1.setModel(model)
listview 1:
class ListView1(QListView):
def __init__(self):
super().__init__()
self.setAcceptDrops(False)
self.setViewMode(QtWidgets.QListView.IconMode)
self.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.setIconSize(QSize(50, 50))
self.setResizeMode(QtWidgets.QListView.Adjust)
self.setDragDropMode(QAbstractItemView.DragOnly)
listview 2:
class ListView2(QListView):
def __init__(self):
super().__init__()
self.setViewMode(QtWidgets.QListView.IconMode)
self.setDragDropMode(QAbstractItemView.DropOnly)
self.setIconSize(QSize(50, 50))
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
event.accept()
def dragMoveEvent(self, event):
event.accept()
def dropEvent(self, event):
event.accept()
event.setDropAction(QtCore.Qt.MoveAction)
event.acceptProposedAction()
How can I drag and drop an icon from listview 1 to listview 2 and access its properties?
It is not necessary to overwrite dragEnterEvent, dragMoveEvent or dropEvent since those implementations already exist and work correctly, the example you point out is for other types of widgets that do not have those events implemented.
from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets
class LListView(QtWidgets.QListView):
def __init__(self, parent=None):
super(LListView, self).__init__(parent)
self.model = QtGui.QStandardItemModel(self)
self.setModel(self.model)
self.setAcceptDrops(False)
self.setViewMode(QtWidgets.QListView.IconMode)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setIconSize(QtCore.QSize(50, 50))
self.setResizeMode(QtWidgets.QListView.Adjust)
self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)
class RListView(QtWidgets.QListView):
def __init__(self, parent=None):
super(RListView, self).__init__(parent)
self.model = QtGui.QStandardItemModel(self)
self.setModel(self.model)
self.setAcceptDrops(True)
self.setViewMode(QtWidgets.QListView.IconMode)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setIconSize(QtCore.QSize(50, 50))
self.setResizeMode(QtWidgets.QListView.Adjust)
self.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.l_view = LListView()
self.r_view = RListView()
self.setCentralWidget(central_widget)
lay = QtWidgets.QHBoxLayout(central_widget)
lay.addWidget(self.l_view)
lay.addWidget(self.r_view)
self.loadImages()
def loadImages(self):
images = Path("images").glob("*.*")
for image in images:
item = QtGui.QStandardItem()
item.setIcon(QtGui.QIcon(str(image)))
self.l_view.model.appendRow(item)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Update:
If you want to add an identifier this can be done through a role that you pass when creating the item, and then in the dropEvent() get all the roles, then get the role you want and through it the identifier:
from pathlib import Path
from PyQt5 import QtCore, QtGui, QtWidgets
class LListView(QtWidgets.QListView):
def __init__(self, parent=None):
super(LListView, self).__init__(parent)
self.m_model = QtGui.QStandardItemModel(self)
self.setModel(self.m_model)
self.setAcceptDrops(False)
self.setViewMode(QtWidgets.QListView.IconMode)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setIconSize(QtCore.QSize(50, 50))
self.setResizeMode(QtWidgets.QListView.Adjust)
self.setDragDropMode(QtWidgets.QAbstractItemView.DragOnly)
class RListView(QtWidgets.QListView):
def __init__(self, parent=None):
super(RListView, self).__init__(parent)
self.m_model = QtGui.QStandardItemModel(self)
self.setModel(self.m_model)
self.setAcceptDrops(True)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.setIconSize(QtCore.QSize(50, 50))
self.setResizeMode(QtWidgets.QListView.Adjust)
self.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
def dropEvent(self, event):
last_row_count = self.model().rowCount()
super(RListView, self).dropEvent(event)
# check if an item is added
if self.model().rowCount() > last_row_count:
md = event.mimeData()
fmt = "application/x-qabstractitemmodeldatalist"
if md.hasFormat(fmt):
encoded = md.data(fmt)
stream = QtCore.QDataStream(encoded, QtCore.QIODevice.ReadOnly)
datas = []
item = {}
while not stream.atEnd():
row = stream.readInt32()
column = stream.readInt32()
map_items = stream.readInt32()
for i in range(map_items):
key = stream.readInt32()
value = QtCore.QVariant()
stream >> value
item[QtCore.Qt.ItemDataRole(key)] = value
datas.append(item)
for data in datas:
identifier = data[QtCore.Qt.UserRole+1].value()
print("identifier: ", identifier)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.l_view = LListView()
self.r_view = RListView()
self.setCentralWidget(central_widget)
lay = QtWidgets.QHBoxLayout(central_widget)
lay.addWidget(self.l_view)
lay.addWidget(self.r_view)
self.loadImages()
def loadImages(self):
images = Path("images").glob("*.*")
for i, image in enumerate(images):
item = QtGui.QStandardItem()
identifier = "img_{:06d}".format(i+1)
item.setData(identifier, QtCore.Qt.UserRole+1)
item.setIcon(QtGui.QIcon(str(image)))
self.l_view.m_model.appendRow(item)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

how to add checkbox in each row of QTableView in PYQT

I have a simple .xlsx file and I load its content to my qtableview. My code likes this:
import xlrd
from PyQt5 import QtCore, QtGui, QtWidgets, uic
form_class = uic.loadUiType("SearchView.ui")[0] # Load the UI
app = None
myWindow = None
dic_messages = dict()
class MyWindowClass(QtWidgets.QMainWindow, form_class):
def __init__(self, fileName, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.gui = form_class
self.fileName = fileName
self.model = QtGui.QStandardItemModel(self)
self.tableView.setModel(self.model)
self.fn_load_messages()
def fn_load_messages(self):
workbook = xlrd.open_workbook('sample.xlsx')
worksheet = workbook.sheet_by_name('sample_sheet')
for i in range(0, worksheet.nrows):
dic_messages[i + 1] = (worksheet.cell(i, 0).value, worksheet.cell(i, 1).value, worksheet.cell(i, 2).value, worksheet.cell(i, 3).value, worksheet.cell(i, 4).value)
i += 1
rowPosition = self.tbl_messages.rowCount()
self.tbl_messages.insertRow(rowPosition)
return
def main():
global app, myWindow
app = QtWidgets.QApplication(sys.argv)
myWindow = MyWindowClass('sample.xlsx')
myWindow.show()
app.exec_()
if __name__ == '__main__':
main()
i want to add a checkbox column in each row and then i want to check or unchecked each row i want. i added below part to my code but the checkboxes are not active:
self.tableView.setItemDelegateForColumn(0 , CheckBoxDelegate(self))
class CheckBoxDelegate(QtWidgets.QStyledItemDelegate):
def paint(self, painter, option, index):
check_box_style_option = QtWidgets.QStyleOptionButton()
check_box_style_option.rect = self.getCheckBoxRect(option)
check_box_style_option.state = QtWidgets.QStyle.State_Enabled
QtWidgets.QApplication.style().drawControl(QtWidgets.QStyle.CE_CheckBox,
check_box_style_option, painter)
def getCheckBoxRect(self, option):
check_box_style_option = QtWidgets.QStyleOptionButton()
check_box_rect = QtWidgets.QApplication.style().subElementRect(QtWidgets.QStyle.SE_CheckBoxIndicator, check_box_style_option, None)
check_box_point = QtCore.QPoint (option.rect.x() +
option.rect.width() / 2 -
check_box_rect.width() / 2,
option.rect.y() +
option.rect.height() / 2 -
check_box_rect.height() / 2)
return QtCore.QRect(check_box_point, check_box_rect.size())
how can I do this?
Thanks.
You don't set it in the view but in the items and model. Like this:
#!/usr/bin/env python
from PyQt5 import QtWidgets, QtGui
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.tableModel = QtGui.QStandardItemModel(self)
self.tableModel.itemChanged.connect(self.itemChanged)
item = QtGui.QStandardItem("Click me")
item.setCheckable(True)
self.tableModel.appendRow(item)
self.mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(self.mainLayout)
self.tableView = QtWidgets.QTableView()
self.tableView.setModel(self.tableModel)
self.mainLayout.addWidget(self.tableView)
def itemChanged(self, item):
print("Item {!r} checkState: {}".format(item.text(), item.checkState()))
def main():
app = QtWidgets.QApplication([])
win = MyWidget()
win.show()
win.raise_()
app.exec_()
if __name__ == "__main__":
main()

Categories