📄 tutorial2-06.html
字号:
m_elements[i].setProX( HORIZONTAL_BAR, proX );
m_elements[i].setProY( HORIZONTAL_BAR, proY );
</pre>
<p> 然后我们创建一个CanvasText条目,传递给它在元素矢量中这个元素的索引和所要使用的标签、字体和画布。我们设置文本条目的颜色为用户指定的颜色并且设置条目的x和y位置和画布的宽高成比例。我们设置Z轴顺序为1,这样文本条目总是在条形(Z轴顺序为0)的上面(前面)。我们调用show()函数在画布上绘制文本条目,并且设置元素的相对x和y位置。
<p> <pre> }
y += proheight;
</pre>
<p> 在绘制完条形和可能存在的标签之后,我们给y增加一定比例的高度用来准备绘制下一个元素。
<p> <pre> }
}
}
</pre>
<p> <h2> <a href="qcanvastext.html">QCanvasText</a>的子类
</h2>
<a name="2"></a><p> (由<tt>canvastext.h</tt>展开。)
<p>
<pre> class CanvasText : public <a href="qcanvastext.html">QCanvasText</a>
{
public:
enum { CANVAS_TEXT = 1100 };
CanvasText( int index, QCanvas *canvas )
: <a href="qcanvastext.html">QCanvasText</a>( canvas ), m_index( index ) {}
CanvasText( int index, const <a href="qstring.html">QString</a>& text, QCanvas *canvas )
: <a href="qcanvastext.html">QCanvasText</a>( text, canvas ), m_index( index ) {}
CanvasText( int index, const <a href="qstring.html">QString</a>& text, QFont font, QCanvas *canvas )
: <a href="qcanvastext.html">QCanvasText</a>( text, font, canvas ), m_index( index ) {}
int index() const { return m_index; }
void setIndex( int index ) { m_index = index; }
int rtti() const { return CANVAS_TEXT; }
private:
int m_index;
};
</pre>
<p> 我们的CanvasText子类是<a href="qcanvastext.html">QCanvasText</a>的一个非常简单的特化。我们所做的一切只是添加一个私有成员<tt>m_index</tt>,它用来保存和这个文本相关的元素的元素矢量索引,并且提供为这个值提供一个读和写函数。
<p> <h2> <a href="qcanvasview.html">QCanvasView</a>的子类
</h2>
<a name="3"></a><p> (由<tt>canvasview.h</tt>展开。)
<p>
<pre> class CanvasView : public <a href="qcanvasview.html">QCanvasView</a>
{
<a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
public:
CanvasView( <a href="qcanvas.html">QCanvas</a> *canvas, ElementVector *elements,
<a href="qwidget.html">QWidget</a>* parent = 0, const char* name = "canvas view",
WFlags f = 0 )
: <a href="qcanvasview.html">QCanvasView</a>( canvas, parent, name, f ),
m_elements( elements ) {}
protected:
void viewportResizeEvent( <a href="qresizeevent.html">QResizeEvent</a> *e );
void contentsMousePressEvent( <a href="qmouseevent.html">QMouseEvent</a> *e );
void contentsMouseMoveEvent( <a href="qmouseevent.html">QMouseEvent</a> *e );
void contentsContextMenuEvent( <a href="qcontextmenuevent.html">QContextMenuEvent</a> *e );
private:
<a href="qcanvasitem.html">QCanvasItem</a> *m_movingItem;
<a href="qpoint.html">QPoint</a> m_pos;
ElementVector *m_elements;
};
</pre>
<p> 我们需要继承<a href="qcanvasview.html">QCanvasView</a>,这样我们就能处理:
<ol type=1>
<li> 上下文菜单请求。
<li> 视窗重定义大小。
<li> 用户拖拽标签到任意位置。
</ol>
<p> 为了支持这些,我们存储一个到正在被移动的画布条目的指针和它的最终位置。我们也存储一个到元素矢量的指针。
<p> <h3> 上下文菜单请求
</h3>
<a name="3-1"></a><p> (由<tt>canvasview.cpp</tt>展开。)
<p>
<pre> <a name="x2434"></a>void CanvasView::<a href="qscrollview.html#contentsContextMenuEvent">contentsContextMenuEvent</a>( <a href="qcontextmenuevent.html">QContextMenuEvent</a> * )
{
<a name="x2429"></a> ((ChartForm*)<a href="qobject.html#parent">parent</a>())->optionsMenu->exec( QCursor::<a href="qcursor.html#pos">pos</a>() );
}
</pre>
<p> 当用户调用一个上下文菜单(比如在绝大多数平台通过右键点击),我们把画布视图的父对象(是一个ChartForm)转化为正确的类型,然后用exec()在光标位置执行选项菜单。
<p> <h3> 视窗重定义大小
</h3>
<a name="3-2"></a><p> <pre> <a name="x2437"></a>void CanvasView::<a href="qscrollview.html#viewportResizeEvent">viewportResizeEvent</a>( <a href="qresizeevent.html">QResizeEvent</a> *e )
{
<a name="x2433"></a> <a href="qcanvasview.html#canvas">canvas</a>()->resize( e-><a href="qresizeevent.html#size">size</a>().width(), e-><a href="qresizeevent.html#size">size</a>().height() );
((ChartForm*)<a href="qobject.html#parent">parent</a>())->drawElements();
}
</pre>
<p> 为了改变大小我们简单地改变花布的大小,画布视图就会呈现在视窗客户端区域的宽高中,然后调用drawElements()函数来重新绘制图表。因为drawElements()画的每一件都和画布的宽高有关,所以图表就会被正确地绘制。
<p> <h3> 拖拽标签到任意位置
</h3>
<a name="3-3"></a><p> 当用户想把标签拖拽到他们点击的位置时,就应该拖拽它并在新的位置释放它。
<p> <pre> <a name="x2436"></a>void CanvasView::<a href="qscrollview.html#contentsMousePressEvent">contentsMousePressEvent</a>( <a href="qmouseevent.html">QMouseEvent</a> *e )
{
<a name="x2430"></a> <a href="qcanvasitemlist.html">QCanvasItemList</a> list = <a href="qcanvasview.html#canvas">canvas</a>()->collisions( e-><a href="qmouseevent.html#pos">pos</a>() );
<a name="x2439"></a><a name="x2438"></a> for ( QCanvasItemList::iterator it = list.<a href="qvaluelist.html#begin">begin</a>(); it != list.<a href="qvaluelist.html#end">end</a>(); ++it )
if ( (*it)->rtti() == CanvasText::CANVAS_TEXT ) {
m_movingItem = *it;
m_pos = e-><a href="qmouseevent.html#pos">pos</a>();
return;
}
m_movingItem = 0;
}
</pre>
<p> 当用户点击鼠标时,我们创建一个鼠标点击“碰撞”(如果有的话)的画布条目的列表。然后我们迭代这个列表并且如果我们发现一个<tt>CanvasText</tt>条目,我们就把它设置为移动的条目并且记录下它的位置。否则我们设置为不移动条目。
<p> <pre> <a name="x2435"></a>void CanvasView::<a href="qscrollview.html#contentsMouseMoveEvent">contentsMouseMoveEvent</a>( <a href="qmouseevent.html">QMouseEvent</a> *e )
{
if ( m_movingItem ) {
<a href="qpoint.html">QPoint</a> offset = e-><a href="qmouseevent.html#pos">pos</a>() - m_pos;
<a name="x2432"></a><a name="x2431"></a> m_movingItem->moveBy( offset.<a href="qpoint.html#x">x</a>(), offset.<a href="qpoint.html#y">y</a>() );
m_pos = e-><a href="qmouseevent.html#pos">pos</a>();
ChartForm *form = (ChartForm*)<a href="qobject.html#parent">parent</a>();
form->setChanged( true );
int chartType = form->chartType();
CanvasText *item = (CanvasText*)m_movingItem;
int i = item->index();
(*m_elements)[i].setProX( chartType, item->x() / canvas()->width() );
(*m_elements)[i].setProY( chartType, item->y() / canvas()->height() );
<a href="qcanvasview.html#canvas">canvas</a>()->update();
}
}
</pre>
<p> 当用户拖拽鼠标的时候,移动事件就产生了。如果那里是一个可移动条目,我们从鼠标最后的位置和可移动条目原来的位置计算出位移。我们将新的位置记录为最后的位置。因为图表现在改变了,所以我们调用setChanged(),这样当用户试图退出或者读入已存在的图表时或者创建新的图表,就会被提示是否保存。我们也分别地更新当前图表类型的元素的x和y的比例位置为当前x和y与宽和高的比例。我们知道要更新哪个元件因为当我们创建每个画布文本条目的时候,我们传给它一个这个元素所对应的位置索引。我们继承了<a href="qcanvastext.html">QCanvasText</a>,这样我们就可以设置和读取这个索引值。最后我们调用update()来重绘画布。
<p> <center><table cellpadding="4" cellspacing="2" border="0">
<tr bgcolor="#f0f0f0">
<td valign="top"><a href="qcanvas.html">QCanvas</a>没有任何视觉效果。为了看到画布的内容,你必须创建一个<a href="qcanvasview.html">QCanvasView</a>来呈现画布。如果条目被show()显示,它们就会出现在画布视图中,然后,只有当<a href="qcanvas.html#update">QCanvas::update</a>()被调用的时候。默认情况下QCanva的背景是白色,并且会在画布上绘制默认的形状,比如<a href="qcanvasrectangle.html">QCanvasRectangle</a>、<a href="qcanvasellipse.html">QCanvasEllipse</a>等等,因为它们被白色填充,所以非常推荐使用一个非白色的画刷颜色!
</table></center>
<p> <p align=right>
<a href="tutorial2-05.html">« 实现图形用户界面</a> |
<a href="tutorial2.html">目录</a> |
<a href="tutorial2-07.html">文件处理 »</a>
</p>
<p>
<!-- eof -->
<p><address><hr><div align=center>
<table width=100% cellspacing=0 border=0><tr>
<td>Copyright © 2002
<a href="http://www.trolltech.com">Trolltech</a>
<td><a href="http://www.trolltech.com/trademarks.html">Trademarks</a>
<td><a href="zh_CN.html">译者:Cavendish</a>
<td align=right><div align=right>Qt 3.0.5版</div>
</table></div></address></body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -