C++、Qt学习交流群: 302558294(欢迎你的加入)
需求:
做一个简单的产品信息管理界面,能够新增,修改,删除产品信息;(所有数据均保存在内存中)
a.学生信息包括(姓名,学校(金牛小学,青羊小学),班级(1班,2班,3班),年龄,性别,身高,政治面貌,个人描述(不超过300字符)
b.界面左边采用QTreeWidget或相关控件显示学校、班级两级信息;
c.界面右边使用QListWidget或相关控件显示选中班级所有成员信息;
d.新增,修改,删除功能均使用菜单来完成;
程序界面展示:
(很多功能还不完善,本例仅供参考,欢迎大家补充)
所用技术:
1、实现自定义委托。
2、QTreewidget、QTableView,
3、MVC模式。
4、菜单栏的功能都可以在对应的控件上右击,弹出快捷菜单。
5、界面布局。
代码:
//main.cpp
<span style="font-size:14px;">#include <QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
StuInfoManagementSystem w;
w.show();
return a.exec();
}
</span>
//widget.h
<span style="font-size:14px;">#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QStandardItemModel>
#include <QTableView>
#include <QMenu>
#include <QAction>
#include <QMenuBar>
#include <QTreeView>
#include <QTreeWidget>
#include <QStandardItem>
#include "controldelegate.h"
class SpinboxDelegate;
class ComboboxDelegate;
//namespace Ui {
//class StuInfoManagementSystem;
//}
class StuInfoManagementSystem: public QWidget
{
Q_OBJECT
public:
explicit StuInfoManagementSystem(QWidget *parent = 0);
~StuInfoManagementSystem();
public:
void contextMenuEvent(QContextMenuEvent *e);
void menuBarInit(); //菜单初始化
void tableWidgetInit(); //table控件初始化
void treeWidgetInit();
void closeEvent(QCloseEvent *event);//程序关闭时触发
void upDateTableView();
private:
QMenu *OperationMenu; //操作菜单
QAction *DeleteAction;
QAction *InsertAction;
QMenu *helpMenu; //帮助菜单
QAction *aboutAction;
QAction *aboutQtAction;
QMenu *schoolAndGradeMenu;
QAction *addSchoolAction;
QAction *addGradeAction;
QAction *delSchoolOrGradeAction;
QMenuBar* menuBar;
SpinboxDelegate* ageSpinbox;//年龄
SpinboxDelegate* heightSpinbox; //身高
ComboboxDelegate* schoolCombobox;//学校
ComboboxDelegate* gradeCombobox;//班级
ComboboxDelegate* sexCombobox; //性别
ComboboxDelegate* statusCombobox; //政治面貌
private slots:
void sltInsertAction();
void sltDeleteAction();
void sltAddSchoolAction();
void sltAddGradeAction();
void sltDelSchoolOrGradeAction();
void sltAboutAction();
void SlotItemClicked(QTreeWidgetItem *item, int column);
private:
QStandardItemModel* tableModel;
QTableView* table;
QStandardItem *dataSources;
QTreeWidget *treeWidget;
//private:
// Ui::StuInfoManagementSystem *ui;
};
#endif // WIDGET_H
</span>
//widget.cpp
<span style="font-size:14px;">#include <QSplitter>
#include <QFileSystemModel>
#include <QTreeView>
#include <QListView>
#include <QVBoxLayout>
#include <QAbstractItemModel>
#include <QTableView>
#include <QMenuBar>
#include <QVBoxLayout>
#include <QDebug>
#include <QTreeWidgetItem>
#include <controldelegate.h>
#include <QToolTip>
#include <QAbstractItemView>
#include <QStandardItem>
#include <QList>
#include <QStandardItem>
#include <QMessageBox>
#include <QInputDialog>
#include "widget.h"
#include "ui_widget.h"
StuInfoManagementSystem::StuInfoManagementSystem(QWidget *parent) : QWidget(parent)/*,ui(new Ui::StuInfoManagementSystem)*/
{
setMinimumSize(1200,400);
menuBarInit();//菜单初始化
tableWidgetInit(); //table初始化
treeWidgetInit(); //tree初始化
QGridLayout *grid = new QGridLayout;
grid->addWidget(menuBar,0,0,1,2);
grid->addWidget(treeWidget,1,0);
grid->addWidget(table,1,1);
setLayout(grid);
showMaximized();
}
StuInfoManagementSystem::~StuInfoManagementSystem()
{
//delete ui;
}
void StuInfoManagementSystem::contextMenuEvent(QContextMenuEvent *e) //重写上下文事件
{
//方法一
if(table->hasFocus())
{
OperationMenu->move(cursor().pos());
OperationMenu->show();
}
if(treeWidget->hasFocus())
{
schoolAndGradeMenu->move(cursor().pos());
schoolAndGradeMenu->show();
}
//方法二
// {
// table->addAction(InsertAction);
// table->addAction(DeleteAction);
// table->setContextMenuPolicy(Qt::ActionsContextMenu);
// }
}
void StuInfoManagementSystem::menuBarInit()
{
menuBar = new QMenuBar(0);
OperationMenu = new QMenu(QString::fromLocal8Bit("学生"));
DeleteAction = new QAction(QString::fromLocal8Bit("删除"));
InsertAction = new QAction(QString::fromLocal8Bit("插入"));
OperationMenu->addAction(DeleteAction);
OperationMenu->addAction(InsertAction);
helpMenu = new QMenu(QString::fromLocal8Bit("帮助"));
aboutAction = new QAction(QString::fromLocal8Bit("关于软件"));
aboutQtAction = new QAction(QString::fromLocal8Bit("关于Qt"));
helpMenu->addAction(aboutAction);
helpMenu->addAction(aboutQtAction);
schoolAndGradeMenu = new QMenu(QString::fromLocal8Bit("学校/班级"));
addSchoolAction = new QAction(QString::fromLocal8Bit("添加 学校"));
addGradeAction = new QAction(QString::fromLocal8Bit("添加 班级"));
delSchoolOrGradeAction = new QAction(QString::fromLocal8Bit("删除"));
schoolAndGradeMenu->addAction(addSchoolAction);
schoolAndGradeMenu->addAction(addGradeAction);
schoolAndGradeMenu->addAction(delSchoolOrGradeAction);
menuBar->addMenu(schoolAndGradeMenu);
menuBar->addMenu(OperationMenu);
menuBar->addMenu(helpMenu);
connect(InsertAction,SIGNAL(triggered(bool)),SLOT(sltInsertAction()));
connect(DeleteAction,SIGNAL(triggered(bool)),SLOT(sltDeleteAction()));
connect(addSchoolAction,SIGNAL(triggered(bool)),SLOT(sltAddSchoolAction()));
connect(addGradeAction,SIGNAL(triggered(bool)),SLOT(sltAddGradeAction()));
connect(delSchoolOrGradeAction,SIGNAL(triggered(bool)),SLOT(sltDelSchoolOrGradeAction()));
connect(aboutAction,SIGNAL(triggered(bool)),SLOT(sltAboutAction()));
connect(aboutQtAction,SIGNAL(triggered(bool)),qApp,SLOT(aboutQt()));
}
void StuInfoManagementSystem::tableWidgetInit()
{
//tableview初始化
{
table = new QTableView;
tableModel = new QStandardItemModel;
table->setModel(tableModel);
tableModel->setHorizontalHeaderItem(0,new QStandardItem(QString::fromLocal8Bit("姓名")));
tableModel->setHorizontalHeaderItem(1,new QStandardItem(QString::fromLocal8Bit("学校")));
tableModel->setHorizontalHeaderItem(2,new QStandardItem(QString::fromLocal8Bit("班级")));
tableModel->setHorizontalHeaderItem(3,new QStandardItem(QString::fromLocal8Bit("年龄")));
tableModel->setHorizontalHeaderItem(4,new QStandardItem(QString::fromLocal8Bit("性别")));
tableModel->setHorizontalHeaderItem(5,new QStandardItem(QString::fromLocal8Bit("身高")));
tableModel->setHorizontalHeaderItem(6,new QStandardItem(QString::fromLocal8Bit("政治面貌")));
tableModel->setHorizontalHeaderItem(7,new QStandardItem(QString::fromLocal8Bit("个人描述")));
// 姓名,学校(金牛小学,青羊小学),班级(1班,2班,3班),年龄,性别,身高,政治面貌,个人描述(不超过300字符)
table->setModel(tableModel);
table->horizontalHeader()->setStretchLastSection(true);
table->setItemDelegateForColumn(1, new ComboboxDelegate);
table->setItemDelegateForColumn(2,new ComboboxDelegate);
table->setItemDelegateForColumn(3,new SpinboxDelegate(3));
table->setItemDelegateForColumn(4,new ComboboxDelegate);
table->setItemDelegateForColumn(5,new SpinboxDelegate(5));
table->setItemDelegateForColumn(6,new ComboboxDelegate);
table->setEditTriggers(QAbstractItemView::DoubleClicked);
table->setSelectionBehavior(QAbstractItemView::SelectRows);
}
}
void StuInfoManagementSystem::treeWidgetInit()
{
treeWidget = new QTreeWidget;
treeWidget->setMaximumWidth(200);
treeWidget->setHeaderLabel(QString::fromLocal8Bit("学校/班级"));
QTreeWidgetItem *qingYang = new QTreeWidgetItem;
qingYang->setText(0,QString::fromLocal8Bit("青羊小学"));
QTreeWidgetItem *jinNiu = new QTreeWidgetItem;
jinNiu->setText(0,QString::fromLocal8Bit("金牛小学"));
QStringList classlist;
classlist << QString::fromLocal8Bit("1班") << QString::fromLocal8Bit("2班")
<< QString::fromLocal8Bit("3班");
for(int i=0;i<=2;i++)
{
QTreeWidgetItem *tmp_qingYang = new QTreeWidgetItem(qingYang);
tmp_qingYang->setText(0,classlist.at(i));
qingYang->addChild(tmp_qingYang);
QTreeWidgetItem *tmp_jinNiu = new QTreeWidgetItem(jinNiu);
tmp_jinNiu->setText(0,classlist.at(i));
jinNiu->addChild(tmp_jinNiu);
}
treeWidget->insertTopLevelItem(0,qingYang);
treeWidget->insertTopLevelItem(1,jinNiu);
connect(treeWidget,SIGNAL(itemPressed(QTreeWidgetItem *, int)),SLOT(SlotItemClicked(QTreeWidgetItem *, int)));
}
void StuInfoManagementSystem::closeEvent(QCloseEvent *event)
{
qDebug()<<"Application close";
}
void StuInfoManagementSystem::sltInsertAction() //插入行操作
{
QList<QStandardItem*> item;
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.append(new QStandardItem(NULL));
item.at(0)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); //设置指定项的对齐方式
item.at(7)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
tableModel->insertRow(tableModel->rowCount(),item);
}
void StuInfoManagementSystem::sltDeleteAction() //删除指定行操作
{
int curreantRow = table->currentIndex().row(); //获取当前行数
tableModel->removeRow(curreantRow);
}
void StuInfoManagementSystem::sltAddSchoolAction()
{
bool ok;
QString text = QInputDialog::getText(this,
"Please Input School Name",
tr("School name:"),
QLineEdit::Normal,
tr(""),
&ok);
if(ok && !text.isEmpty())
{
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0,text);
int schoolCount = treeWidget->topLevelItemCount();
treeWidget->insertTopLevelItem(schoolCount,item);
}
}
void StuInfoManagementSystem::sltAddGradeAction()
{
if(treeWidget->currentItem())
{
bool ok;
QString text = QInputDialog::getText(this,
"Please Input Grade Name",
tr("Grade name:"),
QLineEdit::Normal,
tr(""),
&ok);
if(ok && !text.isEmpty())
{
QTreeWidgetItem *item = new QTreeWidgetItem;
item->setText(0,text);
if(treeWidget->currentItem()->parent())//当前选中的是班级
{
for(int i = 0; i< treeWidget->currentItem()->parent()->childCount(); i++) //同一个学校的班级不能重复
{
if(treeWidget->currentItem()->parent()->child(i)->text(0) == text)
{
QMessageBox::information(this, QString::fromLocal8Bit("警告"),
QString::fromLocal8Bit("%1 已经存在").arg(text));
return;
}
}
treeWidget->currentItem()->parent()->addChild(item);
}
else
{
for(int i = 0; i< treeWidget->currentItem()->childCount(); i++) //同一个学校的班级不能重复
{
if(treeWidget->currentItem()->child(i)->text(0) == text)
{
QMessageBox::information(this, QString::fromLocal8Bit("警告"),
QString::fromLocal8Bit("%1 已经存在").arg(text));
return;
}
}
treeWidget->currentItem()->addChild(item);
}
}
}
treeWidget->expandAll();
}
void StuInfoManagementSystem::sltDelSchoolOrGradeAction()
{
QTreeWidgetItem *item = treeWidget->currentItem();
if(!item->parent())
{
treeWidget->takeTopLevelItem(treeWidget->indexOfTopLevelItem(treeWidget->currentItem()));
}
else
{
QTreeWidgetItem *parent = item->parent();
if(parent)
{
parent->removeChild(item);
}
}
}
void StuInfoManagementSystem::sltAboutAction()
{
QMessageBox::about(this, tr("About Aoftware"),tr("Make By Hero"));
}
void StuInfoManagementSystem::SlotItemClicked(QTreeWidgetItem *item, int column)
{
//学校1,班级2
if(item->parent()) //当前item为子项
{
for(int row = 0; row <= tableModel->rowCount();row++)
{
if(item->text(column) == tableModel->data(tableModel->index(row,2)).toString()) //班级
{
if(item->parent()->text(column) ==tableModel->data(tableModel->index(row,1)).toString()) //学校
table->setRowHidden(row,false);
else
table->setRowHidden(row,true);
}
else
{
table->setRowHidden(row,true);
}
}
}
else //当前点击的item为父项
{
if(item->text(column) == QString::fromLocal8Bit("青羊小学"))
{
for(int row = 0; row <= tableModel->rowCount();row++)
{
if(tableModel->data(tableModel->index(row,1)).toString() != QString::fromLocal8Bit("青羊小学"))
table->setRowHidden(row,true);
else
table->setRowHidden(row,false);
}
}
else if(item->text(column) == QString::fromLocal8Bit("金牛小学"))
{
for(int row = 0; row <= tableModel->rowCount();row++)
{
if(tableModel->data(tableModel->index(row,1)).toString() != QString::fromLocal8Bit("金牛小学"))
table->setRowHidden(row,true);
else
table->setRowHidden(row,false);
}
}
}
}
</span>
//controldelegate
<span style="font-size:14px;">#ifndef CONTROLDELEGATE_H
#define CONTROLDELEGATE_H
#include <QItemDelegate>
#include <QObject>
class SpinboxDelegate : public QItemDelegate //年龄
{
Q_OBJECT
public:
SpinboxDelegate(int column);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//void setEditorData(QWidget *editor, const QModelIndex &index) const ;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const ;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
//void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
private slots:
void commitAndCloseEditor();
private:
int mColumn;
};
class ComboboxDelegate : public QItemDelegate //学校
{
Q_OBJECT
public:
ComboboxDelegate();
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
private slots:
void commitAndCloseEditor();
};
#endif // CONTROLDELEGATE_H
</span>
//controldelegate.cpp
<span style="font-size:14px;">#include <QSpinBox>
#include <QComboBox>
#include <QDebug>
#include <QApplication>
#include <QStyleOptionViewItem>
#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include "controldelegate.h"
SpinboxDelegate::SpinboxDelegate(int column)
{
mColumn = column;
}
//为指定的列或者行创建部件
QWidget *SpinboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const
{
if(index.column() ==3) //年龄
{
QSpinBox *editor = new QSpinBox(parent);
editor->setRange(1,110);
connect(editor,SIGNAL(editingFinished()),SLOT(commitAndCloseEditor()));
return editor;
}
else if( index.column() == 5) //身高
{
QSpinBox *editor = new QSpinBox(parent);
editor->setRange(120,220);
connect(editor,SIGNAL(editingFinished()),SLOT(commitAndCloseEditor()));
return editor;
}
else
{
return QItemDelegate::createEditor(parent,option,index);
}
}
//显示格式控制
void SpinboxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column()== 5)
{
int age = index.model()->data(index,Qt::DisplayRole).toInt();
QString text = QString("%1 CM").arg(age,3,10,QChar(' '));
QStyleOptionViewItem myOption = option;
myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
drawDisplay(painter,myOption,myOption.rect,text);
drawFocus(painter,myOption,myOption.rect);
}
else if(index.column() == 3)
{
int height = index.model()->data(index,Qt::DisplayRole).toInt();
QString text = QString("%1 Year").arg(height,3,10,QChar(' '));
QStyleOptionViewItem myOption = option;
myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
drawDisplay(painter,myOption,myOption.rect,text);
drawFocus(painter,myOption,myOption.rect);
}
}
void SpinboxDelegate::commitAndCloseEditor()
{
QSpinBox *editor = qobject_cast<QSpinBox*>(sender());
emit commitData(editor);
emit closeEditor(editor);
}
//void SpinboxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
//{
//}
void SpinboxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
ComboboxDelegate::ComboboxDelegate()
{
}
QWidget *ComboboxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QComboBox *editor = new QComboBox(parent);
if(index.column() == 1)
{
editor->addItem(QString::fromLocal8Bit("青羊小学"));
editor->addItem(QString::fromLocal8Bit("金牛小学"));
editor->setCurrentIndex(0);
connect(editor,SIGNAL(editingFinished()),SLOT(commitAndCloseEditor()));
return editor;
}
else if(index.column() == 2)
{
editor->addItem(QString::fromLocal8Bit("1班"));
editor->addItem(QString::fromLocal8Bit("2班"));
editor->addItem(QString::fromLocal8Bit("3班"));
editor->setCurrentIndex(0);
connect(editor,SIGNAL(editingFinished()),SLOT(commitAndCloseEditor()));
return editor;
}
else if(index.column() == 4)
{
editor->addItem(QString::fromLocal8Bit("男"));
editor->addItem(QString::fromLocal8Bit("女"));
editor->setCurrentIndex(0);
connect(editor,SIGNAL(editingFinished()),SLOT(commitAndCloseEditor()));
return editor;
}
else if(index.column() == 6)
{
editor->addItem(QString::fromLocal8Bit("群众"));
editor->addItem(QString::fromLocal8Bit("共青团员"));
editor->addItem(QString::fromLocal8Bit("共产党员"));
editor->setCurrentIndex(0);
connect(editor,SIGNAL(editingFinished()),SLOT(commitAndCloseEditor()));
return editor;
}
else
{
QItemDelegate::createEditor(parent,option,index);
}
}
void ComboboxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == 1 || index.column() == 2 ||index.column() == 4 ||index.column() == 6)
{
QString text = index.model()->data(index , Qt::DisplayRole).toString();
QStyleOptionViewItem myOption = option;
myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
drawDisplay(painter,myOption,myOption.rect,text);
drawFocus(painter,myOption,myOption.rect);
}
else
{
QItemDelegate::paint(painter,option,index);
}
}
void ComboboxDelegate::commitAndCloseEditor()
{
QComboBox *editor = qobject_cast<QComboBox*>(sender());
emit commitData(editor);
emit closeEditor(editor);
}
</span>