Désactiver l'utilisateur à cliquer sur QTableWidget
-
20-12-2019 - |
Question
J'ai QTableWidget avec des Cases à cocher dans certaines cellules.Je veux désactiver l'utilisateur afin d'effectuer un clic de souris sur les cellules de la table (donc il ne peut pas changer de case à cocher état) pour un certain temps alors que je suis en utilisant les données de la table.J'ai essayé table.setDisabled(1)
mais qui désactive l'ensemble de la table et j'ai besoin de faire défiler jusqu'à être activé.
Toute aide serait appréciée.
MODIFIER Pour être plus précis:il pourrait y avoir jusqu'à 15x3000 cellules dans le tableau, rempli avec du texte(modifiable), case(vérifiables), svg graphiques(ouvre une autre fenêtre lors d'un double click sur celui-ci) ou de certains widgets personnalisés(qui ont également cliquables ou parties modifiables).J'ai besoin de désactiver l'utilisateur à cliquer ou double-cliquer sur les cellules(de sorte qu'il ne peut pas changer l'un d'eux) pour 1sec - 10sec intervalle de temps (la solution doit être quelque chose de rapide, pas d'une itération à travers tous les éléments), mais j'ai besoin de barre de défilement pour être activé et la table normale de la visibilité.
La solution
Une façon d'y parvenir est de la sous-classe QTableWidgetItem et de re-mettre en œuvre les setData la méthode.De cette façon, vous pouvez contrôler si les éléments d'accepter des valeurs pour certains rôles.
Pour contrôler la "checkability" pour tous les éléments, vous pouvez ajouter un attribut de classe à la sous-classe qui pourrait être testé à chaque fois qu'une valeur pour le check-rôle de l'état a été adoptée à setData.
Voici ce que le sous-classe peut ressembler à:
class TableWidgetItem(QtGui.QTableWidgetItem):
_blocked = True
@classmethod
def blocked(cls):
return cls._checkable
@classmethod
def setBlocked(cls, checkable):
cls._checkable = bool(checkable)
def setData(self, role, value):
if role != QtCore.Qt.CheckStateRole or self.checkable():
QtGui.QTableWidgetItem.setData(self, role, value)
Et le "checkability" de tous les éléments seraient désactivés comme ceci:
TableWidgetItem.setCheckable(False)
Mise à JOUR:
L'idée ci-dessus peut être étendu par l'ajout d'une classe wrapper générique pour la cellule de widgets.
Les classes ci-dessous permettra de bloquer les modifications de texte et de vérifier l'état de la table-widget articles, et aussi une gamme d'évènements souris et clavier pour la cellule de widgets via un événement-filtre (d'autres événements peuvent être bloqués si nécessaire).
La cellule-widgets devraient être créés comme ceci:
widget = CellWidget(self.table, QtGui.QLineEdit())
self.table.setCellWidget(row, column, widget)
et alors accessible comme ceci:
widget = self.table.cellWidget().widget()
Le blocage de l'ensemble de la table passerait comme ça:
TableWidgetItem.setBlocked(True)
CellWidget.setBlocked(True)
# or Blockable.setBlocked(True)
Voici les catégories:
class Blockable(object):
_blocked = False
@classmethod
def blocked(cls):
return cls._blocked
@classmethod
def setBlocked(cls, blocked):
cls._blocked = bool(blocked)
class TableWidgetItem(Blockable, QtGui.QTableWidgetItem):
def setData(self, role, value):
if (not self.blocked() or (
role != QtCore.Qt.EditRole and
role != QtCore.Qt.CheckStateRole)):
QtGui.QTableWidgetItem.setData(self, role, value)
class CellWidget(Blockable, QtGui.QWidget):
def __init__(self, parent, widget):
QtGui.QWidget.__init__(self, parent)
self._widget = widget
layout = QtGui.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(widget)
widget.setParent(self)
widget.installEventFilter(self)
if hasattr(widget, 'viewport'):
widget.viewport().installEventFilter(self)
widget.show()
def widget(self):
return self._widget
def eventFilter(self, widget, event):
if self.blocked():
etype = event.type()
if (etype == QtCore.QEvent.KeyPress or
etype == QtCore.QEvent.KeyRelease or
etype == QtCore.QEvent.MouseButtonPress or
etype == QtCore.QEvent.MouseButtonRelease or
etype == QtCore.QEvent.MouseButtonDblClick or
etype == QtCore.QEvent.ContextMenu or
etype == QtCore.QEvent.Wheel):
return True
return QtGui.QWidget.eventFilter(self, widget, event)
Autres conseils
Juste itérer sur tous les QStandardItem
s et le changement valeurs d'indicateurs pour les articles qui ne doit pas être modifiable.
Vous pouvez utiliser le drapeau: Qt::ItemIsEditable
ou/et Qt::ItemIsEnabled
.
Vous devez désactiver les éléments eux-mêmes, par opposition à l'ensemble de la table si vous avez d'autres éléments que QCheckBoxes que vous ne souhaitez pas désactiver.Voir le code python ci-dessous pour plus de détails:
'''
Iterate through all the check boxes in the standard items
and make sure the enabled flag is cleared so that the items are disabled
'''
for standardItem in standardItems:
standardItem.setFlags(standardItem.flags() & ~Qt.ItemIsEnabled)
Ici vous pouvez trouver la documentation correspondante:
void QTableWidgetItem::setFlags(Qt::ItemFlags drapeaux)
Définit les options pour l'élément à la donnée de drapeaux.Ces de déterminer si l'élément peut être sélectionné ou modifié.