Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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.


Log in to reply