QTreeWidget里嵌套表格QTableView
阅读原文时间:2023年07月15日阅读:4

InformationPositionSubTableView::InformationPositionSubTableView(QStringList& columnNameList,QList& positionItemList,QWidget *parent) : m_ColumnNameList(columnNameList), m_PositionItemList(positionItemList),QTableView(parent)
{
m_InformationPositionSubTableModel = new InformationPositionSubTableModel(columnNameList,positionItemList);
this->setModel(m_InformationPositionSubTableModel);

 this->setMouseTracking(true);  
 this->setFocusPolicy(Qt::NoFocus);  
 this->setGridStyle(Qt::NoPen);  
  this->setSelectionBehavior(QAbstractItemView::SelectItems);  
 this->setSelectionMode(QAbstractItemView::SingleSelection);

 QHeaderView\* headerView = new InformationPositionSubHeaderview(Qt::Horizontal,this);  
 headerView->setSectionsClickable(true);  
 this->setHorizontalHeader(headerView);  
 this->horizontalHeader()->setStretchLastSection(true);  
 this->verticalHeader()->setVisible(false);

 this->setEditTriggers(QAbstractItemView::NoEditTriggers);  
 this->setContextMenuPolicy(Qt::CustomContextMenu);

 this->resizeColumnsToContents();  

// this->resizeRowsToContents(); //不能加上,否则做为QTreeWidget的子控件会多出一行的间隙;

 this->setFrameShape(QFrame::NoFrame);  //设置成无边框;

 this->horizontalHeader()->setStyleSheet("QHeaderView{background-color:gray;}");    //设置表头背景为灰色(这样也看起来扁平);  

}

InformationPositionSubTableView::~InformationPositionSubTableView()
{

}

void InformationPositionSubTableView::mouseMoveEvent(QMouseEvent * event)
{
QModelIndex index = indexAt(event->pos());
if(index.isValid() && index.row()>=)
{
this->setSelection(visualRect(index),QItemSelectionModel::SelectCurrent);
}

}

========

InformationPositionSubTableModel::InformationPositionSubTableModel(QStringList& columnNameList,QList& positionItemList,QObject *parent) : m_ColumnNameList(columnNameList),m_PositionItemList(positionItemList),QAbstractTableModel(parent)
{
this->m_ColumnNameList = columnNameList;
}

InformationPositionSubTableModel::~InformationPositionSubTableModel()
{

}
QVariant InformationPositionSubTableModel::data(const QModelIndex & index, int role) const
{
Q_UNUSED(index);
if(!index.isValid())
return QVariant();

 if(role==Qt::DisplayRole)  
 {  
     PositionItem item = m\_PositionItemList\[index.row()\];  
     int column = index.column();  
     switch (column)  
     {  
     case :  
         return item.GetAccountName();  
     case :  
         return item.GetBuyLot();  
     case :  
         return item.GetAvgBuyPrice();  
     case :  
         return item.GetSellLot();  
     case :  
         return item.GetAvgSellPrice();  
     case :  
         return item.GetNet();  
     default:  
         return item.GetFloatingMap()\[headerData(column,Qt::Horizontal,Qt::DisplayRole).toString()\];  
     }  
 }

 if(role==Qt::TextAlignmentRole)  
 {  
     return Qt::AlignCenter;  
 }

 if(role==Qt::TextColorRole)  
 {  
     if(index.column()== || index.column()==)  
     {  
         return QColor(Qt::red);  
     }  
     if(index.column()==)  
     {  
         return QColor(Qt::green);  
     }  
 }

 return QVariant();  

}
QVariant InformationPositionSubTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role!=Qt::DisplayRole)
return QVariant();

 if(orientation == Qt::Horizontal)  
 {  
     return m\_ColumnNameList\[section\];  
 }

 return QVariant();  

}
bool InformationPositionSubTableModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role)
{
if(role!=Qt::EditRole)
return false;
if(orientation == Qt::Horizontal && section >=)
{
m_ColumnNameList.append(value.toString());
emit headerDataChanged(orientation,section,section);
return true;
}
return false;
}

int InformationPositionSubTableModel::rowCount(const QModelIndex & parent) const
{
int rows = m_PositionItemList.count();
return rows;
}
int InformationPositionSubTableModel::columnCount(const QModelIndex & parent) const
{
return m_ColumnNameList.count();
}
bool InformationPositionSubTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
Q_UNUSED(index);
if (index.isValid() && role == Qt::DisplayRole)
{
int row = index.row();
m_PositionItemList.replace(row, m_UpdatingItem);
emit(dataChanged(index, index));
}
return true;
}
Qt::ItemFlags InformationPositionSubTableModel::flags(const QModelIndex & index) const
{
Q_UNUSED(index);
if (!index.isValid())
return Qt::ItemIsEditable;

 return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;  

}

bool InformationPositionSubTableModel::insertRow(int position,const QModelIndex &index)
{
Q_UNUSED(index);
beginInsertRows(index, position, position);

 int count = m\_UpdatingItem.GetFloatingMap().count();  
 QMapIterator<QString,float> it(m\_UpdatingItem.GetFloatingMap());  
 while(it.hasNext())  
 {  
     it.next();  
     this->AddHeaderSection(it.key());  
 }

 m\_PositionItemList.insert(position,m\_UpdatingItem);  
 endInsertRows();  
 return true;  

}
bool InformationPositionSubTableModel::removeRow(int position,const QModelIndex &index)
{
Q_UNUSED(index);
beginRemoveRows(index, position, position);
m_PositionItemList.removeAt(position);
endRemoveRows();
return true;
}
void InformationPositionSubTableModel::AddHeaderSection(const QString& columnName)
{
if(!m_ColumnNameList.contains(columnName))
{
setHeaderData(m_ColumnNameList.count(),Qt::Horizontal,Qt::EditRole);
m_ColumnNameList.append(columnName);
}
}

=====

InformationPositionSubHeaderview::InformationPositionSubHeaderview(Qt::Orientation orientation,QWidget* parent) : QHeaderView(orientation,parent)
{
this->setSectionsClickable(false);
this->m_IsHided = false;
}

InformationPositionSubHeaderview::~InformationPositionSubHeaderview()
{
}

void InformationPositionSubHeaderview::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();

 if(logicalIndex== && m\_IsHided==false)  
 {  
     painter->drawText(rect,Qt::AlignRight|Qt::AlignVCenter, "<<");  
 }

 if(logicalIndex== && m\_IsHided==true)  
 {  
     QRect leftRect = QRect(rect.x(),rect.y(),HIDEDCOLORBTNWIDTH,rect.height());  
     painter->setBrush(QBrush(Qt::blue));  
     painter->drawRect(leftRect);  
 }

}

void InformationPositionSubHeaderview::mousePressEvent(QMouseEvent * event)
{
if(event->button()==Qt::LeftButton)
{
QFontMetrics fm(this->font());
int textWidth = fm.width("<<");

     int index = logicalIndexAt(event->pos());  
     int xPos =event->pos().x();  
     int xLeft = sectionPosition(index)+sectionSize(index);  
     if(index== && m\_IsHided==false && (xPos<xLeft-HIDEDCOLORBTNWIDTH && xPos>xLeft-textWidth) )  
     {  
         setSectionHidden(index,true);  
         m\_IsHided = true;  
     }  
     else if(index== && m\_IsHided==true && xPos<=HIDEDCOLORBTNWIDTH)  
     {  
         setSectionHidden(index-,false);  
         m\_IsHided = false;  
     }  
 }  
 QHeaderView::mousePressEvent(event);  

}

======

