Qt:QGraphicsScene添加Item

1059 篇文章 285 订阅

 

7f5a079cd3313353802a4ab38ab724b0822.jpg

1、知识点:

/* Item则是具体要显示的东西。最基本的Qt类就是QGraphicsItem,一般如果要显示自定义的形状通常的
 * 做法是继承自QGraphicsItem,然后去实现它的两个纯虚函数boundingRect和paint
 * virtual QRectF boundingRect () const = 0
 * virtual void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ) = 0
 * boundingRect就是返回该Item的包围盒,用于Graphics内部的碰撞检测以及选取等计算。paint则是用于Item的重绘。
*/

2、实现一个item类:

2.1、Sation.h

#ifndef SATION_H
#define SATION_H

#include <QGraphicsItem>

/*新实现一个sation类,这个类可以在scene中用,也可以在mainwindow中用*/
class Sation : public QGraphicsItem
{
public:
    Sation(qreal, qreal);

    void paint(QPainter*,   // // paint虚函数:绘制图标
               const QStyleOptionGraphicsItem*,
               QWidget*
            );
    QRectF boundingRect() const{  // boundingRect虚函数:定义每个图标对应的外部边框
        return QRectF(-6.5, -13, 13, 18);//返回一个矩形:比我们要画的图标稍大
    }
};

#endif //
SATION_H

2.2、sation.cpp

#include "sation.h"

#include <QPainter>

Sation::Sation(qreal x, qreal y):QGraphicsItem()
{
    setPos(x, y);
}
//构造函数里我们根据x和y传递的参数设置坐标。在paint函数绘制我们的电台图标。
void  Sation::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{

    //绘制电台图标,必须小于边框矩形
    painter->setRenderHint( QPainter::Antialiasing );
    painter->setPen( QPen( Qt::black, 2 ) );
    painter->drawRect( -4,  -3,  8,   7 );
    painter->drawLine(  0,  -4,  0, -11 );
    painter->drawLine( -5, -11,  0,  -6 );
    painter->drawLine( +5, -11,  0,  -6 );
}

 

3、在场景类中:

3.1、scene.h

#ifndef SCENE_H
#define SCENE_H

class QGraphicsSceneMouseEvent;

#include <QGraphicsScene>
#include "sation.h"

class Scene : public QGraphicsScene
{
  Q_OBJECT
public:
  Scene( );                       // constructor
signals:
  void  message( QString );                                  // 文本消息信号
protected:
  void  mousePressEvent( QGraphicsSceneMouseEvent* );        // 接收鼠标按下事件
};

#endif // SCENE_H

3.2、scene.cpp


#include "scene.h"

#include <QGraphicsSceneMouseEvent>

Scene::Scene( ) : QGraphicsScene()
{
    addLine( 0, 0, 0, 1, QPen(Qt::transparent, 1) );
    /*在构造函数里我们需要在(0,0)处添加一个不可见的项作为场景的初始锚。
     * 如里没有这样做,Qt默认会把用户添加第一个电台作为左上角定位的锚,
     * 后面添加的电台位置并不是用户所想的。*/
}


void  Scene::mousePressEvent( QGraphicsSceneMouseEvent* event )
{
  // 判断用户是否按下鼠标左键
  if ( event->button() != Qt::LeftButton ) return;

  // 发送信息信号
  qreal  x = event->scenePos().x();
  qreal  y = event->scenePos().y();

  addItem(new Sation(x, y)); // 在用户点击场景的位置新建一个电台
  emit message( QString("Clicked at %1,%2").arg(x).arg(y) );
}

这里是在scene中的鼠标点击位置的x,y用来构造一个sation,也就是将此时左键鼠标点击的x,y作为一个传参初始化一个item,作为sation的的作图坐标原点,画矩形和线

3、mainwindow中:设置view管理scene

3.1、mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "scene.h"

class Scene;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Scene* m_scene;

public slots:   //添加槽方法的定义
  void showMessage( QString );        // 在状态栏上显示消息

};

#endif // MAINWINDOW_H

3.2、mainwindows.cpp中

#include "mainwindow.h"
#include <QMenuBar>
#include <QStatusBar>
#include <QGraphicsView>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    menuBar()->addMenu( "&File" );
    menuBar()->addMenu( "&Edit" );
    menuBar()->addMenu( "&View" );
    menuBar()->addMenu( "&Simulate" );
    menuBar()->addMenu( "&Help" );

    statusBar()->showMessage("QSimulate has started");

    // 创建场景和显示场景的中央视图部件
    m_scene               = new Scene();  //View是视图,负责显示;Scene是文档,负责存储数据。所以从这个角度出发,我们可以这样认为,一个Scene可以关联到多个View,就好比一份数据可以有多个视图去查看它一样。
    QGraphicsView*   view = new QGraphicsView( m_scene ); //QGraphicsScene是一个视图,它不能够单独存在,必须关联到至少一个QGraphicsView
    view->setAlignment( Qt::AlignLeft | Qt::AlignTop );
    view->setFrameStyle( 0 );
    setCentralWidget( view );

    //将信号与槽关联:m_scene发射message信号时,MainWindow接收信号,执行showMessage槽函数
    connect( m_scene, SIGNAL(message(QString)), this, SLOT(showMessage(QString)) );
}

MainWindow::~MainWindow()
{

}

void  MainWindow::showMessage( QString msg )
{
  statusBar()->showMessage( msg );  // 在主窗口状态栏上显示消息
}

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值