QTreeWidget里嵌套表格QTableView
1 InformationPositionSubTableView::InformationPositionSubTableView(QStringList& columnNameList,QList<PositionItem>& positionItemList,QWidget *parent) : m_ColumnNameList(columnNameList), m_PositionItemList(positionItemList),QTableView(parent) 2 { 3 m_InformationPositionSubTableModel = new InformationPositionSubTableModel(columnNameList,positionItemList); 4 this->setModel(m_InformationPositionSubTableModel); 5 6 this->setMouseTracking(true); 7 this->setFocusPolicy(Qt::NoFocus); 8 this->setGridStyle(Qt::NoPen); 9 this->setSelectionBehavior(QAbstractItemView::SelectItems); 10 this->setSelectionMode(QAbstractItemView::SingleSelection); 11 12 QHeaderView* headerView = new InformationPositionSubHeaderview(Qt::Horizontal,this); 13 headerView->setSectionsClickable(true); 14 this->setHorizontalHeader(headerView); 15 this->horizontalHeader()->setStretchLastSection(true); 16 this->verticalHeader()->setVisible(false); 17 18 this->setEditTriggers(QAbstractItemView::NoEditTriggers); 19 this->setContextMenuPolicy(Qt::CustomContextMenu); 20 21 this->resizeColumnsToContents(); 22 // this->resizeRowsToContents(); //不能加上,否则做为QTreeWidget的子控件会多出一行的间隙; 23 24 this->setFrameShape(QFrame::NoFrame); //设置成无边框; 25 26 this->horizontalHeader()->setStyleSheet("QHeaderView{background-color:gray;}"); //设置表头背景为灰色(这样也看起来扁平); 27 } 28 29 InformationPositionSubTableView::~InformationPositionSubTableView() 30 { 31 32 } 33 34 void InformationPositionSubTableView::mouseMoveEvent(QMouseEvent * event) 35 { 36 QModelIndex index = indexAt(event->pos()); 37 if(index.isValid() && index.row()>=0) 38 { 39 this->setSelection(visualRect(index),QItemSelectionModel::SelectCurrent); 40 } 41 42 } 43 44 ======== 45 46 InformationPositionSubTableModel::InformationPositionSubTableModel(QStringList& columnNameList,QList<PositionItem>& positionItemList,QObject *parent) : m_ColumnNameList(columnNameList),m_PositionItemList(positionItemList),QAbstractTableModel(parent) 47 { 48 this->m_ColumnNameList = columnNameList; 49 } 50 51 InformationPositionSubTableModel::~InformationPositionSubTableModel() 52 { 53 54 } 55 QVariant InformationPositionSubTableModel::data(const QModelIndex & index, int role) const 56 { 57 Q_UNUSED(index); 58 if(!index.isValid()) 59 return QVariant(); 60 61 if(role==Qt::DisplayRole) 62 { 63 PositionItem item = m_PositionItemList[index.row()]; 64 int column = index.column(); 65 switch (column) 66 { 67 case 0: 68 return item.GetAccountName(); 69 case 1: 70 return item.GetBuyLot(); 71 case 2: 72 return item.GetAvgBuyPrice(); 73 case 3: 74 return item.GetSellLot(); 75 case 4: 76 return item.GetAvgSellPrice(); 77 case 5: 78 return item.GetNet(); 79 default: 80 return item.GetFloatingMap()[headerData(column,Qt::Horizontal,Qt::DisplayRole).toString()]; 81 } 82 } 83 84 if(role==Qt::TextAlignmentRole) 85 { 86 return Qt::AlignCenter; 87 } 88 89 if(role==Qt::TextColorRole) 90 { 91 if(index.column()==3 || index.column()==5) 92 { 93 return QColor(Qt::red); 94 } 95 if(index.column()==1) 96 { 97 return QColor(Qt::green); 98 } 99 } 100 101 return QVariant(); 102 } 103 QVariant InformationPositionSubTableModel::headerData(int section, Qt::Orientation orientation, int role) const 104 { 105 if(role!=Qt::DisplayRole) 106 return QVariant(); 107 108 if(orientation == Qt::Horizontal) 109 { 110 return m_ColumnNameList[section]; 111 } 112 113 return QVariant(); 114 } 115 bool InformationPositionSubTableModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role) 116 { 117 if(role!=Qt::EditRole) 118 return false; 119 if(orientation == Qt::Horizontal && section >=7) 120 { 121 m_ColumnNameList.append(value.toString()); 122 emit headerDataChanged(orientation,section,section); 123 return true; 124 } 125 return false; 126 } 127 128 int InformationPositionSubTableModel::rowCount(const QModelIndex & parent) const 129 { 130 int rows = m_PositionItemList.count(); 131 return rows; 132 } 133 int InformationPositionSubTableModel::columnCount(const QModelIndex & parent) const 134 { 135 return m_ColumnNameList.count(); 136 } 137 bool InformationPositionSubTableModel::setData(const QModelIndex & index, const QVariant & value, int role) 138 { 139 Q_UNUSED(index); 140 if (index.isValid() && role == Qt::DisplayRole) 141 { 142 int row = index.row(); 143 m_PositionItemList.replace(row, m_UpdatingItem); 144 emit(dataChanged(index, index)); 145 } 146 return true; 147 } 148 Qt::ItemFlags InformationPositionSubTableModel::flags(const QModelIndex & index) const 149 { 150 Q_UNUSED(index); 151 if (!index.isValid()) 152 return Qt::ItemIsEditable; 153 154 return QAbstractTableModel::flags(index) | Qt::ItemIsEditable; 155 } 156 157 bool InformationPositionSubTableModel::insertRow(int position,const QModelIndex &index) 158 { 159 Q_UNUSED(index); 160 beginInsertRows(index, position, position); 161 162 int count = m_UpdatingItem.GetFloatingMap().count(); 163 QMapIterator<QString,float> it(m_UpdatingItem.GetFloatingMap()); 164 while(it.hasNext()) 165 { 166 it.next(); 167 this->AddHeaderSection(it.key()); 168 } 169 170 m_PositionItemList.insert(position,m_UpdatingItem); 171 endInsertRows(); 172 return true; 173 } 174 bool InformationPositionSubTableModel::removeRow(int position,const QModelIndex &index) 175 { 176 Q_UNUSED(index); 177 beginRemoveRows(index, position, position); 178 m_PositionItemList.removeAt(position); 179 endRemoveRows(); 180 return true; 181 } 182 void InformationPositionSubTableModel::AddHeaderSection(const QString& columnName) 183 { 184 if(!m_ColumnNameList.contains(columnName)) 185 { 186 setHeaderData(m_ColumnNameList.count(),Qt::Horizontal,Qt::EditRole); 187 m_ColumnNameList.append(columnName); 188 } 189 } 190 191 ===== 192 193 194 InformationPositionSubHeaderview::InformationPositionSubHeaderview(Qt::Orientation orientation,QWidget* parent) : QHeaderView(orientation,parent) 195 { 196 this->setSectionsClickable(false); 197 this->m_IsHided = false; 198 } 199 200 InformationPositionSubHeaderview::~InformationPositionSubHeaderview() 201 { 202 } 203 204 void InformationPositionSubHeaderview::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const 205 { 206 painter->save(); 207 QHeaderView::paintSection(painter, rect, logicalIndex); 208 painter->restore(); 209 210 if(logicalIndex==0 && m_IsHided==false) 211 { 212 painter->drawText(rect,Qt::AlignRight|Qt::AlignVCenter, "<<"); 213 } 214 215 if(logicalIndex==1 && m_IsHided==true) 216 { 217 QRect leftRect = QRect(rect.x(),rect.y(),HIDEDCOLORBTNWIDTH,rect.height()); 218 painter->setBrush(QBrush(Qt::blue)); 219 painter->drawRect(leftRect); 220 } 221 222 } 223 224 void InformationPositionSubHeaderview::mousePressEvent(QMouseEvent * event) 225 { 226 if(event->button()==Qt::LeftButton) 227 { 228 QFontMetrics fm(this->font()); 229 int textWidth = fm.width("<<"); 230 231 int index = logicalIndexAt(event->pos()); 232 int xPos =event->pos().x(); 233 int xLeft = sectionPosition(index)+sectionSize(index); 234 if(index==0 && m_IsHided==false && (xPos<xLeft-HIDEDCOLORBTNWIDTH && xPos>xLeft-textWidth) ) 235 { 236 setSectionHidden(index,true); 237 m_IsHided = true; 238 } 239 else if(index==1 && m_IsHided==true && xPos<=HIDEDCOLORBTNWIDTH) 240 { 241 setSectionHidden(index-1,false); 242 m_IsHided = false; 243 } 244 } 245 QHeaderView::mousePressEvent(event); 246 } 247 248 ====== 249 250 InformationPositionTreeView::InformationPositionTreeView(InformationPositionItem& infoItem,QWidget *parent) : QTreeWidget(parent) 251 { 252 m_SubColumnNameList = infoItem.GetColumnNameList(); 253 m_SubColumnNameList.removeAt(0); 254 m_SubColumnNameList.replace(0,"Account ");//多出四个空格,是为"<<"腾出空间; 255 256 this->Init(); 257 this->InitPositionItemListMap(infoItem); 258 259 int columnNameCount = infoItem.GetColumnNameList().count(); 260 this->setHeaderLabels(infoItem.GetColumnNameList()); //增加标题; 261 262 int count = m_InstrumentStringList.count(); 263 for(int i=0;i<count;i++) 264 { 265 QList<PositionItem> positionItemList = m_PositionItemListMap[m_InstrumentStringList[i]]; 266 QStringList summaryList; 267 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")) ; 268 QTreeWidgetItem* node = new QTreeWidgetItem(summaryList); 269 this->addTopLevelItem(node); 270 271 InformationPositionSubTableView* subTableView = new InformationPositionSubTableView(m_SubColumnNameList,m_PositionItemListMap[m_InstrumentStringList[i]],this); 272 QTreeWidgetItem* subItem = new QTreeWidgetItem; 273 node->addChild(subItem); 274 setFirstItemColumnSpanned(subItem,true); 275 setItemWidget(subItem,0,subTableView); 276 277 int rowHeight = subTableView->verticalHeader()->defaultSectionSize(); 278 node->setSizeHint(i,QSize(rowHeight,rowHeight)); 279 280 /////////////--附注: 281 如果要让子tableview的宽度随着行数的变化而变化,却不会出现滚动条的话,应先将其滚动条关闭 282 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 283 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 284 然后在此treeWidget中, 285 int subTableItemHeight= subTableView->rowHeight(0); 286 int height = subTableItemHeight+subTableItemHeight*m_PositionItemListMap[m_PositionItemListMap.keys()[subIndex]].count();//算出子table的高度; 287 subTableView->setMaximumHeight(height); 288 subItem->setSizeHint(0,QSize(subTableView->size().width(),height));//改变树节点的宽度 289 //这样,子表就能动态变化而不会高度太大或太小。 290 如果动态变化后发现要出现大小 变化后才能正常显示,可能如下 291 topLevelItem(parentIndex)->setExpanded(false); 292 topLevelItem(parentIndex)->setExpanded(true); 293 即先收起子Treewidgetitem,然后再展开。这只是一种强制其更新的方法。 294 //////////////// 295 296 297 node->setIcon(0,QIcon(QPixmap("Fold.png"))); 298 m_IsFoldedList.append(true); 299 300 int id = 0; 301 while(id<columnNameCount) 302 node->setTextAlignment(id++,Qt::AlignCenter); 303 304 } 305 connect(this,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(ChangeIconSlot(QTreeWidgetItem*,int))); 306 307 } 308 309 InformationPositionTreeView::~InformationPositionTreeView() 310 { 311 312 } 313 void InformationPositionTreeView::mouseMoveEvent(QMouseEvent * event) 314 { 315 QModelIndex index = indexAt(event->pos()); 316 if(index.isValid() && index.row()>=0) 317 { 318 this->setSelection(visualRect(index),QItemSelectionModel::SelectCurrent); 319 } 320 321 } 322 void InformationPositionTreeView::ChangeIconSlot(QTreeWidgetItem * item, int column) 323 { 324 QIcon icon; 325 bool isNeedExpanded = true; 326 if(column==0 && item->parent()==nullptr) 327 { 328 if(m_IsFoldedList[column]) 329 { 330 icon = QIcon(QPixmap("UnFold.png")); 331 isNeedExpanded = true; 332 } 333 else 334 { 335 icon = QIcon(QPixmap("Fold.png")); 336 isNeedExpanded = false; 337 } 338 item->setIcon(column,icon); 339 m_IsFoldedList.replace(column,!m_IsFoldedList[column]); 340 item->setExpanded(isNeedExpanded); 341 } 342 } 343 void InformationPositionTreeView::Init() 344 { 345 // this->setMouseTracking(true); 346 this->setFocusPolicy(Qt::NoFocus); 347 this->setSelectionBehavior(QAbstractItemView::SelectRows); 348 this->setSelectionMode(QAbstractItemView::SingleSelection); 349 350 this->setEditTriggers(QAbstractItemView::NoEditTriggers); 351 this->setContextMenuPolicy(Qt::CustomContextMenu); 352 353 QHeaderView* headerView = new QHeaderView(Qt::Horizontal,this); 354 this->setHeader(headerView); 355 headerView->setStretchLastSection(true); 356 headerView->setDefaultAlignment(Qt::AlignCenter); 357 headerView->setSectionsClickable(true); 358 headerView->setSectionResizeMode(QHeaderView::ResizeToContents); 359 360 361 362 this->setStyleSheet("QTreeView::branch {image:none;}"); 363 // this->setRootIsDecorated(false); 364 // this->setItemDelegateForColumn(0,); 365 } 366 void InformationPositionTreeView::InitPositionItemListMap(InformationPositionItem& infoItem) 367 { 368 QList<PositionItem> positionItemList = infoItem.GetPositionItemList(); 369 int count = positionItemList.count(); 370 for(int i=0;i<count;i++) 371 { 372 m_InstrumentStringList << positionItemList[i].GetInstrument(); 373 } 374 375 m_InstrumentStringList.removeDuplicates(); 376 int keyCount = m_InstrumentStringList.count(); 377 for(int i=0;i<keyCount;i++) 378 { 379 QList<PositionItem> value; 380 for(int j=0;j<count;j++) 381 { 382 if(positionItemList[j].GetInstrument()==m_InstrumentStringList[i]) 383 value.append(positionItemList[j]); 384 } 385 m_PositionItemListMap.insert(m_InstrumentStringList[i],value); 386 } 387 388 } 389 float InformationPositionTreeView::GetSumValue(const QList<PositionItem>& positionItemList,const QString& itemName) 390 { 391 float sum = 0.0; 392 int count = positionItemList.count(); 393 //..... 394 395 return 2.01; 396 } 397 398 ====== 399 400 InformationPositionTreeModel::InformationPositionTreeModel(InformationPositionItem& infoItem,QObject * parent):m_InformationPositionItem(infoItem),QAbstractItemModel(parent) 401 { 402 403 } 404 405 InformationPositionTreeModel::~InformationPositionTreeModel(void) 406 { 407 } 408 409 int InformationPositionTreeModel::rowCount(const QModelIndex &parent) const 410 { 411 return m_InformationPositionItem.GetPositionItemList().count(); 412 } 413 int InformationPositionTreeModel::columnCount(const QModelIndex &parent) const 414 { 415 return m_InformationPositionItem.GetColumnNameList().count(); 416 } 417 QVariant InformationPositionTreeModel::data(const QModelIndex &index, int role) const 418 { 419 if(!index.isValid()) 420 return QVariant(); 421 422 423 424 425 if(role==Qt::DisplayRole) 426 { 427 PositionItem item = m_InformationPositionItem.GetPositionItemList()[index.row()]; 428 switch (index.column()) 429 { 430 case 0: 431 return ""; 432 case 1: 433 return item.GetInstrument(); 434 case 2: 435 return item.GetBuyLot(); 436 case 3: 437 return item.GetAvgBuyPrice(); 438 case 4: 439 return item.GetSellLot(); 440 case 5: 441 return item.GetAvgSellPrice(); 442 case 6: 443 return item.GetNet(); 444 default: 445 return item.GetFloatingMap()[headerData(index.column(),Qt::Horizontal,Qt::DisplayRole).toString()];; 446 } 447 } 448 if(role==Qt::DecorationRole && index.column()==0) 449 { 450 return QIcon(QPixmap("Fold.png")); 451 } 452 if(role==Qt::TextAlignmentRole) 453 { 454 Qt::AlignCenter; 455 } 456 return QVariant(); 457 } 458 QVariant InformationPositionTreeModel::headerData(int section, Qt::Orientation orientation, int role) const 459 { 460 if(orientation == Qt::Horizontal && role == Qt::DisplayRole) 461 { 462 return m_InformationPositionItem.GetColumnNameList()[section]; 463 } 464 return QVariant(); 465 } 466 Qt::ItemFlags InformationPositionTreeModel::flags(const QModelIndex &index) const 467 { 468 if (!index.isValid()) 469 return Qt::ItemIsSelectable; 470 471 return QAbstractItemModel::flags(index) | Qt::ItemIsSelectable; 472 } 473 bool InformationPositionTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) 474 { 475 if(!index.isValid()) 476 return false; 477 return false; 478 } 479 480 QModelIndex InformationPositionTreeModel::parent(const QModelIndex & index) const 481 { 482 if(index.isValid()) 483 return index.parent(); 484 return QModelIndex(); 485 } 486 QModelIndex InformationPositionTreeModel::index(int row, int column, const QModelIndex & parent) const 487 { 488 if(parent.isValid()) 489 return parent.child(row,column); 490 return QModelIndex(); 491 }