InformationPositionTreeView::InformationPositionTreeView(InformationPositionItem& infoItem,QWidget *parent) : QTreeWidget(parent)
{
m_SubColumnNameList = infoItem.GetColumnNameList();
m_SubColumnNameList.removeAt();
m_SubColumnNameList.replace(,"Account ");//多出四个空格,是为"<<"腾出空间;

 this->Init();  
 this->InitPositionItemListMap(infoItem);

 int columnNameCount = infoItem.GetColumnNameList().count();  
 this->setHeaderLabels(infoItem.GetColumnNameList()); //增加标题;

 int count = m\_InstrumentStringList.count();  
 for(int i=;i<count;i++)  
 {  
     QList<PositionItem>  positionItemList = m\_PositionItemListMap\[m\_InstrumentStringList\[i\]\];  
     QStringList summaryList;  
     summaryList << "" << (m\_InstrumentStringList\[i\]) << QString("%0").arg(GetSumValue(positionItemList,"buy")) << QString("%0").arg(GetSumValue(positionItemList,"avgbuy")) << QString("%0").arg(GetSumValue(positionItemList,"sell")) << QString("%0").arg(GetSumValue(positionItemList,"avgsell")) << QString("%0").arg(GetSumValue(positionItemList,"net")) ;  
     QTreeWidgetItem\* node = new QTreeWidgetItem(summaryList);  
     this->addTopLevelItem(node);

     InformationPositionSubTableView\* subTableView = new InformationPositionSubTableView(m\_SubColumnNameList,m\_PositionItemListMap\[m\_InstrumentStringList\[i\]\],this);  
     QTreeWidgetItem\* subItem = new QTreeWidgetItem;  
     node->addChild(subItem);  
     setFirstItemColumnSpanned(subItem,true);  
     setItemWidget(subItem,,subTableView);

     int rowHeight = subTableView->verticalHeader()->defaultSectionSize();  
     node->setSizeHint(i,QSize(rowHeight,rowHeight));

/////////////--附注:
如果要让子tableview的宽度随着行数的变化而变化,却不会出现滚动条的话,应先将其滚动条关闭
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
然后在此treeWidget中,
int subTableItemHeight= subTableView->rowHeight();
int height = subTableItemHeight+subTableItemHeight*m_PositionItemListMap[m_PositionItemListMap.keys()[subIndex]].count();//算出子table的高度;
subTableView->setMaximumHeight(height);
subItem->setSizeHint(,QSize(subTableView->size().width(),height));//改变树节点的宽度
//这样,子表就能动态变化而不会高度太大或太小。
如果动态变化后发现要出现大小 变化后才能正常显示,可能如下
topLevelItem(parentIndex)->setExpanded(false);
topLevelItem(parentIndex)->setExpanded(true);
即先收起子Treewidgetitem,然后再展开。这只是一种强制其更新的方法。
////////////////

     node->setIcon(,QIcon(QPixmap("Fold.png")));  
     m\_IsFoldedList.append(true);

     int id = ;  
     while(id<columnNameCount)  
         node->setTextAlignment(id++,Qt::AlignCenter);

 }  
 connect(this,SIGNAL(itemClicked(QTreeWidgetItem\*,int)),this,SLOT(ChangeIconSlot(QTreeWidgetItem\*,int)));

}

