Найти - Пользователи
Полная версия: PyQt4: проблема с созданием делегата
Начало » GUI » PyQt4: проблема с созданием делегата
1
voltron
Есть модель QStandardItemModel, данные из которой оторажаются при помощи QTableView. Необходимо сделать так, чтобы при редактировании последнего столбца таблицы использовался нестандартный элемент, а именно, поле ввода с кнопкой открытия диалога выбора папки (QFileDialog.getExistingDirectory()). Т.е. надо создать делегат и повесить его на нужный столбец QTableView.

Вот на создании делегата я и застрял: не могу понять как сделать передачу значения в делегат и из него. Код такой
class DirectoryDelegate( QItemDelegate ):
  selectClicked = pyqtSignal()
  def __init__( self, parent = None ):
    QItemDelegate.__init__( self, parent )
  def createEditor( self, parent, options, index ):
    self.btnSelect = QPushButton( self.tr( "..." ) )
    self.lineEdit = QLineEdit()
    hbl = QHBoxLayout()
    hbl.addWidget( self.lineEdit )
    hbl.addWidget( self.btnSelect )
    self.btnSelect.clicked.connect( self.selectDirectory )
    myWidget = QWidget( parent )
    myWidget.setBackgroundRole( QPalette.Window )
    myWidget.setAutoFillBackground( True )
    myWidget.setLayout( hbl )
    return myWidget
  def setEditorData( self, editor, index ):
    value = index.model().data( index, Qt.EditRole ).toString()
    editor.setText( value )
  def setModelData( self, editor, model, index ):
    model.setData( index, editor.text(), Qt.EditRole )
  def selectDirectory( self ):
    dirName = QFileDialog.getExistingDirectory( None, self.tr( "Select directory" ), "", QFileDialog.ShowDirsOnly )
    if dirName.isEmpty():
      return
    self.lineEdit.setText( dirName )
Ошибка возникает в строке
editor.setText( value )
и гласит, что у QWidget нет метода setText, что логично. Вопрос в том, как все же достучаться до QLineEdit? Пробовал использовать
editor.findChild( QLineEdit, "lineEdit" )
не помогает.

P.S. Может я вообще не правильно делегат создаю?
reclosedev
Вам нужно сделать свой виджет - editor, в котором будут все элементы (кнопки, lineEdit-ы), сигналы и функции.

Псевдокод:
class DirChooseEditor(QtGui.QWidget):
    def __init__(self, parent=None):
        super(DirChooseEditor, self).__init__(parent)
        self.lineEdit = ...
        self.button = ...
        # layout, style, signals etc
        # ...
        
    def _on_button_clicked(self):
        # show select dir dialog
        # update lineedit
        
    def get_directory(self):
        return self.lineEdit.text()
        
    def set_directory(self, directory):
        self.lineEdit.setText(directory)
 
 
class DirectoryDelegate(QItemDelegate):
    # ...
    def createEditor( self, parent, options, index ):
        return DirChooseEitor(parent) # maybe set initial directory before return, etc
    
    def setEditorData( self, editor, index ):
        value = ...
        editor.set_directory(value)
    # ...
voltron
Спасибо, часть вопросов снялась, но возникли другие. Сделал виджет по вашему совету
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from ui_directoryselectorbase import Ui_DirectorySelector
class DirectorySelector( QWidget, Ui_DirectorySelector ):
  def __init__( self, parent = None ):
    QWidget.__init__( self, parent )
    self.setupUi( self )
    self.setFocusPolicy( Qt.StrongFocus )
    self.btnSelect.clicked.connect( self.selectDirectory )
  def selectDirectory( self ):
    dirName = QFileDialog.getExistingDirectory( None, self.tr( "Select directory" ), "", QFileDialog.ShowDirsOnly )
    if dirName.isEmpty():
      return
    self.lineEdit.setText( dirName )
  def text( self ):
    return self.lineEdit.text()
  def setText( self, value ):
    self.lineEdit.setText( value )
и делегат
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import directoryselector
class DirectoryDelegate( QItemDelegate ):
  def __init__( self, parent = None ):
    QItemDelegate.__init__( self, parent )
  def createEditor( self, parent, options, index ):
    return directoryselector.DirectorySelector( parent )
  def setEditorData( self, editor, index ):
    value = index.model().data( index, Qt.EditRole ).toString()
    editor.setText( value )
  def setModelData( self, editor, model, index ):
    model.setData( index, editor.text(), Qt.EditRole )
Теперь ошибка возникает при попытке обновить содержимое lineEdit'а после выбора каталога
File “directoryselector.py”, line 56, in selectDirectory
self.lineEdit.setText( dirName )
RuntimeError: underlying C/C++ object has been deleted
reclosedev
В коде выглядит все нормально, но вот что нагуглил:
http://stackoverflow.com/questions/2468587/c-object-destroyed-in-qcombobox-descendant-editor-in-delegate

Получается, что т.к. вызывается модальный диалог для выбора папки, фокус у editor'а пропадает и виджет удаляется. Странно это конечно.
voltron
Огромное спасибо! Помогло
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB