python qt model-view-controller pyqt pyside

python - La ordenación de QTableView falla después de setHorizontalHeader()



model-view-controller pyqt (1)

Me encuentro con un problema extraño con PySide QTableView s después de haber configurado una nueva instancia de setHorizontalHeader() través de setHorizontalHeader() . Específicamente, parece que la capacidad de clasificación de la vista está rota / no se puede invocar más.

Preguntas

  • ¿Por qué se rompe la clasificación después de establecer una nueva vista de encabezado?
  • ¿Por qué los métodos de monopatching en la instancia de vista de encabezado solo funcionan después de establecer un nuevo encabezado a través de setHorizontalHeader() ? (Consulte wrap_size_hint() en el código de demostración).
  • Al iniciar sesión en los elementos QHeaderView de la vista de tabla, ¿por qué siempre hay 2 instancias de QHeaderView ?
  • ¿Qué están haciendo realmente los métodos initialize() en QHeaderView ? ¿Podrían ser útiles aquí de alguna manera? Los documentos no son tan útiles .

Código de demostración (gist)

# -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function, division import logging import sys from PySide import QtCore from PySide import QtGui # configure logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) def wrap_size_hint(func): """Monkeypatch virtual method to increase sizeHint. Notes: Strangely this does not work when when no custom header is set on the table view. """ def wrapped(*args, **kwargs): """Just extend sizeHint to increase height.""" size = func(*args, **kwargs) # QSize height_increase = 60 height = size.height() + height_increase size.setHeight(height) return size return wrapped class CustomHeaderView(QtGui.QHeaderView): """CustomHeaderView""" class TestWidget(QtGui.QWidget): def __init__(self, use_custom_headerview=True, *args, **kwargs): super(TestWidget, self).__init__(*args, **kwargs) self.logger = logging.getLogger(type(self).__name__) QtGui.QVBoxLayout(self) self.setup_mvc(use_custom_headerview) self.update_model() self.log_children(self.view) def setup_mvc(self, use_custom_headerview): layout = self.layout() # model header_labels = "One Two Three Four Five".split() self.model = QtGui.QStandardItemModel() self.model.setHorizontalHeaderLabels(header_labels) # proxymodel self.proxymodel = QtGui.QSortFilterProxyModel() self.proxymodel.setDynamicSortFilter(True) self.proxymodel.setSourceModel(self.model) # view self.view = QtGui.QTableView() if (use_custom_headerview is True): self.view.setHorizontalHeader(CustomHeaderView(QtCore.Qt.Horizontal)) self.view.setSortingEnabled(True) self.view.setModel(self.proxymodel) # monkeypatch sizeHint to increase size headerview = self.view.horizontalHeader() headerview.sizeHint = wrap_size_hint(headerview.sizeHint) layout.addWidget(self.view) def update_model(self): for row in range(50): items = [] for column in range(self.model.columnCount()): text = "{0} {1}".format(row, column) item = QtGui.QStandardItem() item.setEditable(True) item.setData(text, QtCore.Qt.DisplayRole) items.append(item) self.model.appendRow(items) def log_children(self, widget, tab=-1): tab += 1 msg = "{0}{0}: {1}".format("--"*tab, type(widget).__name__, widget) self.logger.info(msg) for child in widget.children(): self.log_children(child, tab) if (__name__ == "__main__"): app = QtGui.QApplication(sys.argv) # widget_sorting_fails widget_sorting_fails = TestWidget(use_custom_headerview=True) widget_sorting_fails.setWindowTitle("Custom headerview") widget_sorting_fails.show() logger.info("-"*100) # widget_sorting_succeeds widget_sorting_succeeds = TestWidget(use_custom_headerview=False) widget_sorting_succeeds.setWindowTitle("No custom headerview") widget_sorting_succeeds.show() # start event loop sys.exit(app.exec_())


Ok, descubrí que setClickable(True) hará el truco. Parece estar QTableView forma predeterminada en las vistas de encabezado de QTableView , pero no en instancias creadas manualmente.