InformationPositionTreeView::~InformationPositionTreeView()
{

}
void InformationPositionTreeView::mouseMoveEvent(QMouseEvent * event)
{
QModelIndex index = indexAt(event->pos());
if(index.isValid() && index.row()>=)
{
this->setSelection(visualRect(index),QItemSelectionModel::SelectCurrent);
}

}
void InformationPositionTreeView::ChangeIconSlot(QTreeWidgetItem * item, int column)
{
QIcon icon;
bool isNeedExpanded = true;
if(column== && item->parent()==nullptr)
{
if(m_IsFoldedList[column])
{
icon = QIcon(QPixmap("UnFold.png"));
isNeedExpanded = true;
}
else
{
icon = QIcon(QPixmap("Fold.png"));
isNeedExpanded = false;
}
item->setIcon(column,icon);
m_IsFoldedList.replace(column,!m_IsFoldedList[column]);
item->setExpanded(isNeedExpanded);
}
}
void InformationPositionTreeView::Init()
{
// this->setMouseTracking(true);
this->setFocusPolicy(Qt::NoFocus);
this->setSelectionBehavior(QAbstractItemView::SelectRows);
this->setSelectionMode(QAbstractItemView::SingleSelection);

 this->setEditTriggers(QAbstractItemView::NoEditTriggers);  
 this->setContextMenuPolicy(Qt::CustomContextMenu);

 QHeaderView\* headerView = new QHeaderView(Qt::Horizontal,this);  
 this->setHeader(headerView);  
 headerView->setStretchLastSection(true);  
 headerView->setDefaultAlignment(Qt::AlignCenter);  
 headerView->setSectionsClickable(true);  
 headerView->setSectionResizeMode(QHeaderView::ResizeToContents);

 this->setStyleSheet("QTreeView::branch {image:none;}");  

// this->setRootIsDecorated(false);
// this->setItemDelegateForColumn(0,);
}
void InformationPositionTreeView::InitPositionItemListMap(InformationPositionItem& infoItem)
{
QList positionItemList = infoItem.GetPositionItemList();
int count = positionItemList.count();
for(int i=;i<count;i++)
{
m_InstrumentStringList << positionItemList[i].GetInstrument();
}

 m\_InstrumentStringList.removeDuplicates();  
 int keyCount = m\_InstrumentStringList.count();  
 for(int i=;i<keyCount;i++)  
 {  
     QList<PositionItem> value;  
     for(int j=;j<count;j++)  
     {  
         if(positionItemList\[j\].GetInstrument()==m\_InstrumentStringList\[i\])  
             value.append(positionItemList\[j\]);  
     }  
     m\_PositionItemListMap.insert(m\_InstrumentStringList\[i\],value);  
 }

}
float InformationPositionTreeView::GetSumValue(const QList& positionItemList,const QString& itemName)
{
float sum = 0.0;
int count = positionItemList.count();
//…..

 return 2.01;  

}

======

InformationPositionTreeModel::InformationPositionTreeModel(InformationPositionItem& infoItem,QObject * parent):m_InformationPositionItem(infoItem),QAbstractItemModel(parent)
{

}

InformationPositionTreeModel::~InformationPositionTreeModel(void)
{
}

int InformationPositionTreeModel::rowCount(const QModelIndex &parent) const
{
return m_InformationPositionItem.GetPositionItemList().count();
}
int InformationPositionTreeModel::columnCount(const QModelIndex &parent) const
{
return m_InformationPositionItem.GetColumnNameList().count();
}
QVariant InformationPositionTreeModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();

 if(role==Qt::DisplayRole)  
 {  
     PositionItem item = m\_InformationPositionItem.GetPositionItemList()\[index.row()\];  
     switch (index.column())  
     {  
     case :  
         return "";  
     case :  
         return item.GetInstrument();  
     case :  
         return item.GetBuyLot();  
     case :  
         return item.GetAvgBuyPrice();  
     case :  
         return item.GetSellLot();  
     case :  
         return item.GetAvgSellPrice();  
     case :  
         return item.GetNet();  
     default:  
         return item.GetFloatingMap()\[headerData(index.column(),Qt::Horizontal,Qt::DisplayRole).toString()\];;  
     }  
 }  
 if(role==Qt::DecorationRole && index.column()==)  
 {  
     return     QIcon(QPixmap("Fold.png"));  
 }  
 if(role==Qt::TextAlignmentRole)  
 {  
     Qt::AlignCenter;  
 }  
 return QVariant();  

}
QVariant InformationPositionTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
return m_InformationPositionItem.GetColumnNameList()[section];
}
return QVariant();
}
Qt::ItemFlags InformationPositionTreeModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsSelectable;

return QAbstractItemModel::flags(index) | Qt::ItemIsSelectable;  

}
bool InformationPositionTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(!index.isValid())
return false;
return false;
}

QModelIndex InformationPositionTreeModel::parent(const QModelIndex & index) const
{
if(index.isValid())
return index.parent();
return QModelIndex();
}
QModelIndex InformationPositionTreeModel::index(int row, int column, const QModelIndex & parent) const
{
if(parent.isValid())
return parent.child(row,column);
return QModelIndex();
}