QT’s MVC (View/Delegate) model is very powerful and can use various controls to limit table input.
Idea:
1: Define delegates for each column:
A: The first column is the number column. Use a read-only delegate to make the cells in this column read-only.
B: The third column is the ID column. Only 1-12 numbers can be entered. QLineEdit delegates and regular expressions are used to limit the input.
C: The fourth age column, use QSpinBox delegation to limit the input. Only numbers between 1 and 100 can be entered.
D: The fifth column is the gender column. Use the QComboBox delegate to limit the input. The cells in this column can only enter Male or Female.
E: The sixth column is the avatar column. Place an avatar in the center of the cell in this column.
2: Define a proxy class to center the characters in all cells.
3: Use QSS to change the background color of the table to yellow and blue.
Above code:
#include <QtGui> #include <QItemDelegate> #include <QSpinBox> //Number column, read-only delegate //I really can’t think of this method, haha class ReadOnlyDelegate : public QItemDelegate { Q_OBJECT public: ReadOnlyDelegate(QObject *parent = 0): QItemDelegate(parent) { } QWidget *createEditor(QWidget*parent, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { return NULL; } }; //ID column, only 1-12 numbers can be entered //Use QLineEdit delegates and regular expressions to limit input class UserIDDelegate : public QItemDelegate { Q_OBJECT public: UserIDDelegate(QObject *parent = 0): QItemDelegate(parent) { } QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { QLineEdit *editor = new QLineEdit(parent); QRegExp regExp("[0-9]{0,10}"); editor->setValidator(new QRegExpValidator(regExp, parent)); return editor; } void setEditorData(QWidget *editor, const QModelIndex & amp;index) const { QString text = index.model()->data(index, Qt::EditRole).toString(); QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); lineEdit->setText(text); } void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex & amp;index) const { QLineEdit *lineEdit = static_cast<QLineEdit*>(editor); QString text = lineEdit->text(); model->setData(index, text, Qt::EditRole); } void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { editor->setGeometry(option.rect); } }; //In the age column, use the QSpinBox delegate to limit the input. Only numbers between 1 and 100 can be entered. class AgeDelegate : public QItemDelegate { Q_OBJECT public: AgeDelegate(QObject *parent = 0): QItemDelegate(parent) { } QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { QSpinBox *editor = new QSpinBox(parent); editor->setMinimum(1); editor->setMaximum(100); return editor; } void setEditorData(QWidget *editor, const QModelIndex & amp;index) const { int value = index.model()->data(index, Qt::EditRole).toInt(); QSpinBox *spinBox = static_cast<QSpinBox*>(editor); spinBox->setValue(value); } void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex & amp;index) const { QSpinBox *spinBox = static_cast<QSpinBox*>(editor); spinBox->interpretText(); int value = spinBox->value(); model->setData(index, value, Qt::EditRole); } void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { editor->setGeometry(option.rect); } }; //Gender column, use QComboBox delegate to limit input //The cells in this column can only enter Male or Female class SexDelegate : public QItemDelegate { Q_OBJECT public: SexDelegate(QObject *parent = 0): QItemDelegate(parent) { } QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { QComboBox *editor = new QComboBox(parent); editor->addItem("Female"); editor->addItem("Male"); return editor; } void setEditorData(QWidget *editor, const QModelIndex & amp;index) const { QString text = index.model()->data(index, Qt::EditRole).toString(); QComboBox *comboBox = static_cast<QComboBox*>(editor); int tindex = comboBox->findText(text); comboBox->setCurrentIndex(tindex); } void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex & amp;index) const { QComboBox *comboBox = static_cast<QComboBox*>(editor); QString text = comboBox->currentText(); model->setData(index, text, Qt::EditRole); } void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { editor->setGeometry(option.rect); } }; //The avatar column is just a small picture placed in the center of the cell. class IconDelegate : public QItemDelegate { Q_OBJECT public: IconDelegate(QObject *parent = 0): QItemDelegate(parent) { } void paint(QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp; index ) const { //show.bmp is a picture in the project directory (actually it is the QQ icon, haha) QPixmap pixmap = QPixmap("show.bmp").scaled(24, 24); qApp->style()->drawItemPixmap(painter, option.rect, Qt::AlignCenter, QPixmap(pixmap)); } }; //Agent class, display the characters in all cells in the center class VIPModel : public QStandardItemModel { Q_OBJECT public: VIPModel(QObject *parent=NULL) : QStandardItemModel(parent) { } VIPModel(int row, int column, QObject *parent=NULL) : QStandardItemModel(row, column, parent) { } QVariant data(const QModelIndex & amp;index, int role = Qt::DisplayRole) const { if( Qt::TextAlignmentRole == role ) return Qt::AlignCenter; return QStandardItemModel::data(index, role); } }; #include "main.moc" int main(int argc, char *argv[]) { QApplication app(argc, argv); VIPModel *model = new VIPModel(5, 5); QTableView *tableView = new QTableView; //Adjust the background of the table to yellow and blue //I saw this method on the Internet, and it’s really convenient to use. tableView->setAlternatingRowColors(true); tableView->setStyleSheet("QTableView{background-color: rgb(250, 250, 115);" "alternate-background-color: rgb(141, 163, 215);}"); tableView->setWindowTitle("VIP List"); tableView->resize(700, 400); tableView->setModel(model); QStringList headerList; headerList << "No." << "ID" << "Name" << "Age" << "Sex" << "Show"; model->setHorizontalHeaderLabels(headerList); tableView->verticalHeader()->setVisible(false); tableView->horizontalHeader()->setStretchLastSection(true); //Load delegates for each column ReadOnlyDelegate readOnlyDelegate; //tableView->setItemDelegateForColumn(0, & amp;readOnlyDelegate); //I will get an error if I use it tableView->setItemDelegateForColumn(0, new ReadonlyDelegate(this)); //I use this UserIDDelegate userIDDelegate; tableView->setItemDelegateForColumn(1, & userIDDelegate); AgeDelegate spinBoxDelegate; tableView->setItemDelegateForColumn(3, & amp;spinBoxDelegate); SexDelegate comboBoxDelegate; tableView->setItemDelegateForColumn(4, & amp;comboBoxDelegate); IconDelegate iconDelegate; tableView->setItemDelegateForColumn(5, & amp;iconDelegate); for(int i=0; i<10; i + + ) { QModelIndex index = model->index(i, 0, QModelIndex()); model->setData(index, i); } tableView->show(); return app.exec(); }
QTableView, QStandardItemModel/QAbstractItemModel, QStyledItemDelegate/QItemDelegate and QModelIndex;
Let’s take a look at the picture first to see the effect.
The next line is the full path of the selected file displayed.
Line 2 “C:” is the value set during initialization, just for test display.
The last line is no file selected.
This SelectFileButton method I implemented:
QPushButton;
Implement a slot function in SelectFileButton: function, select the file and return the path when clicked.
cQItemDelegate;
d. Then rewrite createEditor(); return the pointer of SelectFileButton
e. Rewrite setModelData(), setEditorData(); set model data and set editing data.
Benefits of this article,You can receive Qt development learning materials package and technical videos for free, including (C++ language basics, introduction to Qt programming, QT signals and slots mechanism, QT interface development -Image drawing, QT network, QT database programming, QT project practice, QT embedded development, Quick module, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the article莬to receive the fee↓↓
#ifndef SELECTFILEBUTTONDELEGATE_H #define SELECTFILEBUTTONDELEGATE_H #include <QItemDelegate> #include <QPushButton> #include <QModelIndex> #include <QFileDialog> #include <QAbstractItemModel> #include <QDebug> class TableModel; class SelectFileButton: public QPushButton { Q_OBJECT public: SelectFileButton(const QModelIndex & amp; index, QWidget *parent = 0) : QPushButton(parent) { Init(index); } SelectFileButton(const QModelIndex & amp; index, const QString & amp;text, QWidget *parent = 0) : QPushButton(text, parent) { Init(index); } SelectFileButton(const QModelIndex & amp; index, const QIcon & amp; icon, const QString & amp;text, QWidget *parent = 0) :QPushButton(icon, text, parent) { Init(index); } ~SelectFileButton() { qDebug() << "~SelectFileButton"; } protected: void Init(const QModelIndex & amp; index) { m_index = index; connect(this, SIGNAL(clicked()), this, SLOT(btnClick_slot())); } public slots: void btnClick_slot() { QString strValue; QModelIndex index = this->m_index; QFileDialog * dlg = new QFileDialog(0); int res =dlg->exec(); //Start a new thread here, and the top layer will release this button, so you need to save a copy of the Index if (res==QFileDialog::Accepted) { strValue = dlg->selectedFiles()[0]; QAbstractItemModel* model = const_cast<QAbstractItemModel*>(index.model()); model->setData(index, strValue); } } private: QModelIndex m_index; }; /****************************************************** *********************/ class SelectFileButtonDelegate : public QItemDelegate { Q_OBJECT public: QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { SelectFileButton* btn = new SelectFileButton(index,QStringLiteral("Find file path"), parent); //This is in other threads so it cannot be saved. Btn is different every time return btn; } void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex & amp;index) const; void setEditorData(QWidget *editor, const QModelIndex & amp;index) const; public: SelectFileButtonDelegate(QObject *parent); ~SelectFileButtonDelegate(); private: QPushButton* m_btn; }; #endif // SELECTFILEBUTTONDELEGATE_H
Draw custom controls through painter
QStyleOption subclass:
QStyleOptionButton, QStyleOptionComplex, QStyleOptionDockWidget, QStyleOptionFocusRect, QStyleOptionFrame, QStyleOptionGraphicsItem, QStyleOptionHeader, QStyleOptionMenuItem, QStyleOptionProgressBar, QStyleOptionRubberBand, QStyleOptionTab, QStyleOptionTabBarBase, QStyleOptionTabWidgetFrame, QStyleOptionToolBar, QStyleOption ToolBox, and QStyleOptionViewItem
1. Painter custom progress bar
//Customize progress bar BarDelegate::BarDelegate( QObject *parent ) : QAbstractItemDelegate( parent ) { } void BarDelegate::paint( QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index ) const { if( option.state & amp; QStyle::State_Selected ) painter->fillRect( option.rect, option.palette.highlight() ); //The data is a QStandardItem stored in QStandardItemModel, which will automatically match based on the current row (I think) int value = index.model()->data( index, Qt::DisplayRole ).toInt(); // This sentence gets the data of the current row qDebug() << value; double factor = double(value)/100.0; // Calculate the scale factor painter->save(); // Save the old artboard (I think) //Progress bar background color if(factor > 0.8) { painter->setBrush( Qt::red ); // Paint pure red beyond 0.8 factor = 1; } else painter->setBrush( QColor( 0, int(factor*255), 255-int(factor*255) ) ); // Otherwise, the colors will become lighter in sequence int n = factor*100; QString str1 = QString("%1\%").arg(n); painter->setPen( Qt::red ); // Brush color (not used here, I think) // The previous steps are all preparation work, here is where the progress bar is actually drawn. 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(); // Restore the new artboard (I think) } QSize BarDelegate::sizeHint( const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index ) const { return QSize( 45, 15 ); // Change it as you like, it will not affect (I think) }
class BarDelegate : public QAbstractItemDelegate { public: BarDelegate( QObject *parent = 0 ); // Override two functions to display the progress bar void paint( QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index ) const; QSize sizeHint( const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index ) const; };
1 painter progress bar QStyleOptionProgressBar
void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;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 & amp; QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); painter->setBrush(option.palette.highlightedText()); } QApplication::style()->drawControl(QStyle::CE_ProgressBar, & amp;progressBarOption, painter); painter->restore(); } else { return QItemDelegate::paint (painter, option, index); } }
2. Painter custom button 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("Edit button") << QStringLiteral("Delete button"); } //Set button normal, swipe, and press styles 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() { } // draw button void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { QStyleOptionViewItem viewOption(option); initStyleOption( & amp;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) { // Calculate button display area 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) { // draw button 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, & amp;button, painter, pWidget); } } } //Respond to button events - swipe, press bool TableViewDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem & amp; option, const QModelIndex & amp; 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; //Restore mouse style 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); //The mouse is over the button if (!button.rect.contains(m_mousePoint)) continue; bRepaint = true; switch (event->type()) { //mouse over case QEvent::MouseMove: { //Set the mouse style to hand type //QApplication::setOverrideCursor(Qt::PointingHandCursor); m_nType = 0; QToolTip::showText(pEvent->globalPos(), m_list.at(i)); break; } //Mouse pressed case QEvent::MouseButtonPress: { m_nType = 1; break; } //mouse release case QEvent::MouseButtonRelease: { if(i==0) { emit EditData(index); } else { emit deleteData(index); } break; } default: break; } } return bRepaint; }
Three painter set pictures
void ItemdelegateTest::paint(QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { QStyleOptionViewItem viewOption(option); if (viewOption.state & amp; 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 & amp;option, const QModelIndex & amp;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 & amp; & amp; DrawRect.contains(mouseEvent->pos())) { emit deleteItem(index); } if (event->type() == QEvent::MouseMove & amp; & amp; DrawRect.contains(mouseEvent->pos())) { QCursor cursor(Qt::PointingHandCursor); QApplication::setOverrideCursor(cursor); QToolTip::showText(mouseEvent->globalPos(), "delete"); } else { QCursor cursor(Qt::ArrowCursor); QApplication::setOverrideCursor(cursor); } return QStyledItemDelegate::editorEvent(event, model, option, index); }
panier draws checkbox
CheckBoxDelegate::CheckBoxDelegate(QObject *parent) : QStyledItemDelegate(parent) { } CheckBoxDelegate::~CheckBoxDelegate() { } // draw checkbox void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) const { QStyleOptionViewItem viewOption(option); initStyleOption( & amp;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, & amp;checkBoxStyle, painter, & amp;checkBox); } } //Respond to mouse events and update data bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem & amp;option, const QModelIndex & amp;index) { QRect decorationRect = option.rect; QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); if (event->type() == QEvent::MouseButtonPress & amp; & amp; 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); }
Original link: https://www.cnblogs.com/whwywzhj/p/8883634.html
Benefits of this article,You can receive Qt development learning materials package and technical videos for free, including (C++ language basics, introduction to Qt programming, QT signals and slots mechanism, QT interface development -Image drawing, QT network, QT database programming, QT project practice, QT embedded development, Quick module, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the article莬to receive the fee↓↓