0

我很难在 Qt5 框架中实现自己的 MVC 方法。

我创建了自己的自定义项目类,从 QAbstractItemModel 派生了我的模型类,从 QStyledItemDelegate 派生了我的委托类,并将所有内容放在 QTreeView 中。

我已经尽可能地减少了我的代码以创建一个有点“最小”的例子。

我看到的是以下内容:我可以看到我的标题有 42,我可以看到一个条目说“测试项目”。尽管如此,当我双击后者或在选择它时按 F2 时 - 没有任何反应。'editTriggers' 调用返回 10,这意味着双击应该起作用(但它们不起作用)。我显然在这里遗漏了一些东西,但是经过几天自己试图弄清楚之后,我不得不承认我不知道。这是我的程序:

编辑开始,11 月 28 日

正如@eyllanesc 向我提议的那样,为了方便起见,我建立了一个小的 Github 存储库。链接在这里:

https://github.com/phyz777/DelegateTest.git

编辑结束,11 月 28 日

主.cpp:

int main(int argc, char* argv[]){
  QApplication a(argc, argv);
  MainWindow w;
  w.showFullScreen();

  return a.exec();
}

主窗口.hpp:

class MainWindow : public QMainWindow{
  Q_OBJECT

public:
  MainWindow(QWidget* parent = 0);
  ~MainWindow();
private slots:

private:
  TestModel model;
};

主窗口.cpp:

MainWindow::MainWindow(QWidget *parent)
  :QMainWindow(parent),
   model(){
  this->model.insertTestItem(new TestClass());

  QTreeView* treeView = new QTreeView(this);
  treeView->setItemDelegate(new TestModelItemDelegate());
  treeView->setModel(&this->model);
  treeView->setRootIndex(this->model.index(0, 0, QModelIndex()));
  std::cout << "Edit triggers: " << (int)treeView->editTriggers() << std::endl;
  this->setCentralWidget(treeView);
}

MainWindow::~MainWindow(){
  ;
}

测试模型.hpp:

class TestModel:public QAbstractItemModel{
public:
  TestModel();
  ~TestModel();

  int rowCount(QModelIndex const& =QModelIndex()) const;
  int columnCount(QModelIndex const& =QModelIndex()) const;

  QModelIndex index(int, int, QModelIndex const& =QModelIndex()) const;
  QModelIndex parent(QModelIndex const&) const;

  QVariant headerData(int, Qt::Orientation, int=Qt::DisplayRole) const;
  QVariant data(const QModelIndex&, int=Qt::DisplayRole) const;
  Qt::ItemFlags flags(QModelIndex const&);

  bool setHeaderData(int, Qt::Orientation, QVariant const&, int);
  bool setData(QModelIndex const&, QVariant const&, int);

  void insertTestItem(TestClass*);

  RootItem* getRoot();
private:
  RootItem* root;
};

测试模型.cpp:

TestModel::TestModel()
  :root(new RootItem()){

}

TestModel::~TestModel(){

}

int TestModel::rowCount(QModelIndex const& parent) const{
  TestModelItemBase* itemBase =
    reinterpret_cast<TestModelItemBase*>(parent.internalPointer());
  switch(itemBase->getItemType()){
    case TestModelItemBase::ITEM_TYPE::ROOT:
      {
        RootItem* item = dynamic_cast<RootItem*>(itemBase);
        return item->getList().size();
      }
    case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
      {
        TestModelItem* item = dynamic_cast<TestModelItem*>(itemBase);
        return 0;
      }
    default:
      return -1;
  }
}

int TestModel::columnCount(QModelIndex const& parent) const{
  return 1;
}

QModelIndex TestModel::index(int row, int column, QModelIndex const& parent) const{
  if(0!=column){
    return QModelIndex();
  }
  if(!parent.isValid()){
    if(row==0){
      return this->createIndex(0, 0, this->root);
    }
    return QModelIndex();
  }
  TestModelItemBase* parentItemBase = reinterpret_cast<TestModelItemBase*>(parent.internalPointer());
  TestModelItemBase::ITEM_TYPE itemType = parentItemBase->getItemType();
  switch(itemType){
    case TestModelItemBase::ITEM_TYPE::ROOT:
      {
        RootItem* parentItem = dynamic_cast<RootItem*>(parentItemBase);
        return this->createIndex(row, 0, reinterpret_cast<void*>(parentItem->getList().at(row)));
      }
    case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
      return QModelIndex();
    default:
      return QModelIndex();
  }
}

