展示型网站制作服务,国际新闻最新消息今天乌克兰与俄罗斯视频,现在建设一个网站多少钱,建投商务网登录介绍
在键鼠自动化2.0中使用Qtc实现了全自定义树形结构#xff0c;实现任务的拖拽#xff0c;复制粘贴#xff0c;撤销重做#xff0c;以及包括树形结构增加序号展示#xff0c;以及增加搜索功能
实现
1.自定义节点
// 自定义节点类
class TreeNode : public QObject …介绍
在键鼠自动化2.0中使用Qtc实现了全自定义树形结构实现任务的拖拽复制粘贴撤销重做以及包括树形结构增加序号展示以及增加搜索功能
实现
1.自定义节点
// 自定义节点类
class TreeNode : public QObject {
public:TreeNode(QObject *parent nullptr): QObject(parent) {}
public:bool isInChild false; //是否接受子节点QString nodeText; //用于判断的节点名称QString nodeItemTest; //显示的名称QVariant taskData; //数据存储QListTreeNode* children; //子节点TreeNode* parent nullptr; //父节点MyStandardItem* item; //itemint number -1; //临时使用// 重载运算符以判断nodeText是否相等bool operator(const TreeNode other) const {return nodeText other.nodeText;}
};
2.拖拽功能
重写拖拽相关函数 void startDrag(Qt::DropActions supportedActions);void dragLeaveEvent(QDragLeaveEvent* event);void dragEnterEvent(QDragEnterEvent *event);void dragMoveEvent(QDragMoveEvent *event);void dropEvent(QDropEvent *event);void paintEvent(QPaintEvent* event);部分核心代码
if (sourceNode-parent nullptr targetNode-parent nullptr) { //父与父//当前是父节点与父节点直接拖拽int sourceRow sourceNode-item-row();qDebug() MyDebug 1111111111111111 targetRow sourceRow;if (targetRow ! sourceRow) {//在目标源下插入一行if (sourceNode-children.isEmpty()) {TreeNode* node;if (isAppendParent) {node this-appendChileItem(targetNode, sourceNode);}else {node this-insertTopItem(sourceNode, targetRow);}cmdAdd-appNodeList(node);this-selectionModel()-select(node-item-index(), QItemSelectionModel::SelectCurrent);//删除来源itemthis-removeTopItem(sourceNode);}else if (!sourceNode-children.isEmpty()) {//如果来源里面有子节点就需要递归插入,先查入头节点TreeNode* newParentNode;if (isAppendParent) {newParentNode this-appendChileItem(targetNode, sourceNode);}else {newParentNode this-insertTopItem(sourceNode, targetRow);}this-selectionModel()-select(newParentNode-item-index(), QItemSelectionModel::SelectCurrent);//递归插入for (int i 0 ; i sourceNode-children.size(); i) {this-RecursionInsert(newParentNode, sourceNode-children.at(i));}cmdAdd-appNodeList(newParentNode);//删除来源itemthis-removeTopItem(sourceNode);}else {qDebug() MyDebug 未知动作!!!!!!!!!!!!!!!!!!!!!!!!;}}}3.复制粘贴
void MyTreeView::copyItemRow()
{QModelIndexList selectedIndexes this-selectedIndexes();if (selectedIndexes.size() 0) return;// 使用自定义的比较函数进行排序从大到小std::sort(selectedIndexes.begin(), selectedIndexes.end(), compareModelIndex);m_CopyListData.clear();for (int i 0; i selectedIndexes.size(); i) {MyStandardItem* sourceItem dynamic_castMyStandardItem*(model-itemFromIndex(selectedIndexes.at(i)));TreeNode* sourceNode findNodeByText(sourceItem-m_NodeText, m_TreeListData);TreeNode* nodeData new TreeNode;nodeData-isInChild sourceNode-isInChild;nodeData-nodeText sourceNode-nodeText;nodeData-nodeItemTest sourceNode-nodeItemTest;nodeData-parent sourceNode-parent;nodeData-taskData sourceNode-taskData;if (!sourceNode-children.isEmpty()) {QListTreeNode* childNodeList;RecursionCopyData(sourceNode, childNodeList);nodeData-children childNodeList;}m_CopyListData nodeData;}
}void MyTreeView::pasteItemRow()
{QModelIndexList selectedIndexes this-selectedIndexes();MyStandardItem* targetItem;if (selectedIndexes.size() 0) {targetItem dynamic_castMyStandardItem*(model-item(model-rowCount() - 1));}else {std::sort(selectedIndexes.begin(), selectedIndexes.end(), compareModelIndex);targetItem dynamic_castMyStandardItem*(model-itemFromIndex(selectedIndexes.first()));}if (!targetItem) return;TreeNode* targetNode findNodeByText(targetItem-m_NodeText, m_TreeListData);QListTreeNode* undoNodeList;for (int i 0; i m_CopyListData.size(); i) {TreeNode* node m_CopyListData.at(i);//判断目标行是父节点还是子节点if (targetNode-parent nullptr) {TreeNode* newParentNode insertTopItem(node, targetItem-row() 1);//如果存在子节点递归插入if (!node-children.isEmpty()) {for (int number 0 ; number node-children.size(); number) {RecursionInsert(newParentNode, node-children.at(number), false);}}undoNodeList newParentNode;}else {// qDebug() MyDebug 222222222222222 targetNode-nodeItemTest targetItem-row() node-nodeItemTest;TreeNode* nodeTemp insertChileItem(targetNode-parent, node, targetItem-row() 1);if (!node-children.isEmpty()) {for (int number 0 ; number node-children.size(); number) {RecursionInsert(nodeTemp, node-children.at(number), false);}}undoNodeList nodeTemp;}}AddRowCommand* cmd new AddRowCommand(this, undoNodeList);m_Undo.append(cmd);m_Redo.clear();emit signalUpdateTableView();
}4.撤销重做
实现基类command虚函数撤销与重做依次实现add和del以及多行拖拽类存储。
class Command {
public:virtual ~Command() default;virtual void undo() 0;virtual void redo() 0;
};class AddRowCommand : public Command
{
public:AddRowCommand(MyTreeView* view, QListTreeNode* nodeList QListTreeNode*());void appNodeList(TreeNode* nodeData);void undo();void redo();
private:MyTreeView* m_View;QListint m_RowList;QListbool m_IsParentList;QListQString m_ParentNodeText;QListTreeNode* m_NodeList;
};//该类注意事项
//1.要注意先增加类对象再删除node否则删除后再增加找不到子节点和自身对象等等问题
class DelRowCommand : public Command
{
public:DelRowCommand(MyTreeView* view, QListTreeNode* nodeList QListTreeNode*());void appNodeList(TreeNode* nodeData);void undo();void redo();
private:MyTreeView* m_View;QListint m_RowList; //item的行存储因为item会丢失所以保存行QListbool m_IsParentList; //保存item是否是父节点QListQString m_ParentNodeText; //父节点nodetext保存QListTreeNode* m_NodeList;
};class DragRowCommand : public Command
{
public:DragRowCommand(MyTreeView* view, QListCommand* cmdList, bool bigToSmall);void undo();void redo();
private:MyTreeView* m_View;QListCommand* m_CmdList;bool m_BigToSmall;
};5.行号
如何实现QTreeView的行号功能 这里采用了QTabelView功能布局中放下了tableview和treeview行号在treeview的左侧当滚动或者新增数据来更新一下视图数据当展开或者合并节点同步更新数据来实现所有节点的独立行号。
public slots://读取滚动条数据同步void onReadScrollValue(int value);//遍历节点子节点下的所有数量int CountTotalChildren(TreeNode* node);//递归更新子节点数据void RecursionUpdateChild(TreeNode* node);//展开void onEntered(const QModelIndex index);//合并void onCollapsed(const QModelIndex index);//获取是删除还是delvoid onReadIsAddAndDel(int isAdd, bool isHide);//更新视图数据void onUpdateView();
protected:void wheelEvent(QWheelEvent* event);void mousePressEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);void mouseDoubleClickEvent(QMouseEvent *event);6. QTreeview的搜索功能
核心代码节点递归搜索递归搜索节点返回所有包含的数据通过存到列表中加一个当前index来实现上下的切换
QListTreeNode* MyTreeView::findNodeItemText(const QString findStr)
{QListTreeNode* TreeNodeList;for (int i 0; i m_TreeListData.size(); i) {TreeNode* node m_TreeListData.at(i);recursiveFindNodeByTextItem(findStr, node, TreeNodeList);}return TreeNodeList; // 未找到匹配的节点
}void MyTreeView::recursiveFindNodeByTextItem(const QString targetText, TreeNode *currentNode, QListTreeNode * list)
{QString nodeStr currentNode-nodeItemTest;nodeStr.remove(Tools::getInstance()-m_HtmlTitleBegin);nodeStr.remove(Tools::getInstance()-m_HtmlTitleEnd);nodeStr.remove(Tools::getInstance()-m_HtmlTextBegin);nodeStr.remove(Tools::getInstance()-m_HtmlTextEnd);nodeStr.remove(Tools::getInstance()-m_HtmlHiglightBegin);nodeStr.remove(Tools::getInstance()-m_HtmlHiglightEnd);if (nodeStr.contains(targetText)) {list.append(currentNode);}for (TreeNode* child : currentNode-children) {recursiveFindNodeByTextItem(targetText, child, list);}
}7.其他功能
1.关于如何实现的treeview的富文本 重新绘制的富文本当然会比正常文本的资源消耗更高速度较慢实际测试几十万行并不会卡但是比较慢一点日常能接受。
//自定义代理类用来绘制文字富文本
class RichTextDelegate : public QStyledItemDelegate
{
public:RichTextDelegate(QObject* parent nullptr): QStyledItemDelegate(parent){}void paint(QPainter* painter, const QStyleOptionViewItem option, const QModelIndex index) const override;
};
void RichTextDelegate::paint(QPainter *painter, const QStyleOptionViewItem option, const QModelIndex index) const
{QString text index.data(Qt::DisplayRole).toString();QStyleOptionViewItem opt option;initStyleOption(opt, index);painter-save();// 手动绘制背景用于选中和进入的样式if (opt.state QStyle::State_Selected) {// 选中状态下的背景颜色为204, 232, 255QBrush backgroundBrush(QColor(185, 232, 255));painter-fillRect(opt.rect, backgroundBrush);}else if (opt.state QStyle::State_MouseOver) {// 进入状态下的背景颜色为225, 243, 255QBrush backgroundBrush(QColor(235, 243, 255));painter-fillRect(opt.rect, backgroundBrush);}// 手动绘制文本QTextDocument doc;doc.setHtml(text);opt.text ;painter-translate(option.rect.topLeft());doc.drawContents(painter);painter-restore();
}