Qplugin
刚开始接触的时候,想着诶不是弄这么多框框架架的东西和多写几个widget不一样吗,后面想想还真不一样,还是得多了解一下。
插件插件,就是说明他是动态的,热加载的。热加载就是相当于热插拔,比较灵活。
这次仿着大佬们的框架搞一个,边搞边查资料理解一下吧。
大概是这样,左边是一个列表,列表的每个条目对应一个插件,插件内容大概就是一个页面,显示在右边的区域里。
所以第一步还是先把图形弄一弄,额也就是说还扯不上qplugin。
建工程咯
打算用cmake构建啦,图形程序主体在src目录下,其余每个插件各建一个目录。最外层的cmake先写上:
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project(qplugin-demo)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(QT_MINIMUM_VERSION "5.7.1")
include(GNUInstallDirs)
find_package(Qt5Widgets ${QT_MINIMUM_VERSION} REQUIRED)
add_subdirectory(src)
后面在src里面再建立cmakelist文件,建立mainwindow头文件cpp文件ui文件等,走流程走流程。
编辑ui,先把什么menubar、maintoolbar、statusbar什么的都删掉,留下一个主窗口的widget就行了。
然后拖一个treeview和一个scrollArea上去,要同时选中两个控件,才能点水平分割布局:
再设置一个外层widget的布局,他们俩就一左一右填满的整个窗体了!
TreeView
提起这个控件,就离不开model view delegate三幻神。
关于view
唉就随随便便设一下样式表就行了嘛,把treeview各种东西都干掉了,什么左边点击选项,节点设置,双击等等,不太需要:
ui->treeView->setExpandsOnDoubleClick(false);
ui->treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->treeView->setAnimated(true);
ui->treeView->setHeaderHidden(true);
ui->treeView->setItemDelegate(new TagItemDelegate(this));
ui->treeView->setRootIsDecorated(false);
ui->treeView->setIndentation(0);
ui->treeView->setContentsMargins(0, 0, 0, 0);
ui->treeView->setStyleSheet("QTreeView{border:none;background: #E0FFFF;}");
ui->sidebarWidget->setStyleSheet("QWidget{background:#E0FFFF;}");
关于model
就列表每条item有一个字符串的标题数据,用Qt::DisplayRole值就能返回每条item的字符串了,加一个自定义的role存放每一项的高度吧,想着放个空的进去能有分割效果。
好了这是标题字符串们:
tagList << tr("humpback whale") << tr("orcinus orca") << tr("balaenoptera musculus") << tr("carcharodon carcharias");
新建个QStandardItem的子类,里面就存着标题和高度的数据,高度默认40,空的就30,上面三条鲸鱼,中间一个空,下面一条大白鲨!把这些字符串全插入!:
for (int i = 0; i < 3; i++) {
TagItem *item = new TagItem(tagList.at(i));
appendRow(item);
}
TagItem *item = new TagItem("");
item->setSelectable(false);
item->setEnabled(false);
item->setCheckable(false);
item->setheight(30);
appendRow(item);
TagItem *item2 = new TagItem(tagList.at(3));
appendRow(item2);
字符串数据就通过Qt::DisplayRole获取了,而RowHeight这个就是自定义就行了。再编辑获取数据的data函数,model就完成了:
QVariant TagModel::data(const QModelIndex& index, int role/* = Qt::DisplayRole*/) const
{
if(!index.isValid()) {
return QVariant();
}
TagItem* item = static_cast<TagItem*>(QStandardItemModel::itemFromIndex(index));
if(item){
switch(role) {
case RowHeight:
{
return item->height();
}
}
}
return QStandardItemModel::data(index, role);
}
关于delegate
继承QStyledItemDelegate,就是细化处理每一条item了把,函数里的index参数用于定位哪一条item。
这个虚函数可以设置每一条的高度:
QSize TagItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
这个虚函数可以细画每一条item里的数据,但当决定要自己写这个paint(瞅一眼const QStyleOptionViewItem &option这个参数心里默默知道要干嘛了吧),就要把项目里的内容都好好画,包括什么item的矩形(option->rect),item的文本,item的状态(option->state)等,不然就是空的。要不就不重写也行:
void TagItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
而获取每一条item的文本和高度这样获取(高度是自己弄的):
QString title = index.data(Qt::DisplayRole).toString();
int height = index.data(RowHeight).toInt();
有了这些,就自己咋画就咋画吧。
我好了
mainwindow构建好ui后set一下model就好了:
model = new TagModel(this);
ui->treeView->setModel(model);
然后图形出来了:
主要看左边,那是一个treeview。treeview弄好了后面随便加节点数据啦哈哈哈。