Pergunta

Eu tenho um QTreeWidgetItem com duas colunas de dados, existe alguma maneira de fazer somente a segunda coluna editável?Quando eu faço o seguinte:

QTreeWidgetItem* item = new QTreeWidgetItem();
item->setFlags(item->flags() | Qt::ItemIsEditable);

todas as colunas tornar editável.

Foi útil?

Solução

Parece que você terá que renunciar ao uso QTreeWidget e QTreeWidgetItem e vá com QTreeView e QAbstractItemModel. As classes "widgets" são classes de conveniência que são implementações concretas das versões mais abstratas, mas mais flexíveis. QAbstractItemModel tem uma ligação flags(QModelIndex index) onde você retornaria o valor apropriado para sua coluna.

Outras dicas

Você pode fazer apenas algumas colunas em uma QTreeWidget editável utilizando uma solução:

1) Definir o editTriggers propriedade do QTreeWidget para NoEditTriggers

2) Na inserção de itens, definir o Qt:ItemIsEditable bandeira do QTreeWidgetItem objeto

3) Conectar o seguinte slot para o "itemDoubleClicked" sinal da QTreeWidget objeto:

void MainWindow::onTreeWidgetItemDoubleClicked(QTreeWidgetItem * item, int column)
{
    if (isEditable(column)) {
        ui.treeWidget->editItem(item, column);
    }
}

onde "isEditable" é uma função que você escreveu que retorna true para colunas editáveis e false para não-colunas editáveis.

Recentemente, tive o mesmo problema e descobri uma solução que funciona com todos os edittiggers, não apenas o DoubleClicked One (e a conexão com o sinal de clique duas vezes)

Crie um delegado, que retorne um ponteiro nulo para o editor:

class NoEditDelegate: public QStyledItemDelegate {
    public:
      NoEditDelegate(QObject* parent=0): QStyledItemDelegate(parent) {}
      virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
        return 0;
      }
    };

E use -o mais tarde como um delegado personalizado para sua coluna

ui->parameterView->setItemDelegateForColumn(0, new NoEditDelegate(this));

Parece que o QtreeWidget padrão não permite isso. Eu acho que existem duas maneiras de fazer isso:

  1. Use um QtreeView com sua própria classe derivada de QabstractItemModel e substitua a função Sinalizador

  2. Use um QtreeView com um qStandardiTemmodel. Então, quando você adiciona o item, basta definir a coluna apropriada para permitir edições:

Aqui está algum código para a segunda opção:

QString x, y;
QList<QStandardItem*> newIt;
QStandardItem * item = new QStandardItem(x);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
newIt.append(item);
item = new QStandardItem(y);
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable);
newIt.append(item);
model->appendRow(newIt);

Acho a segunda abordagem mais simples, mas isso depende de quanta flexibilidade você deseja com seu modelo.

A maneira mais simples que eu encontrei foi usar qt :: itemflags

void myClass::treeDoubleClickSlot(QTreeWidgetItem *item, int column)
{
    Qt::ItemFlags tmp = item->flags();
    if (isEditable(item, column)) {
        item->setFlags(tmp | Qt::ItemIsEditable);
    } else if (tmp & Qt::ItemIsEditable) {
        item->setFlags(tmp ^ Qt::ItemIsEditable);
    }
}

O topo do if adiciona a funcionalidade de edição através de um OR, e o fundo verifica se está lá com AND, então remove com um XOR.

Dessa forma, a funcionalidade de edição é adicionada quando você deseja e removida quando não o fizer.

Em seguida, conecte esta função ao widget da árvore itemDoubleClicked() sinalize e escreva o seu 'para editar ou não editar' a decisão dentro de isEditable()

class EditorDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    EditorDelegate(QObject *parent):QItemDelegate(parent){};
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

QWidget* EditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.column() == 1)
    {
        return QItemDelegate::createEditor(parent, option, index);
    }
    return nullptr;
}

No QTreeWidget:

myQTreeWidget::myQTreeWidget()
{
    EditorDelegate *d = new EditorDelegate(this);
    this->setItemDelegate(d);
}

Talvez um pouco tarde, mas possa ajudar:

void MyClass::on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column) {
    Qt::ItemFlags flags = item->flags();
    if(column == 0)
    {
        item->setFlags(flags & (~Qt::ItemIsEditable));
    }
    else
    {
        item->setFlags(flags | Qt::ItemIsEditable);
    } 
}

Aqui 0 está o índice da coluna que você deseja fazer readonly.

flags & (~Qt::ItemIsEditable)

Define a posição iticemedável para 0, independentemente do sinalizador anterior do seu item.

flags | Qt::ItemIsEditable

Define -o para 1 independentemente da bandeira anterior.

Eu sou novo no Pyside e Python em geral, mas consegui fazer isso funcionar registrando -se no Qtreewidget para o ItemClicked Retorpors. Dentro do retorno de chamada, verifique a coluna e ligue apenas para 'EditItem' se for para uma coluna que você deseja permitir a edição.

class Foo(QtGui.QMainWindow):
...
def itemClicked(self, item, column):
   if column > 0:
      self.qtree.editItem(item, column)

Ao não invocar o EditItem para a coluna 0, o evento é basicamente descartado.

Descobri que o código abaixo funciona bem para minhas necessidades e "meio" impede o usuário de editar certas partes das colunas:

Eu basicamente verifico a função e depois a coluna. Eu só permito editar na coluna 0. Portanto, se o usuário editá -lo em qualquer outra coluna, paro a edição do setData e nenhuma alteração estiver sendo feita.

void treeItemSubclassed::setData(int column, int role, const QVariant &value) {
    if (role == Qt::ItemIsEditable && column != 0){
        return;
    }
    QTreeWidgetItem::setData(column, role, value);
}

Defina o filho da árvore-widget editável ou não (itmes de árvore), com base na linha e na coluna.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top