https://blog.youkuaiyun.com/hu_linux/article/details/52791665
该链接也有自定义控件用法,比较好看
QT的MVC(View/Delegate)模型十分强大,可以利用各种控件来对表格的输入进行限制。
思路:
1:为每一列定义委托:
A:第一列是编号列,使用只读委托,令该列的单元格是只读的
B:第三列是ID列,只能输入1-12个数字,利用QLineEdit委托和正则表达式对输入进行限制
C:第四年龄列,利用QSpinBox委托进行输入限制,只能输入1-100之间的数字
D:第五列是性别列,利用QComboBox委托对输入进行限制,该列的单元格只能输入Male或Female
E:第六列是头像列,在该列的单元格中央放置一张头像
2:定义代理类,把所有单元格中的字符居中显示。
3:利用QSS,将表格的背景色弄成黄蓝相间。
截图:
上代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
|
QTableView、QStandardItemModel/QAbstractItemModel 、QStyledItemDelegate/QItemDelegate和QModelIndex;
先上图看效果吧
选择文件按钮这一列,第0行是点击后进入编辑模式时显示按钮的情况。
下面一行是显示的选择文件的全路径。
第2行”C:“是初始化时设置的值,只是为了测试显示。
最后一行是没有选择文件。
我实现的这个SelectFileButton办法:
QPushButton;
SelectFileButton里实现一个槽函数:功能,点击时选择文件并返回路径。
cQItemDelegate;
d、然后再重写createEditor();返回SelectFileButton的指针
e、重写setModelData()、setEditorData(); 设置模型数据和设置编辑数据的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
|
通过painter画自定义控件
QStyleOption子类:
QStyleOptionButton, QStyleOptionComplex, QStyleOptionDockWidget, QStyleOptionFocusRect, QStyleOptionFrame, QStyleOptionGraphicsItem, QStyleOptionHeader, QStyleOptionMenuItem, QStyleOptionProgressBar, QStyleOptionRubberBand, QStyleOptionTab, QStyleOptionTabBarBase, QStyleOptionTabWidgetFrame, QStyleOptionToolBar, QStyleOptionToolBox, and QStyleOptionViewItem
一 、painter 自定义进度条
//自定义进度条 BarDelegate::BarDelegate( QObject *parent ) : QAbstractItemDelegate( parent ) { } void BarDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const { if( option.state & QStyle::State_Selected ) painter->fillRect( option.rect, option.palette.highlight() ); // 数据是存储在QStandardItemModel的QStandardItem,会自动根据当前行进行匹配(我认为) int value = index.model()->data( index, Qt::DisplayRole ).toInt(); // 这句,取得当前行的数据 qDebug() << value; double factor = double(value)/100.0; // 计算比例因子 painter->save(); // 保存旧画板(我认为) // 进度条背景色 if( factor > 0.8 ) { painter->setBrush( Qt::red ); // 超过0.8画纯红色 factor = 1; } else painter->setBrush( QColor( 0, int(factor*255), 255-int(factor*255) ) ); // 否则颜色依次变淡 int n = factor*100; QString str1 = QString("%1\%").arg(n); painter->setPen( Qt::red ); // 画笔颜色(这里没用到,我认为) // 前面都是准备工作,这里才是真正画进度条 painter->drawRect( option.rect.x()+2, option.rect.y()+2, int(factor*(option.rect.width()-5)), option.rect.height()-5 ); painter->drawText(option.rect.x()+int(factor*(option.rect.width()))+2, option.rect.y()+option.rect.height()/2, str1); painter->restore(); // 恢复新画板(我认为) } QSize BarDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const { return QSize( 45, 15 ); // 随便改,不影响(我认为) }
class BarDelegate : public QAbstractItemDelegate { public: BarDelegate( QObject *parent = 0 ); // 覆盖两个函数就可以显示进度条 void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const; QSize sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const; };
1 painter进度条 QStyleOptionProgressBar
void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if(index.column() == 0) { int value = index.model()->data(index).toInt(); QStyleOptionProgressBarV2 progressBarOption; progressBarOption.rect = option.rect.adjusted(4, 4, -4, -4); progressBarOption.minimum = 0; progressBarOption.maximum = 100; progressBarOption.textAlignment = Qt::AlignRight; progressBarOption.textVisible = true; progressBarOption.progress = value; progressBarOption.text = tr("%1%").arg(progressBarOption.progress); painter->save(); if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); painter->setBrush(option.palette.highlightedText()); } QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); painter->restore(); } else { return QItemDelegate::paint (painter, option, index); } }
二、painter自定义按钮 QStyTableViewDelegate::TableViewDelegate(int z_Column, int z_NumberButtons,QWidget *parent)
: QStyledItemDelegate(parent), m_pOpenButton(new QPushButton()), m_pDeleteButton(new QPushButton()), m_nSpacing(5), m_nWidth(25), m_nHeight(20), m_Column(z_Column), m_NumberButtons(z_NumberButtons) {if (2 == m_NumberButtons) { m_list << QStringLiteral("编辑按钮") << QStringLiteral("删除按钮"); } // 设置按钮正常、划过、按下样式 QString z_Path = QCoreApplication::applicationDirPath(); m_pOpenButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url("+z_Path+"/res/system.png);} \ QPushButton:hover {image:url("+z_Path+"/res/system.png);} \ QPushButton:pressed {image:url("+z_Path+"/res/system.png);}"); m_pDeleteButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url("+z_Path+"/res/delete.png);} \ QPushButton:hover {image:url("+z_Path+"/res/delete.png);} \ QPushButton:pressed {image:url("+z_Path+"/res/delete.png);}"); } TableViewDelegate::~TableViewDelegate() { } // 绘制按钮 void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem viewOption(option); initStyleOption(&viewOption, index); if (option.state.testFlag(QStyle::State_HasFocus)) viewOption.state = viewOption.state ^ QStyle::State_HasFocus; QStyledItemDelegate::paint(painter, viewOption, index); if (index.column() == m_Column) { // 计算按钮显示区域 int nCount = m_list.count(); int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2; int nTop = (option.rect.height() - m_nHeight) / 2; for (int i = 0; i < nCount; ++i) { // 绘制按钮 QStyleOptionButton button; button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i, option.rect.top() + nTop, m_nWidth, m_nHeight); button.state |= QStyle::State_Enabled; button.iconSize = QSize(20, 20); if (button.rect.contains(m_mousePoint)) { if (m_nType == 0) { button.state |= QStyle::State_MouseOver; //button.icon = QIcon(QString(":/Images/%1Hover").arg(m_list.at(i))); } else if (m_nType == 1) { button.state |= QStyle::State_Sunken; //button.icon = QIcon(QString(":/Images/%1Pressed").arg(m_list.at(i))); } } //QWidget *pWidget = m_pOpenButton.data(); QWidget *pWidget = (i == 0) ? m_pOpenButton.data() : m_pDeleteButton.data(); pWidget->style()->drawControl(QStyle::CE_PushButton, &button, painter, pWidget); } } } // 响应按钮事件 - 划过、按下 bool TableViewDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { if (index.column() != m_Column) return false; m_nType = -1; bool bRepaint = false; QMouseEvent *pEvent = static_cast<QMouseEvent *> (event); m_mousePoint = pEvent->pos(); int nCount = m_list.count(); int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2; int nTop = (option.rect.height() - m_nHeight) / 2; // 还原鼠标样式 QApplication::restoreOverrideCursor(); for (int i = 0; i < nCount; ++i) { QStyleOptionButton button; button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i, option.rect.top() + nTop, m_nWidth, m_nHeight); // 鼠标位于按钮之上 if (!button.rect.contains(m_mousePoint)) continue; bRepaint = true; switch (event->type()) { // 鼠标滑过 case QEvent::MouseMove: { // 设置鼠标样式为手型 //QApplication::setOverrideCursor(Qt::PointingHandCursor); m_nType = 0; QToolTip::showText(pEvent->globalPos(), m_list.at(i)); break; } // 鼠标按下 case QEvent::MouseButtonPress: { m_nType = 1; break; } // 鼠标释放 case QEvent::MouseButtonRelease: { if (i == 0) { emit EditData(index); } else { emit deleteData(index); } break; } default: break; } } return bRepaint; }
三 painter 设置图片
void ItemdelegateTest::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem viewOption(option); if (viewOption.state & QStyle::State_HasFocus) { viewOption.state = viewOption.state ^ QStyle::State_HasFocus; } QStyledItemDelegate::paint(painter, viewOption, index); int height = (viewOption.rect.height()) / 2; QPixmap pixmap = QPixmap(":/check.png"); //QPixmap pixmap = QPixmap("E:/qt/QtDelegateTestT/zhj.png"); QRect DrawRect = QRect(viewOption.rect.left() + viewOption.rect.width() - 30, viewOption.rect.top() + height, 9, 9); painter->drawPixmap(DrawRect, pixmap); } bool ItemdelegateTest::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { int height = (option.rect.height()) / 2; QRect DrawRect = QRect(option.rect.left() + option.rect.width() - 30, option.rect.top() + height, 9, 9); //QMouseEvent *mouseEvent = static_cast(event); QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if (event->type() == QEvent::MouseButtonPress && DrawRect.contains(mouseEvent->pos())) { emit deleteItem(index); } if (event->type() == QEvent::MouseMove && DrawRect.contains(mouseEvent->pos())) { QCursor cursor(Qt::PointingHandCursor); QApplication::setOverrideCursor(cursor); QToolTip::showText(mouseEvent->globalPos(), "删除"); } else { QCursor cursor(Qt::ArrowCursor); QApplication::setOverrideCursor(cursor); } return QStyledItemDelegate::editorEvent(event, model, option, index); }
panier绘制checkbox
CheckBoxDelegate::CheckBoxDelegate(QObject *parent) : QStyledItemDelegate(parent) { } CheckBoxDelegate::~CheckBoxDelegate() { } // 绘制复选框 void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem viewOption(option); initStyleOption(&viewOption, index); if (option.state.testFlag(QStyle::State_HasFocus)) viewOption.state = viewOption.state ^ QStyle::State_HasFocus; QStyledItemDelegate::paint(painter, viewOption, index); if (index.column() == CHECK_BOX_COLUMN) { bool data = index.model()->data(index, Qt::UserRole).toBool(); QStyleOptionButton checkBoxStyle; checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off; checkBoxStyle.state |= QStyle::State_Enabled; checkBoxStyle.iconSize = QSize(20, 20); checkBoxStyle.rect = option.rect; QCheckBox checkBox; QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox); } } // 响应鼠标事件,更新数据 bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { QRect decorationRect = option.rect; QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos())) { if (index.column() == CHECK_BOX_COLUMN) { bool data = model->data(index, Qt::UserRole).toBool(); model->setData(index, !data, Qt::UserRole); } } return QStyledItemDelegate::editorEvent(event, model, option, index); } --------------------- 作者:一去丶二三里 来源:优快云 原文:https://blog.youkuaiyun.com/liang19890820/article/details/50721200 版权声明:本文为博主原创文章,转载请附上博文链接!