PyQt5: QListWidget
Torna all’indice degli appunti
Il ListWidget permette di visualizzare una lista di elementi.
Questi elementi possono essere semplici stringhe di testo o oggetti QListWidgetItem, che permettono ad esempio di avere associata un’icona.
I metodi principali sono:
addItem(item):
aggiunge l’elemento al listwidget. Questo elemento può essere anche un QListWidgetItem!
>>> from PyQt5.QtWidgets import (QMainWindow, QApplication, QGridLayout, QWidget, ... QListWidget) >>> from PyQt5.QtWidgets import QListWidgetItem >>> from PyQt5.QtGui import QIcon >>> app = QApplication([]) >>> lw = QListWidget() >>> lw.addItem("Simple string 1") >>> item = QListWidgetItem(QIcon("Italy.png"), "Italy") >>> lw.addItem(item) >>> lw.count() 2
insertItem(row, item):
aggiunge l’elemento alla riga specificata row.
>>> lw.insertItem(1, "Simple string 2") >>> for index in range(lw.count()): ... print("[%s]" % index, lw.item(index).text()) ... [0] Simple string 1 [1] Simple string 2 [2] Italy
count:
conta gli elementi del list-widget
current Item:
per settare il current item, si utilizza il metodo setCurrentItem(item) dove item è l’elemento
sul quale vogliamo spostare il focus.
Per sapere quale è attualmente il current item, si utilizza il metodo currentItem:
>>> item <PyQt5.QtWidgets.QListWidgetItem object at 0x0398D260> >>> lw.setCurrentItem(item) >>> lw.currentItem() <PyQt5.QtWidgets.QListWidgetItem object at 0x0398D260>
current Row:
Stessi concetti del metodo precedente, ma si sposta il focus sull’elemento desiderato, tramite row.
Il metodo è appunto setCurrentRow(row). Per ottenere invece la current row, si utilizza il metodo currentRow:
>>> lw.currentRow() 2 >>> lw.setCurrentRow(1) >>> lw.currentRow() 1
Sorting:
E’ possibile impostare l’ordinamento degli elementi tramite il metodo sortItems(order).
Il parametro order può avere i seguenti due valori:
Qt.AscendingOrder: ordine ascendente;
Qt.DescendingOrder: ordine discendente;
>>> from PyQt5.QtCore import Qt >>> for index in range(lw.count()): ... print("[%s]" % index, lw.item(index).text()) ... [0] Simple string 1 [1] Simple string 2 [2] Italy >>> lw.sortItems(Qt.DescendingOrder) >>> for index in range(lw.count()): ... print("[%s]" % index, lw.item(index).text()) ... [0] Simple string 2 [1] Simple string 1 [2] Italy
L’ordinamento degli elementi del list-widget può essere attivato/disattivato con il metodo setSortingEnabled(bool)
e per conoscere lo stato di questo flag, si utilizza il metodo isSortingEnabled(bool).
remove item:
Per Rimuovere l’item dalla list-widget si usa il metodo removeItemWidget(item). Questo metodo rimuove l’item dal list-widget, ma non lo cancella di fatto. Per rimuoverlo definitivamente bisogna usare takeItem(row) che ritorna l’elemento eliminato.
>>> item_to_remove = lw.item(2) >>> lw.removeItemWidget(item_to_remove) >>> for index in range(lw.count()): ... print("[%s]" % index, lw.item(index).text()) ... [0] Simple string 2 [1] Simple string 1 [2] Italy >>> lw.takeItem(2) <PyQt5.QtWidgets.QListWidgetItem object at 0x0398D260> >>> for index in range(lw.count()): ... print("[%s]" % index, lw.item(index).text()) ... [0] Simple string 2 [1] Simple string 1
SEGNALI:
i segnali del list-widget sono i seguenti:
currentItemChanged: emesso quando cambia il current item;
currentRowChanged(int): emesso quando cambia la current row;
currentTextChanged: currentText è il text-data del current item, di conseguenza questo segnale viene emesso
ogni qualvolta cambia il current item;
itemActivated: segnale emesso quando un item viene attivato tramite doppio-click o premendo
itemChanged: segnale emesso quando l’item cambia i propri dati, più avanti faremo un accenno all’editing dell’item;
itemClicked: segnale emesso al click sull’item;
itemDoubleClicked: segnale emesso al doppio-click su un item;
itemEntered: segnale emesso quando il mouse passa sull’item, è necessario attivare il mouseTracking
per il list-widget con il metodo setMouseTracking;
itemPressed: segnale emesso quando sull’item viene premuto un botton del mouse;
itemSelectionChanged: segnale emesso quando cambia la selezione;
Ecco un esempio con tutti i segnali; decommentare il segnale da monitorare:
import sys from PyQt5.QtWidgets import (QMainWindow, QApplication, QVBoxLayout, QWidget, QListWidget, QListWidgetItem, QPushButton, QLabel) from PyQt5.QtGui import QIcon from PyQt5.QtCore import Qt class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle("QListWidget Example") self.central_widget = FrameWidget(self) self.setCentralWidget(self.central_widget) self.resize(200, 200) class FrameWidget(QWidget): def __init__(self, parent=None): super(FrameWidget, self).__init__(parent) layout = QVBoxLayout() self.setLayout(layout) self.text_label = QLabel() self.list_widget = QListWidget() self.list_widget.setMouseTracking(True) for index, name in enumerate(["Italy", "France", "Spain"]): item = QListWidgetItem(QIcon("%s.png" % name), name) self.list_widget.insertItem(index, item) button_asc = QPushButton("Ascend") button_desc = QPushButton("Descend") layout.addWidget(self.text_label) layout.addWidget(self.list_widget) layout.addWidget(button_asc) layout.addWidget(button_desc) button_asc.clicked.connect(self.on_sorted) button_desc.clicked.connect(self.on_sorted) # self.list_widget.clicked.connect(self.on_list_widget) # self.list_widget.currentItemChanged.connect(self.on_current_i_changed) # self.list_widget.currentRowChanged[int].connect(self.on_row_changed) # self.list_widget.currentTextChanged.connect(self.on_text_changed) # self.list_widget.itemActivated.connect(self.on_item_activated) # self.list_widget.itemChanged.connect(self.on_item_changed) # self.list_widget.itemClicked.connect(self.on_item_clicked) # self.list_widget.itemDoubleClicked.connect(self.on_item_double_clicked) # self.list_widget.itemEntered.connect(self.on_item_entered) # self.list_widget.itemPressed.connect(self.on_item_pressed) # self.list_widget.itemSelectionChanged.connect(self.on_sel_changed) def on_current_i_changed(self): item = self.list_widget.currentItem() print("[SIG] Current item changed to <%s>" % item.text()) def on_row_changed(self, row): item = self.list_widget.item(row) print("[SIG] Current item changed to <{}[{}]>".format(item.text(), row)) def on_text_changed(self): item = self.list_widget.currentItem() print("[SIG] Current text-data changed to <%s>" % item.text()) def on_item_activated(self): item = self.list_widget.currentItem() print("[SIG] Activated item <%s>" % item.text()) def on_item_changed(self): item = self.list_widget.currentItem() print("[SIG] item changed to <%s>" % item.text()) def on_item_clicked(self): item = self.list_widget.currentItem() print("[SIG] item <%s> clicked" % item.text()) def on_item_double_clicked(self): item = self.list_widget.currentItem() print("[SIG] item <%s> double-clicked" % item.text()) def on_item_entered(self): item = self.list_widget.currentItem() print("[SIG] Mouse on ListWidget: current item is <%s>" % item.text()) def on_item_pressed(self): item = self.list_widget.currentItem() print("[SIG] item <%s> pressed" % item.text()) def on_sel_changed(self): item = self.list_widget.currentItem() print("[SIG] item <%s> selected" % item.text()) def on_sorted(self): button = self.sender() if button.text().lower() == "ascend": self.list_widget.sortItems(Qt.AscendingOrder) else: self.list_widget.sortItems(Qt.DescendingOrder) def on_list_widget(self): item = self.list_widget.currentItem() row = self.list_widget.currentRow() self.text_label.setText("{} selected (row {})".format(item.text(), row)) if __name__ == '__main__': app = QApplication(sys.argv) main_window = MainWindow() main_window.show() sys.exit(app.exec_())
Editing Item
Merita un approfondimento l’editing di un item.
Per poter editare i dati di un item e modificarli (causando l’emissione del segnale itemChanged, dobbiamo
utilizzare i metodi openPersistentEditor(item) e closePersistentEditor(item), del list-widget.
Ad esempio possiamo fare in modo che al doppio click su un item, si apra l’editor; per questo possiamo utilizzare il
segnale itamActivated, mentre a dati modificati, possiamo chiudere l’editor sfruttando il segnale
itemChanged:
... class FrameWidget(QWidget): def __init__(self, parent=None): ... self.list_widget.itemActivated.connect(self.on_item_activated) self.list_widget.itemChanged.connect(self.on_item_changed) ... def on_item_activated(self): item = self.list_widget.currentItem() print("[SIG] Activated item <%s>" % item.text()) self.list_widget.openPersistentEditor(item) # qui apriamo l'editor def on_item_changed(self): item = self.list_widget.currentItem() print("[SIG] item changed to <%s>" % item.text()) self.list_widget.closePersistentEditor(item) # qui chiudiamo l'editor ...
Nota:
Cosa succede se edito un item ma premo invio senza modificarne i dati?
L’editor rimane attivo sull’item, poichè lo chiudiamo solo in caso di modifica dei dati.
Per chiuderlo anche in caso di NON-modifica, possiamo ad esempio intercettare l’evento KeyPress e sovrascriverlo in modo che,
alla pressione del tasto
... class FrameWidget(QWidget): def __init__(self, parent=None): ... self.list_widget.itemActivated.connect(self.on_item_activated) self.list_widget.itemChanged.connect(self.on_item_changed) ... def on_item_activated(self): item = self.list_widget.currentItem() print("[SIG] Activated item <%s>" % item.text()) self.list_widget.openPersistentEditor(item) # qui apriamo l'editor def on_item_changed(self): item = self.list_widget.currentItem() print("[SIG] item changed to <%s>" % item.text()) self.list_widget.closePersistentEditor(item) # qui chiudiamo l'editor def keyPressEvent(self, event): # sovrascrivo l'evento KeyPressEvent print("[EVENT] Key Return pressed") if event.key() == Qt.Key_Return: item = self.list_widget.currentItem() self.list_widget.closePersistentEditor(item) ...
Ora, anche non modificando i deti dell’item, il persistent editor si chiuderà.
Commenti recenti