自己用QTableWidget来记录实时数据时,出现该问题,百度之后发现是因为在最初设置行数处(setRowCount()),设置的行宽不够,在对数据测试时,数据超出了设置行数,在调用相关setText()时,出现空指针导致程序崩掉。网上现存的解决方案中,是对该指针以及后续text进行空指判断,个人觉得这种实现方式治标不治本,所以本文会给出两种该bug的解决方式,以供参考。
// 判断指向该item的指针是否为空 || 判断该item的text是否为空
if(ui->tableWidget_bsdl->item(i,j)==nullptr || ui->tableWidget_bsdl->item(i,j)->text().isEmpty())
{
}
该操作原理,可以参考这位博主的文章,讲得十分详细。
解释:
(1)因为C++逻辑或和逻辑与采用短路求值策略:对于逻辑或运算,当且仅当左侧运算对象为假时,才对右侧运算对象求值。
(2)当ui->tableWidget->item(i,j)==nullptr为真时,是空指针,此时左侧运算对象为真,不会对右侧运算对象求值,即,不会用空指针去访问->text(),不会判断ui->tableWidget->item(i,j)->text()是否为空,是安全的。
(3)当ui->tableWidget->item(i,j)==nullptr为假时,不是空指针,此时才对||的右侧运算对象求值,又因为它不是空指针,所以用它访问->text()是安全的。
static int ROW_COUNT = 20;//设置行宽
if(temp.count() > ROW_COUNT) //此处temp为vector,该vector存放了需要显示的数据
{
ROW_COUNT = temp.count();
this->setRowCount(ROW_COUNT);
}
//do else
获取到需要设置的行宽数据,每次保证ROW_COUNT为最大,并设置最大行宽,就不会出现空指针问题了。
#ifndef LISTWIDGET_H
#define LISTWIDGET_H
#include
#include
#include
class QStandardItemModel;
class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QAbstractItemModel *model);
protected:
virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
virtual QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers) Q_DECL_OVERRIDE;
void scrollTo (const QModelIndex & index, ScrollHint hint = EnsureVisible) Q_DECL_OVERRIDE;
};
class ListWidget: public QWidget
{
Q_OBJECT
public:
ListWidget(QTableWidget * parent = nullptr);
~ListWidget();
private:
TableView *m_table_view;
QStandardItemModel *m_model;
QStringList headers;
};
#endif // LISTWIDGET_H
#include "ListWidget.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
TableView::TableView(QAbstractItemModel *model)
{
setModel(model);
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
setHorizontalScrollMode(ScrollPerPixel);
setVerticalScrollMode(ScrollPerPixel);
// verticalHeader()->setDefaultSectionSize(25); //配置行宽
horizontalHeader()->setSectionResizeMode(0,QHeaderView::ResizeToContents);//配置大小模式
horizontalHeader()->setSectionResizeMode(1,QHeaderView::Stretch);
horizontalHeader()->setSectionResizeMode(2,QHeaderView::Stretch);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setStyleSheet("QTableView { border: none;"
"selection-background-color: #999}");
}
void TableView::resizeEvent(QResizeEvent *event)
{
QTableView::resizeEvent(event);
}
QModelIndex TableView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
QModelIndex current = QTableView::moveCursor(cursorAction, modifiers);
if (cursorAction == MoveLeft && current.column() > 0
&& visualRect(current).topLeft().x() < columnWidth(3) )
{
const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x()
- columnWidth(0);
horizontalScrollBar()->setValue(newValue);
}
if (cursorAction == MoveLeft)
{
const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x();
horizontalScrollBar()->setValue(newValue);
}
return current;
}
void TableView::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint)
{
if (index.column() >= 0)
QTableView::scrollTo(index, hint);
}
ListWidget::ListWidget(QTableWidget *parent) :QWidget(parent)
{
m_model=new QStandardItemModel();
headers << "ID" <<"距离"<<"角度";
m_model->setHorizontalHeaderLabels(headers);
QVBoxLayout *main_layout = new QVBoxLayout();
m_table_view = new TableView(m_model);
main_layout->addWidget(m_table_view);
this->setLayout(main_layout);
// this->horizontalHeader()->setStyleSheet("QHeaderView::section{font: 15}");//设置表头背景和字体颜色
this->setFont(QFont("黑体",8));
m_timer = new QTimer(this);
m_timer->start(500);//ms
connect(this->m_timer,SIGNAL(timeout()),this,SLOT(clearListitem()));
}
ListWidget::~ListWidget()
{
}
//添加item代码
m_model->setItem(0,0,new QStandardItem(QString::number(it.key())));
m_model->item(0,0)->setTextAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
利用qt本身的view-model结构来进行实现,这种实现方式,可以避免空指针的问题。