QTableView使用自定义委托(QItemDelegate)
需要在表格中绘制流程图,主要有箭头,方向,颜色,字符串,由于QTableView没有可用的绘制函数,所以需要自己去定义、
委托(delegate)继承QItemDelegate,模型(model)继承QAbstractTableModel,表头(headerview)继承QHeaderView,表(table)继承QTableView
这里只实现绘制显示功能,如果需要进行编辑还需另外重写createEditor setEditorData setModelData 函数
如下是实现效果图
1 /********************ArrowDelegate********************/ 2 class ArrowDelegate : public QItemDelegate 3 { 4 Q_OBJECT 5 6 public: 7 8 ArrowDelegate(QObject* parent = 0); 9 virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; 10 11 protected: 12 13 private: 14 }; 15 16 /********************TableModel********************/ 17 class TableModel : public QAbstractTableModel 18 { 19 Q_OBJECT 20 21 public: 22 23 TableModel(QObject *parent = 0); 24 ~TableModel(void); 25 void setHorizontalHeaderList(QStringList horizontalHeaderList); 26 void setVerticalHeaderList(QStringList verticalHeaderList); 27 int rowCount(const QModelIndex &parent = QModelIndex()) const; 28 int columnCount(const QModelIndex &parent = QModelIndex()) const; 29 QVariant data(const QModelIndex &index, int role) const; 30 QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; 31 Qt::ItemFlags flags(const QModelIndex &index) const; 32 void setModalDatas(QList< QStringList > *rowlist); 33 void refrushModel(); 34 35 protected: 36 37 signals: 38 39 void updateCount(int count); 40 41 private: 42 43 QStringList horizontal_header_list; 44 QStringList vertical_header_list; 45 QList< QStringList > *arr_row_list; 46 47 }; 48 49 class MyHeader : public QHeaderView 50 { 51 Q_OBJECT 52 53 public: 54 MyHeader(QWidget *parent = 0);//:QHeaderView(Qt::Horizontal, parent) 55 56 protected: 57 void mouseReleaseEvent(QMouseEvent *e); 58 59 signals: 60 void refresh(); 61 }; 62 /********************ReadOnlyTableView********************/ 63 class MyTableView : public QTableView 64 { 65 Q_OBJECT 66 67 public: 68 69 MyTableView(QWidget *parent=0); 70 ~MyTableView(void); 71 void addRow(QStringList rowList); 72 void clearAllRow(int row);//数据清空 73 int rowCount(); 74 75 public slots: 76 77 void remove(); 78 void clear(); 79 void changeValue(); 80 void refreshmymodel(); 81 82 void mouseReleaseEvent(QMouseEvent *event); 83 private: 84 85 void initHeader(); 86 87 private: 88 MyHeader *myheader; 89 TableModel *mymodel; 90 QList< QStringList > grid_data_list; 91 ArrowDelegate *arrow_delegate; 92 int row; 93 signals: 94 95 void updateCount(int count); 96 };
1 #include "tableview.h" 2 #include "math.h" 3 #include <QApplication> 4 #include <QPen> 5 6 int g_x; 7 /********************ArrowDelegate********************/ 8 ArrowDelegate::ArrowDelegate(QObject *parent) 9 : QItemDelegate(parent) 10 { 11 g_x = 0; 12 } 13 14 void ArrowDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const 15 { 16 int row = index.row(); 17 int x = option.rect.x(); 18 int y = option.rect.y(); 19 int width = option.rect.width(); 20 int height = option.rect.height(); 21 QPen pen_black; 22 pen_black.setWidth(2); 23 pen_black.setColor(QColor(Qt::black)); 24 QStyleOptionViewItem myOption = option; 25 26 if (index.column() == 2)//UE 27 { 28 QPainterPath path_UE; 29 30 QPoint One; 31 QPoint Two; 32 // pen.setWidth(2); 33 One.setX(x + width / 2); 34 One.setY(y); 35 Two.setX(x + width / 2); 36 Two.setY(y + height); 37 path_UE.moveTo(One); 38 path_UE.lineTo(Two); 39 painter->setPen(pen_black); 40 painter->drawPath(path_UE); 41 } 42 43 if (index.column() == 3) 44 { 45 g_x = x + width / 2;//get the begin 46 QPainterPath path_SENB; 47 48 QPoint One; 49 QPoint Two; 50 One.setX(x + width / 2); 51 One.setY(y); 52 Two.setX(x + width / 2); 53 Two.setY(y + height); 54 path_SENB.moveTo(One); 55 path_SENB.lineTo(Two); 56 // pen.setColor(QColor(Qt::black)); 57 painter->setPen(pen_black); 58 painter->drawPath(path_SENB); 59 // g_y = y + height / 2; 60 } 61 if (index.column() == 4) 62 { 63 QString str4 = index.model()->data(index,Qt::DisplayRole).toString(); 64 if (!str4.isEmpty()) 65 { 66 QPainterPath path_TENB; 67 68 QPoint One; 69 QPoint Two; 70 // pen.setWidth(2); 71 One.setX(x + width / 2); 72 One.setY(y); 73 Two.setX(x + width / 2); 74 Two.setY(y + height); 75 path_TENB.moveTo(One); 76 path_TENB.lineTo(Two); 77 painter->setPen(pen_black); 78 painter->drawPath(path_TENB); 79 } 80 } 81 82 if (index.column() == 5) 83 { 84 QPainterPath path,path_SMME; 85 QPen pen; 86 QPoint One; 87 QPoint Two; 88 // pen5.setWidth(2); 89 One.setX(x + width / 2); 90 One.setY(y); 91 Two.setX(x + width / 2); 92 Two.setY(y + height); 93 path_SMME.moveTo(One); 94 path_SMME.lineTo(Two); 95 // pen5.setColor(QColor(Qt::black)); 96 painter->setPen(pen_black); 97 painter->drawPath(path_SMME); 98 99 QString str = index.model()->data(index,Qt::DisplayRole).toString(); 100 if (str.isEmpty()) 101 return;//break this turn 102 QStringList strList = str.split("+"); 103 QString text = strList.at(0); 104 int direction = strList.at(1).toInt(); 105 106 myOption.displayAlignment = Qt::AlignCenter; 107 108 QRectF rect; 109 pen.setWidth(1); 110 if (direction) 111 { 112 pen.setColor(QColor(255,0,0));//red 113 // One.setX(x); 114 // One.setY(y + 3 * height / 4); 115 One.setX(g_x); 116 One.setY(y + 3 * height / 4); 117 Two.setX(x + width / 2); 118 Two.setY(y + 3 * height / 4); 119 // painter->drawText(One,text); 120 } 121 else 122 { 123 pen.setColor(QColor(0,0,255)); 124 // Two.setX(x); 125 // Two.setY(y + 3 * height / 4); 126 Two.setX(g_x); 127 Two.setY(y + 3 * height / 4); 128 One.setX(x + width / 2); 129 One.setY(y + 3 * height / 4); 130 // painter->drawText(Two,text); 131 } 132 133 int Height = 20; 134 // QPoint Three(x + width / 2 , y + height / 3); 135 136 double slopy , cosy , siny; 137 double Par = Height/2; 138 slopy = atan2( ( One.y() - Two.y() ),( One.x() - Two.x() ) ); 139 cosy = cos( slopy ); 140 siny = sin( slopy ); 141 142 143 path.moveTo(One); 144 path.lineTo(Two); 145 146 147 path.moveTo(Two); 148 path.lineTo(Two.x() + int( Par * cosy - ( Par / 2.0 * siny ) ), 149 Two.y() + int( Par * siny + ( Par / 2.0 * cosy ) ) ); 150 path.moveTo(Two); 151 path.lineTo(Two.x() + int( Par * cosy - ( Par / 2.0 * siny ) ), 152 Two.y() - int( Par * siny + ( Par / 2.0 * cosy ) ) ); 153 154 painter->setPen(pen); 155 painter->drawPath(path); 156 157 // pen.setColor(QColor(Qt::black)); 158 painter->setPen(pen_black); 159 rect.setTopLeft(QPointF(g_x,y)); 160 rect.setBottomRight(QPointF(x + width / 2,y + height / 2)); 161 // rect(QPointF(g_x,y),QPointF(x + width / 2,y + height / 2)); 162 QTextOption textOption; 163 textOption.setAlignment(Qt::AlignCenter); 164 painter->drawText(rect,text,textOption); 165 } 166 else 167 { 168 return QItemDelegate::paint (painter, option, index); 169 } 170 } 171 172 /********************TableModel********************/ 173 TableModel::TableModel(QObject *parent) 174 : QAbstractTableModel(parent), arr_row_list(NULL) 175 { 176 177 } 178 179 TableModel::~TableModel(void) 180 { 181 arr_row_list = NULL; 182 } 183 184 void TableModel::setHorizontalHeaderList(QStringList horizontalHeaderList) 185 { 186 horizontal_header_list = horizontalHeaderList; 187 } 188 189 void TableModel::setVerticalHeaderList(QStringList verticalHeaderList) 190 { 191 vertical_header_list = verticalHeaderList; 192 } 193 194 int TableModel::rowCount(const QModelIndex &parent) const 195 { 196 if(vertical_header_list.size() > 0) 197 return vertical_header_list.size(); 198 199 if(NULL == arr_row_list) 200 return 0; 201 else 202 return arr_row_list->size(); 203 } 204 205 int TableModel::columnCount(const QModelIndex &parent) const 206 { 207 if(horizontal_header_list.size() > 0) 208 return horizontal_header_list.size(); 209 210 if(NULL == arr_row_list) 211 return 0; 212 else if(arr_row_list->size() < 1) 213 return 0; 214 else 215 return arr_row_list->at(0).size(); 216 } 217 218 QVariant TableModel::data(const QModelIndex &index, int role) const 219 { 220 if (!index.isValid()) 221 return QVariant(); 222 223 if(NULL == arr_row_list) 224 return QVariant(); 225 226 if(arr_row_list->size() < 1) 227 return QVariant(); 228 229 if (role == Qt::TextAlignmentRole) 230 { 231 return int(Qt::AlignLeft | Qt::AlignVCenter); 232 } 233 else if (role == Qt::DisplayRole) 234 { 235 if(index.row() >= arr_row_list->size()) 236 return QVariant(); 237 if(index.column() >= arr_row_list->at(0).size()) 238 return QVariant(); 239 return arr_row_list->at(index.row()).at(index.column()); 240 } 241 return QVariant(); 242 } 243 244 QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const 245 { 246 if(role==Qt::DisplayRole) 247 { 248 if(orientation==Qt::Horizontal) 249 { 250 if(horizontal_header_list.size() > section) 251 return horizontal_header_list[section]; 252 else 253 return QVariant(); 254 } 255 else 256 { 257 if(vertical_header_list.size() > section) 258 return vertical_header_list[section]; 259 else 260 return QVariant(); 261 } 262 } 263 264 return QVariant(); 265 } 266 267 Qt::ItemFlags TableModel::flags(const QModelIndex &index) const 268 { 269 if (!index.isValid()) 270 return Qt::NoItemFlags; 271 272 Qt::ItemFlags flag = QAbstractItemModel::flags(index); 273 274 // flag|=Qt::ItemIsEditable 275 return flag; 276 } 277 278 void TableModel::setModalDatas(QList< QStringList > *rowlist) 279 { 280 arr_row_list = rowlist; 281 } 282 283 void TableModel::refrushModel() 284 { 285 beginResetModel(); 286 endResetModel(); 287 288 emit updateCount(this->rowCount(QModelIndex())); 289 } 290 291 /********************TableView********************/ 292 MyTableView::MyTableView(QWidget *parent) 293 : QTableView(parent) 294 { 295 this->setAlternatingRowColors(true); 296 // this->setStyleSheet( "QTableView{background-color: rgb(250, 250, 115);" 297 // "alternate-background-color: rgb(141, 163, 215);}" );//???? 298 this->setSelectionBehavior(QAbstractItemView::SelectRows); 299 this->horizontalHeader()->setStretchLastSection(true); 300 this->horizontalHeader()->setHighlightSections(false); 301 this->verticalHeader()->setVisible(false); 302 this->setShowGrid(false); 303 this->setEditTriggers(QAbstractItemView::NoEditTriggers); 304 this->setSelectionMode(QAbstractItemView::ExtendedSelection); 305 306 307 mymodel = new TableModel(); 308 this->setModel(mymodel); 309 myheader = new MyHeader; 310 myheader->setModel(mymodel); 311 this->setHorizontalHeader(myheader); 312 313 this->initHeader(); 314 mymodel->setModalDatas(&grid_data_list); 315 arrow_delegate = new ArrowDelegate(); 316 this->setItemDelegate(arrow_delegate); 317 318 319 connect(mymodel, SIGNAL(updateCount(int)), this, SLOT(updateCount(int ))); 320 connect(myheader,SIGNAL(refresh()),this,SLOT(refreshmymodel())); 321 322 } 323 324 MyTableView::~MyTableView(void) 325 { 326 if(arrow_delegate) { 327 delete arrow_delegate; 328 arrow_delegate = NULL; 329 } 330 331 if(mymodel) { 332 delete mymodel; 333 mymodel = NULL; 334 } 335 grid_data_list.clear(); 336 } 337 338 void MyTableView::addRow(QStringList rowList) 339 { 340 grid_data_list.append(rowList); 341 mymodel->refrushModel(); 342 } 343 344 void MyTableView::clearAllRow(int row) 345 { 346 this->row = row; 347 grid_data_list.clear(); 348 mymodel->refrushModel(); 349 } 350 351 void MyTableView::remove() 352 { 353 QModelIndexList model_index_list = this->selectedIndexes(); 354 int model_count = model_index_list.count(); 355 if(model_count <= 0) 356 return; 357 358 QList<int> list_row; 359 for(int i=model_count-1; i>=0; i--) 360 { 361 QModelIndex model_index = model_index_list.at(i); 362 int row = model_index.row(); 363 if(!list_row.contains(row)) 364 list_row.append(row); 365 } 366 367 if(list_row.isEmpty()) 368 return; 369 370 qSort(list_row); 371 372 for(int i=list_row.count()-1; i>=0; i--) 373 { 374 grid_data_list.removeAt(list_row.at(i)); 375 } 376 377 mymodel->refrushModel(); 378 } 379 380 void MyTableView::clear() 381 { 382 grid_data_list.clear(); 383 mymodel->refrushModel(); 384 } 385 386 int MyTableView::rowCount() 387 { 388 return mymodel->rowCount(QModelIndex()); 389 } 390 391 void MyTableView::initHeader() 392 { 393 QStringList header; 394 header<<"NO"<<"Time"<<"UE"<<"S-ENB"<<"T-ENB"<<"S-MME"<<"T-MME"<<"SGSN" 395 <<"S-SGW"<<"T-SGW"<<"PGW/GGSN"<<"HSS/EIR"<<"PCRF"<<"AAA/ALP"<<"AF"; 396 mymodel->setHorizontalHeaderList(header); 397 // MyHeader *h = new MyHeader(this->horizontalHeader()); 398 399 } 400 401 402 void MyTableView::refreshmymodel() 403 { 404 mymodel->refrushModel(); 405 } 406 407 408 MyHeader::MyHeader(QWidget *parent):QHeaderView(Qt::Horizontal, parent) 409 { 410 411 } 412 413 void MyHeader::mouseReleaseEvent(QMouseEvent *e) 414 { 415 emit refresh(); 416 }
通过全局变量保存箭头的左边点,函数计算箭头的头部画线路径。因为需要实现拖动表头列宽,改变对应表格项的宽度,所以需要触发表头的mouserelease事件,即鼠标释放,表格中的内容动态变化