Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » PyQt4: проблема с созданием делегата [RSS Feed]

#1 Июнь 13, 2012 21:36:01

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt4: проблема с созданием делегата

Есть модель 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. Может я вообще не правильно делегат создаю?



Офлайн

#2 Июнь 14, 2012 08:01:20

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

PyQt4: проблема с созданием делегата

Вам нужно сделать свой виджет - 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)
    # ...

Отредактировано reclosedev (Июнь 14, 2012 08:02:34)

Офлайн

#3 Июнь 14, 2012 11:26:11

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt4: проблема с созданием делегата

Спасибо, часть вопросов снялась, но возникли другие. Сделал виджет по вашему совету

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



Офлайн

#4 Июнь 14, 2012 11:53:06

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

PyQt4: проблема с созданием делегата

В коде выглядит все нормально, но вот что нагуглил:
http://stackoverflow.com/questions/2468587/c-object-destroyed-in-qcombobox-descendant-editor-in-delegate

Получается, что т.к. вызывается модальный диалог для выбора папки, фокус у editor'а пропадает и виджет удаляется. Странно это конечно.

Офлайн

#5 Июнь 14, 2012 12:11:18

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt4: проблема с созданием делегата

Огромное спасибо! Помогло



Офлайн

  • Начало
  • » GUI
  • » PyQt4: проблема с созданием делегата[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version