QModelIndex TestModel::parent(QModelIndex const& index) const{
  TestModelItemBase* parent =
    reinterpret_cast<TestModelItemBase*>(index.internalPointer());
  return this->createIndex(parent->getIndex(), 0,
                           reinterpret_cast<void*>(parent->getParent()));
}

QVariant TestModel::headerData(int section, Qt::Orientation orientation, int role) const{
  if (0==section && Qt::Orientation::Horizontal==orientation && Qt::DisplayRole==role) {
    int i = 42;
    return QVariant(i);
  } else {
    return QVariant();
  }
}

QVariant TestModel::data(QModelIndex const& index, int role) const{
  TestModelItemBase* item = reinterpret_cast<TestModelItemBase*>(index.internalPointer());
  if(Qt::DisplayRole==role){
    switch(item->getItemType()){
      case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
        return QString("Test item");
      default:
        return QString("");
    }
  }else{
    if(Qt::EditRole==role){
      QMessageBox::information(nullptr, "Model data", "We have an edit role");
    }
    if(Qt::UserRole==role){
      QMessageBox::information(nullptr, "Model data", "We have a user role");
    }

    return QVariant();
  }
}

Qt::ItemFlags TestModel::flags(QModelIndex const&){
  QMessageBox::information(nullptr, "Model Flags", "Selectable, Editable, Enabled");

  return (Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
}

bool TestModel::setHeaderData(int, Qt::Orientation, const QVariant&, int){
  QMessageBox::information(nullptr, "Set header data", "Just return true");

  return true;
}

bool TestModel::setData(const QModelIndex&, const QVariant&, int){
  QMessageBox::information(nullptr, "Set data", "Just return true");

  return true;
}

void TestModel::insertTestItem(TestClass* testClass){
  if(nullptr==testClass){
    QMessageBox::critical(nullptr, "Critical", "Not inserting nullptr");
    return;
  }

  TestModelItem* child = new TestModelItem(testClass, this->root->size(), this->root);
  this->beginInsertRows(this->createIndex(0, 0, reinterpret_cast<void*>(this->root)),
                        this->root->size(), this->root->size());
  this->root->appendChild(child);
  this->endInsertRows();
}

RootItem* TestModel::getRoot(){
  return this->root;
}

testmodelitem.hpp:

class TestModelItemBase{
public:
  enum class ITEM_TYPE{
    ISNULL, INVALID, ROOT, TEST_ITEM
  };

  TestModelItemBase();
  TestModelItemBase(ITEM_TYPE, int, TestModelItemBase*);
  virtual ~TestModelItemBase();

  ITEM_TYPE getItemType() const;
  int getIndex() const;
  TestModelItemBase* getParent();

  virtual int size();

private:
  ITEM_TYPE itemType;
  int index;
  TestModelItemBase* parent;
};

class RootItem;
class TestModelItem;
class TestClass;

class RootItem:public TestModelItemBase{
public:
  RootItem();
  ~RootItem();

  QList<TestModelItem*>& getList();

  void appendChild(TestModelItem*);

  virtual int size();
private:
  QList<TestModelItem*> list;
};

class TestModelItem:public TestModelItemBase{
public:
  TestModelItem(TestClass*, int, RootItem*);
  ~TestModelItem();

  TestClass* getData();

  virtual int size();
private:
  TestClass* data;
};

class TestClass{

};

testmodelitem.cpp:

TestModelItemBase::TestModelItemBase()
  :itemType(TestModelItemBase::ITEM_TYPE::INVALID), index(-1), parent(nullptr){

}

TestModelItemBase::TestModelItemBase(TestModelItemBase::ITEM_TYPE type, int i, TestModelItemBase* p)
  :itemType(type), index(i), parent(p){

}

TestModelItemBase::~TestModelItemBase(){

}

TestModelItemBase::ITEM_TYPE TestModelItemBase::getItemType() const{
  if(nullptr==this){
    return TestModelItemBase::ITEM_TYPE::ISNULL;
  }
  return this->itemType;
}

int TestModelItemBase::getIndex() const{
  if(nullptr==this){
    return -2;
  }
  return this->index;
}

TestModelItemBase* TestModelItemBase::getParent(){
  if(nullptr==this){
    return nullptr;
  }
  return this->parent;
}

int TestModelItemBase::size(){
  return -1;
}

RootItem::RootItem()
  :TestModelItemBase(TestModelItemBase::ITEM_TYPE::ROOT,
                     0, nullptr){

}

RootItem::~RootItem(){

}

QList<TestModelItem*>& RootItem::getList(){
  return this->list;
}

void RootItem::appendChild(TestModelItem* child){
  this->list.append(child);
}

int RootItem::size(){
  return this->list.size();
}

TestModelItem::TestModelItem(TestClass* d, int index, RootItem* parent)
  :data(d),
   TestModelItemBase(TestModelItemBase::ITEM_TYPE::TEST_ITEM,
                     index, parent){

}

TestModelItem::~TestModelItem(){

}

TestClass* TestModelItem::getData(){
  return this->data;
}

int TestModelItem::size(){
  return 0;
}

testmodelitemdelegate.hpp:

class TestModelItemDelegate:public QStyledItemDelegate{
Q_OBJECT

public:
  TestModelItemDelegate();
  ~TestModelItemDelegate();

  QWidget* createEditor(QWidget*, QStyleOptionViewItem const&, QModelIndex const&) const override;
  void setEditorData(QWidget*, QModelIndex const&) const override;
  void setModelData(QWidget*, QAbstractItemModel*, QModelIndex const&);
  void updateEditorGeometry(QWidget* editor, QStyleOptionViewItem const& option,
                            QModelIndex const& index) const;

private:
  QWidget* createTestEditor(QWidget*) const;
};

testmodelitemdelegate.cpp:

TestModelItemDelegate::TestModelItemDelegate(){
  ;
}

TestModelItemDelegate::~TestModelItemDelegate(){
  ;
}

QWidget* TestModelItemDelegate::createEditor(QWidget* parent,
                                             QStyleOptionViewItem const& option,
                                             QModelIndex const& index) const{
  QMessageBox::information(nullptr, "Create editor", "Creating editor...");

  TestModelItemBase* item = reinterpret_cast<TestModelItemBase*>(index.internalPointer());

  switch(item->getItemType()){
    case TestModelItemBase::ITEM_TYPE::TEST_ITEM:
      return TestModelItemDelegate::createTestEditor(parent);
    default:
      break;
  }
}

void TestModelItemDelegate::setEditorData(QWidget*, QModelIndex const&) const{
  QMessageBox::information(nullptr, "Set editor data", "Doing nothing");
}

void TestModelItemDelegate::setModelData(QWidget*, QAbstractItemModel*,
                                         QModelIndex const&){
  QMessageBox::information(nullptr, "Set model data", "Doing nothing");
}

void TestModelItemDelegate::updateEditorGeometry(QWidget* editor, QStyleOptionViewItem const& option,
                                                 QModelIndex const& index) const{
  QMessageBox::information(nullptr, "Update editor geometry", "Doing nothing");
}

QWidget* TestModelItemDelegate::createTestEditor(QWidget* parent) const{
  QMessageBox::information(nullptr, "Create test editor", "Editor for testing");

  QWidget* editor = new QWidget(parent);

  QHBoxLayout* layout = new QHBoxLayout(editor);

  layout->addWidget(new QPushButton(editor));
  layout->addWidget(new QLineEdit(editor));

  editor->setLayout(layout);

  return editor;
}

我截断了所有包含的内容。我非常感谢提供的任何帮助。提前致谢!

4

0 回答 0