




已阅读5页,还剩28页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Qt学习笔记-图形视图框架(一)2010-07-11 07:40优点:处理多个图元,单击,拖动,选择图元架构:一个场景,多个图元位于其中,通过视图显示主要应用: 绘图软件,显示地图软件当使用没有变换的视图观察场景时,场景中的一个单元对应屏幕上的一个像素图元坐标通常以图元中心为原点,X轴正方向为向右,Y轴正方向为向下场景坐标的原点在场景中心,X轴正方向为向右,Y轴正方向为向下视图坐标以左上角为原点,X轴正方向为向右,Y轴正方向为向下所有的鼠标事件最开始都是使用视图坐标场景:图元的容器1.提供管理很多图元的接口2.传播事件到图元中3.管理图元状态,例如选择和焦点处理4.提供非转换的绘制功能,主要用于打印QGraphicsScene scene;QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100); / 添加图元QGraphicsItem *item = scene.itemAt(50, 50); / 查询图元/ item = rect;通过QGraphicsScene:setSelectionArea()可以选择场景的任一个图元,QGraphicsScene:setSelectedItems()返回被选择的图元设置焦点图元QGraphicsScene:setFocusItem(), setFocus(),QGraphicsScene:focusItem(), 返回焦点图元视图:一个可视的子部件,可视化场景的内容多个视图可以显示同一个场景坐标转换:QGraphicsView:mapToScene(), QGraphicsView:mapFromScene()图元:支持鼠标事件,滚轮事件,上下文菜单事件支持键盘输入焦点,按键事件支持拖放支持分组冲突探测提供坐标转换,图元与场景,图元与图元之间利用QGraphicsItem:shape()和QGraphicsItem:collidesWith()实现冲突探测,这2个函数都是虚函数相关类:QGraphicsScene, QGraphicsItem, QGraphicsViewQGraphicsItem子类:QGraphicsEllipseItem provides an ellipse itemQGraphicsLineItem provides a line itemQGraphicsPathItem provides an arbitrary path itemQGraphicsPixmapItem provides a pixmap itemQGraphicsPolygonItem provides a polygon itemQGraphicsRectItem provides a rectangular itemQGraphicsSimpleTextItem provides a simple text label itemQGraphicsTextItem provides an advanced text browser itemQGraphicsSvgItem provides a SVG file itemQGraphicsScene:拥有多个图元,包含三层:背景层,图元层,前景层背景层和前景层可以使用QBrush绘制,也可以使用drawBackground(),drawForeground()实现如果使用图片作为背景,可以用texture QBrush(pixmap)实现前景层brush可以使用半透明的白色实现褪色效果,或者使用交叉模式实现网格重叠场景可以告诉我们,哪些图元发生冲突,哪些图元被选择,哪些图元位于一个特定的点或者区域每个图元可以是:1.顶级图元,场景是它的父亲;2.孩子,它的父亲是另一个图元,任何作用于父图元的转换都将自动应用于它的孩子2种分组方式:1.一个图元成为另一个图元的孩子; 2.使用QGraphicsItemGroup。使用分组,可以使位于同一个组的所有图元的操作都相同QGraphicsView:是一个Widget,用于显示一个场景,提供滚动条功能和转换功能,可以缩放和旋转场景。默认使用内建的2D画图引擎,可以使用OpenGL:在构造后,调用setViewport()坐标系统:使用3种坐标系统:viewport, scene, itemviewport: 位于QGraphicsView内部scene: 逻辑坐标用于定位顶级图元item: 与图元相关,以图元的(0,0)为中心,移动图元时,它的坐标不会改变实践中,主要关注场景坐标(定位顶级图元)和图元坐标(定位子图元和绘制图元)在图元自己的坐标系统里面绘图意味着我们不用担心它在场景中的位置和应用于它的坐标转换Demo:/ 主要特点:/ 上下文菜单, 右键菜单/ copy-paste方法/TEMPLATE = appHEADERS = diagramwindow.h link.h node.h propertiesdialog.hSOURCES = diagramwindow.cpp link.cpp main.cpp node.cpp propertiesdialog.cppFORMS = propertiesdialog.uiRESOURCES = resources.qrc/link.h#ifndef LINK_H#define LINK_H#include class Node;class Link : public QGraphicsLineItem / 如果使用信号和槽,采用多继承public QObjectpublic:Link(Node *fromNode, Node *toNode);Link();Node *fromNode() const;Node *toNode() const;void setColor(const QColor &color);QColor color() const;void trackNodes(); / 节点移动时,跟踪节点private:Node *myFromNode; / 连线的2个节点Node *myToNode;#endif/link.cpp#include #include link.h#include node.hLink:Link(Node *fromNode, Node *toNode)myFromNode = fromNode;myToNode = toNode;myFromNode-addLink(this); / 节点增加连线,每个节点有任意多个连线myToNode-addLink(this);setFlags(QGraphicsItem:ItemIsSelectable); / 连线可以被选择,然后删除setZValue(-1); / 在场景中显示的前后层次,因为连线是两个节点的中心,-1表示位于最后面,/ 节点覆盖了部分连线setColor(Qt:darkRed); / 设置线的颜色trackNodes();Link:Link()myFromNode-removeLink(this); / 删除连线时,将删除它在节点中的记录myToNode-removeLink(this);Node *Link:fromNode() constreturn myFromNode;Node *Link:toNode() constreturn myToNode;void Link:setColor(const QColor &color)setPen(QPen(color, 1.0);QColor Link:color() constreturn pen().color();void Link:trackNodes()/ pos()返回节点在场景中或者父图元中的位置setLine(QLineF(myFromNode-pos(), myToNode-pos();/node.h#ifndef NODE_H#define NODE_H#include #include #include #include class Link;class Node : public QGraphicsItemQ_DECLARE_TR_FUNCTIONS(Node) / 在此类中增加tr()功能,直接使用,而不需要QObject:tr()了public:Node();Node();void setText(const QString &text);QString text() const;void setTextColor(const QColor &color);QColor textColor() const;void setOutlineColor(const QColor &color);QColor outlineColor() const;void setBackgroundColor(const QColor &color);QColor backgroundColor() const;void addLink(Link *link);void removeLink(Link *link);QRectF boundingRect() const; / 重新实现,决定一个图元是否需要绘制,必须的QPainterPath shape() const; / 重新实现,返回图元的精确形状,/ 决定一个点是否在图元内,或者2个图元是否发生冲突void paint(QPainter *painter, / 重新实现,画图, 必须的const QStyleOptionGraphicsItem *option, QWidget *widget);protected:void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); / 双击事件,修改节点的文本QVariant itemChange(GraphicsItemChange change, / 重新实现,图元变化时,相关的连线发生变化const QVariant &value); / 没有使用mouseMoveEvent(), / 是因为程序可以改变节点位置private:QRectF outlineRect() const;int roundness(double size) const;QSet myLinks;QString myText;QColor myTextColor;QColor myBackgroundColor;QColor myOutlineColor;#endif/link.cpp#include #include link.h#include node.hNode:Node()myTextColor = Qt:darkGreen;myOutlineColor = Qt:darkBlue;myBackgroundColor = Qt:white;setFlags(ItemIsMovable | ItemIsSelectable); / 节点可以移动,被选择Node:Node()foreach (Link *link, myLinks) / 删除所有的连线,防止边界效应,不使用aDeleteAll()delete link;void Node:setText(const QString &text)prepareGeometryChange(); / 改变节点内的文本时,矩形可能会发生变化myText = text;update();QString Node:text() constreturn myText;void Node:setTextColor(const QColor &color)myTextColor = color;update();QColor Node:textColor() constreturn myTextColor;void Node:setOutlineColor(const QColor &color)myOutlineColor = color;update();QColor Node:outlineColor() constreturn myOutlineColor;void Node:setBackgroundColor(const QColor &color)myBackgroundColor = color;update();QColor Node:backgroundColor() constreturn myBackgroundColor;void Node:addLink(Link *link)myLinks.insert(link); / 增加连线时,记录连线void Node:removeLink(Link *link)myLinks.remove(link);QRectF Node:boundingRect() const / View决定是否绘制矩形const int Margin = 1;return outlineRect().adjusted(-Margin, -Margin, +Margin, +Margin);QPainterPath Node:shape() const / View用于冲突探测QRectF rect = outlineRect();QPainterPath path;path.addRoundRect(rect, roundness(rect.width(),roundness(rect.height();return path;/ 绘制图元void Node:paint(QPainter *painter,const QStyleOptionGraphicsItem *option,QWidget * /* widget */)QPen pen(myOutlineColor);if (option-state & QStyle:State_Selected) / 图元被选择pen.setStyle(Qt:DotLine);pen.setWidth(2);painter-setPen(pen);painter-setBrush(myBackgroundColor);QRectF rect = outlineRect();painter-drawRoundRect(rect, roundness(rect.width(),roundness(rect.height();painter-setPen(myTextColor);painter-drawText(rect, Qt:AlignCenter, myText);/ 双击节点,弹出标准输入对话框void Node:mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)QString text = QInputDialog:getText(event-widget(),tr(Edit Text), tr(Enter new text:),QLineEdit:Normal, myText);if (!text.isEmpty()setText(text);/ 拖动节点时,调用此函数QVariant Node:itemChange(GraphicsItemChange change,const QVariant &value)if (change = ItemPositionHasChanged) foreach (Link *link, myLinks)link-trackNodes();return QGraphicsItem:itemChange(change, value);QRectF Node:outlineRect() constconst int Padding = 8;QFontMetricsF metrics = qApp-font();QRectF rect = metrics.boundingRect(myText);rect.adjust(-Padding, -Padding, +Padding, +Padding);rect.translate(-rect.center();return rect;int Node:roundness(double size) constconst int Diameter = 12;return 100 * Diameter / int(size);/ diagramwindow.h#ifndef DIAGRAMWINDOW_H#define DIAGRAMWINDOW_H#include #include class QAction;class QGraphicsItem;class QGraphicsScene;class QGraphicsView;class Link;class Node;class DiagramWindow : public QMainWindowQ_OBJECTpublic:DiagramWindow();private slots:void addNode();void addLink();void del();void cut();void copy();void paste();void bringToFront();void sendToBack();void properties(); / 弹出属性设置对话框void updateActions(); / 更新菜单栏和工具栏的动作,哪些可用,哪些不可用private:typedef QPair NodePair;void createActions();void createMenus();void createToolBars();void setZValue(int z);void setupNode(Node *node);Node *selectedNode() const;Link *selectedLink() const;NodePair selectedNodePair() const;QMenu *fileMenu;QMenu *editMenu;QToolBar *editToolBar;QAction *exitAction;QAction *addNodeAction;QAction *addLinkAction;QAction *deleteAction;QAction *cutAction;QAction *copyAction;QAction *pasteAction;QAction *bringToFrontAction;QAction *sendToBackAction;QAction *propertiesAction;QGraphicsScene *scene;QGraphicsView *view;int minZ; / sendToBack(), bringToFront()使用int maxZ;int seqNumber; / 唯一标示一个节点的文本;#endif/digramwindow.cpp#include #include diagramwindow.h#include link.h#include node.h#include propertiesdialog.hDiagramWindow:DiagramWindow()scene = new QGraphicsScene(0, 0, 600, 500); / 创建场景,起始点为(0,0), 宽600,高500view = new QGraphicsView;view-setScene(scene); / 显示场景view-setDragMode(QGraphicsView:RubberBandDrag); / 选择多个节点方式:1.按ctrl;2.设置橡皮筋方式view-setRenderHints(QPainter:Antialiasing| QPainter:TextAntialiasing);view-setContextMenuPolicy(Qt:ActionsContextMenu); / 右键菜单setCentralWidget(view);minZ = 0;maxZ = 0;seqNumber = 0;createActions();createMenus();createToolBars();connect(scene, SIGNAL(selectionChanged(),this, SLOT(updateActions();setWindowTitle(tr(Diagram);updateActions();/ 增加一个节点void DiagramWindow:addNode()Node *node = new Node;node-setText(tr(Node %1).arg(seqNumber + 1);setupNode(node);void DiagramWindow:addLink()NodePair nodes = selectedNodePair();if (nodes = NodePair()return;Link *link = new Link(nodes.first, nodes.second);scene-addItem(link);/ 删除选择的图元:首先删除连线,然后删除节点,以防止多次删除同一个连线void DiagramWindow:del()QList items = scene-selectedItems();QMutableListIterator it(items);while (it.hasNext() Link *link = dynamic_cast(it.next();if (link) delete link;it.remove();qDeleteAll(items);/ 剪切操作:先复制,后删除void DiagramWindow:cut()Node *node = selectedNode();if (!node)return;copy();delete node;/ 拷贝操作:值得研究!void DiagramWindow:copy()Node *node = selectedNode();if (!node)return;QString str = QString(Node %1 %2 %3 %4).arg(node-textColor().name().arg(node-outlineColor().name().arg(node-backgroundColor().name().arg(node-text();QApplication:clipboard()-setText(str);void DiagramWindow:paste()QString str = QApplication:clipboard()-text();QStringList parts = str.split( );if (parts.count() = 5 & parts.first() = Node) Node *node = new Node;node-setText(QStringList(parts.mid(4).join( ); / 连接字符串列表node-setTextColor(QColor(parts1);node-setOutlineColor(QColor(parts2);node-setBackgroundColor(QColor(parts3);setupNode(node);void DiagramWindow:bringToFront()+maxZ;setZValue(maxZ); / 改变绘图顺序,首先绘制父图元,然后是子图元,根据子图元Z值的大小,/ 值最小,最先绘制,值最大,最后绘制void DiagramWindow:sendToBack()-minZ;setZValue(minZ);void DiagramWindow:properties()Node *node = selectedNode();Link *link = selectedLink();if (node) PropertiesDialog dialog(node, this);dialog.exec(); else if (link) QColor color = QColorDialog:getColor(link-color(), this);if (color.isValid()link-setColor(color);/ 更新动作使能void DiagramWindow:updateActions()bool hasSelection = !scene-selectedItems().isEmpty();bool isNode = (selectedNode() != 0);bool isNodePair = (selectedNodePair() != NodePair();cutAction-setEnabled(isNode);copyAction-setEnabled(isNode);addLinkAction-setEnabled(isNodePair);deleteAction-setEnabled(hasSelection);bringToFrontAction-setEnabled(isNode);sendToBackAction-setEnabled(isNode);propertiesAction-setEnabled(isNode);foreach (QAction *action, view-actions()view-removeAction(action); / 删除右键菜单foreach (QAction *action, editMenu-actions() if (action-isEnabled()view-addAction(action); / 增加右键菜单void DiagramWindow:createActions()exitAction = new QAction(tr(E&xit), this);exitAction-setShortcut(tr(Ctrl+Q);connect(exitAction, SIGNAL(triggered(), this, SLOT(close();addNodeAction = new QAction(tr(Add &Node), this);addNodeAction-setIcon(QIcon(:/images/node.png);addNodeAction-setShortcut(tr(Ctrl+N);connect(addNodeAction, SIGNAL(triggered(), this, SLOT(addNode();addLinkAction = new QAction(tr(Add &Link), this);addLinkAction-setIcon(QIcon(:/images/link.png);addLinkAction-setShortcut(tr(Ctrl+L);connect(addLinkAction, SIGNAL(triggered(), this, SLOT(addLink();deleteAction = new QAction(tr(&Delete), this);deleteAction-setIcon(QIcon(:/images/delete.png);deleteAction-setShortcut(tr(Del);connect(deleteAction, SIGNAL(triggered(), this, SLOT(del();cutAction = new QAction(tr(Cu&t), this);cutAction-setIcon(QIcon(:/images/cut.png);cutAction-setShortcut(tr(Ctrl+X);connect(cutAction, SIGNAL(triggered(), this, SLOT(cut();copyAction = new QAction(tr(&Copy), this);copyAction-setIcon(QIcon(:/images/copy.png);copyAction-setShortcut(tr(Ctrl+C);connect(copyAction, SIGNAL(triggered(), this, SLOT(copy();pasteAction = new QAction(tr(&Paste), this);pasteAction-setIcon(QIcon(:/images/paste.png);pasteAction-setShortcut(tr(Ctrl+V);connect(pasteAction, SIGNAL(triggered(), this, SLOT(paste();bringToFrontAction = new QAction(tr(Bring to &Front), this);bringToFrontAction-setIcon(QIcon(:/images/bringtofront.png);connect(bringToFrontAction, SIGNAL(triggered(),this, SLOT(bringToFront();sendToBackAction = new QAction(tr(&Send to Back), this);sendToBackAction-setIcon(QIcon(:/images/sendtoback.png);connect(sendToBackAction, SIGNAL(triggered(),this, SLOT(sendToBack();propertiesAction = new QAction(tr(P&roperties.), this);connect(propertiesAction, SIGNAL(triggered(),this, SLOT(properties();void DiagramWindow:createMenus()fileMenu = menuBar()-addMenu(tr(&File);fileMenu-addAction(exitAction);editMenu = menuBar()-addMenu(tr(&Edit);editMenu-addAction(addNodeAction);editMenu-addAction(addLinkAction);editMenu-addAction(deleteAction);editMenu-addSeparator();editMenu-addAction(cutAction);editMenu-addAction(copyAction);editMenu-addAction(pasteAction);editMenu-addSeparator();editMenu-addAction(bringToFrontAction);editMenu-addAction(sendToBackAction);editMenu-addSeparator();editMenu-addAction(propertiesAction);void DiagramWindow:createToolBars()editToolBar = addToolBar(tr(Edit);editToolBar-addAction(addNodeAction);editToolBar-addAction(addLinkAction);editToolBar-addAction(deleteAction);editToolBar-addSeparator();editToolBar-addAction(cutAction);editToolBar-addAction(copyAction);editToolBar-addAction(pasteAction);editToolBar-addSeparator();editToolBar-addAction(bringToFrontAction);editToolBar-addAction(sendToBackAction);void DiagramWindow:setZValue(int z)Node *node = selectedNode();if (node)node-setZValue(z);void DiagramWindow:setupNode(Node *node)node-setPos(QPoint(80 + (100 * (seqNumber % 5),80 + (50 * (seqNumber / 5) % 7);scene-addItem(node);+seqNumber;scene-clearSelection();node-setSelected(true);bringToFront();/ 返回一个选择的节点Node *DiagramWindow:selectedNode() constQList items = scene-selectedItems(); / 全部选择的节点if (items.count() = 1) return dynamic_cast(items.first(); else return 0;Link *DiagramWindow:selectedLink() constQList items = scene-selectedItems();if (items.count() = 1) return dynamic_cast(items.first(); else return 0;/ 返回选择的节点对DiagramWindow:NodePair DiagramWindow:selectedNodePair() constQList items = scene-selectedItems();if (items.count() = 2) Node *first = dynamic_cast(items.first();Node *second = dynamic_cast(items.last();if (first & second)return NodePair(first, second);return NodePair();/ propertiesdialog.h#ifndef PROPERTIESDIALOG_H#define PROPERTIESDIALOG_H#include ui_propertiesdialog.hclass Node;class PropertiesDialog : public QDialog, private Ui:PropertiesDialogQ_OBJECTpublic:PropertiesDialog(Node *node, QWidget *parent = 0);private slots:void on_buttonBox_accepted(); / 快速信号连接void on_textColorButton_clicked();void on_outlineColorButton_clicked();void on_backgroundColorButton_clicked();private:void updateColorLabel(QLabel *label, const QColor &color);void chooseColor(QLabel *label, QColor *color);Node *node;QColor textColor;QColor outlineColor;QColor backgroundColor;#endif/propertiesdialog.cpp#include #include node.h#include propertiesdialog.hPropertiesDialog:PropertiesDialog(Node *node, QWidget *parent): QDialog(parent)setupUi(this);this-node = node;xSpinBox-setValue(int(node-x();ySpinBox
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 七级地理测试题及答案
- 肝功能相关生化检验考核试题及答案
- 上海一家人逆市营销案例分享
- 2025年有机肥料及微生物肥料项目建议书
- 司机职责培训
- 高管股权激励行权协议书(含税务筹划及分红条款)
- 文化节庆活动宣传推广合同
- 食品安全监管维护补充合同
- 滨海栈道防腐木结构安装与保养合作协议
- 生物制药专利技术许可与知识产权保护合同
- 幼儿园红色故事:一封鸡毛信
- 2023年度内蒙古自治区政府采购评审专家资格典型题汇编及答案
- 中职学校招生接待流程
- 机动车检测站2023年评审准则版质量手册程序文件质量记录合集
- 项管系统培训(物资管理)
- 公安技术与警务指挥作业指导书
- 老年危重症患者的护理
- 《隧道测量》课件
- 《痤疮与抗痤疮药》课件
- 《平凡的世界》中孙少平人物形象分析8500字(论文)
- 《结构式家庭疗法提升“丧偶式育儿”家庭亲密度的个案研究》
评论
0/150
提交评论