Why my application is collapsed?
-
Hi guys!
I am a freshman for Qt.
Now I want a table to display formulas. There are 4 columns in table. The first column is a QCheckbox. And the others contain a QComboBox. I use a class derived from QStyledItemDelegate and a class derived from QAbstractTableModel to build it. The code of these class is following:class FormulaListModel : public QAbstractTableModel { typedef struct { QString op1_name; QString op2_name; QString op; bool isEnable; }FORMULA, *PFORMULA; Q_OBJECT public: FormulaListModel(QObject *parent); ~FormulaListModel(); /*Implement the necessary virtual function of QAbstractListModel*/ int rowCount(const QModelIndex & parent = QModelIndex()) const; int columnCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; private: QVector<PFORMULA> m_lsFormula; }; FormulaListModel::FormulaListModel(QObject *parent) : QAbstractTableModel(parent) { int i; for (i = 0;i < 10;i ++) { PFORMULA formula = new FORMULA; formula->isEnable = true; formula->op = "+"; formula->op1_name = QString("%1").arg(i); formula->op2_name = QString("%1").arg(50 - i); m_lsFormula.append(formula); } } FormulaListModel::~FormulaListModel() { foreach(PFORMULA f, m_lsFormula) { if (f) { delete f; } } m_lsFormula.clear(); } int FormulaListModel::rowCount(const QModelIndex & parent) const { return m_lsFormula.count(); } int FormulaListModel::columnCount(const QModelIndex & parent) const { return 4; } QVariant FormulaListModel::data(const QModelIndex & index, int role) const { switch(role) { case Qt::EditRole: { int r = index.row(); int c = index.column(); PFORMULA pf = m_lsFormula[r]; switch(c) { case 0: return pf->isEnable; case 1: return pf->op1_name; case 2: return pf->op; case 3: return pf->op2_name; } } case Qt::DisplayRole: { int c = index.column(); int r = index.row(); PFORMULA pf = m_lsFormula[r]; QStringList lsStr; switch(c) { case 0: return "IsUsed"; case 1: case 3: lsStr << "1"; lsStr << "2"; return lsStr; case 2: lsStr << "+"; lsStr << "-"; return lsStr; } } case Qt::DecorationRole: { QColor clr(Qt::transparent); return clr; } case Qt::SizeHintRole: return QSize(130, 16); case Qt::FontRole: { QFont font; font.setBold(true); return font; } case Qt::BackgroundRole: { QBrush brush(Qt::transparent); return brush; } case Qt::TextAlignmentRole: { return Qt::AlignHCenter; } case Qt::CheckStateRole: { return Qt::Checked; } case Qt::TextColorRole: { QColor clr(Qt::black); return clr; } case Qt::ToolTipRole: { return "Formula List"; } } } class FormulaItemDelegate : public QStyledItemDelegate { Q_OBJECT public: FormulaItemDelegate(QObject *parent); ~FormulaItemDelegate(); QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index)const; void setEditorData(QWidget * editor, const QModelIndex & index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; private: }; FormulaItemDelegate::FormulaItemDelegate(QObject *parent) : QStyledItemDelegate(parent) { } FormulaItemDelegate::~FormulaItemDelegate() { } QWidget * FormulaItemDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index)const { QVariant value = index.model()->data(index, Qt::DisplayRole); if (index.column() == 0) { QCheckBox * pBox = new QCheckBox(parent); pBox->setText(value.toString()); return pBox; } else { QComboBox * pBox = new QComboBox(parent); pBox->addItems(value.toStringList()); return pBox; } } void FormulaItemDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const { QVariant value = index.model()->data(index, Qt::EditRole); if (index.column() == 0) { bool checked = value.toBool(); QCheckBox * pBox = static_cast<QCheckBox *>(editor); if (pBox) { pBox->setChecked(checked); } } else { QString str = index.model()->data(index, Qt::EditRole).toString(); QComboBox * pBox = static_cast<QComboBox *>(editor); if (pBox) { pBox->setCurrentIndex(pBox->findText(str)); } } } void FormulaItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { QRect rc = option.rect; editor->setGeometry(rc); } void FormulaItemDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { if (index.column() == 0) { QCheckBox * pBox = static_cast<QCheckBox *>(editor); pBox->update(); bool checked = pBox->isChecked(); model->setData(index, checked, Qt::EditRole); } else { QComboBox * pBox = static_cast<QComboBox *>(editor); pBox->update(); QString str = pBox->currentText(); model->setData(index, str, Qt::EditRole); } } void FormulaItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { //画控件本身 int x = option.rect.x(); int y = option.rect.y(); painter->setBackgroundMode(Qt::TransparentMode); QVariant value = index.model()->data(index, Qt::DisplayRole); if (index.column() == 0) { bool checked = value.toBool(); QStyleOptionButton style; style.rect = QRect(x, y + 8, 12, 12); style.state |= QStyle::State_Enabled; style.state |= checked ? QStyle::State_On : QStyle::State_Off; QApplication::style()->drawControl(QStyle::CE_CheckBox, &style, painter); } else { QStyleOptionComplex style; style.rect = QRect(x, y + 8, 12, 12); style.state = QStyle::State_HasFocus; style.state |= QStyle::State_Enabled; QApplication::style()->drawComplexControl(QStyle::CC_ComboBox, &style, painter); } }
Then I use the following code to make table:
m_plsModel = new FormulaListModel(this); ui.tvFormulas->setModel(m_plsModel); ui.tvFormulas->setShowGrid(false); QHeaderView * pHeader = ui.tvFormulas->horizontalHeader(); pHeader->hide(); pHeader = ui.tvFormulas->verticalHeader(); pHeader->hide(); //列宽 ui.tvFormulas->setColumnWidth(0, 80); ui.tvFormulas->setColumnWidth(1, 150); ui.tvFormulas->setColumnWidth(2, 150); ui.tvFormulas->setColumnWidth(3, 150); m_pFormulaItem = new FormulaItemDelegate(this); ui.tvFormulas->setItemDelegate(m_pFormulaItem); for (int i = 0;i < m_plsModel->rowCount();i ++) { for (int j = 0;j < m_plsModel->columnCount();j ++) { ui.tvFormulas->openPersistentEditor(m_plsModel->index(i, j)); } } ui.tvFormulas->updateGeometry();
It's bizarre that when I use these code in a simple testing project, they works perfect. But when I use the same code in my real project, it collapsed when I use mouse wheel to scroll it. I check the code again and again. They are same as each other. The only difference is the environment. My test project is a QDialog application, though my real project is a QMainWindow application. The table is showed in a QDialog poped up. Is this the reason of collapse?
I hope someone could be kind to help me. Thank you! -
This bug had been fixed. The resolve is to add protected function in delegate class named eventFilter. In this member function, QEvent::Wheel should be filtered for QCheckBox because it can't support it. So, bug of collapse is fixed.