QT——菜单栏和工具栏

添加

添加菜单栏

QMainWindow类下有一个menuBar()方法,此方法返回主窗口的菜单栏QMenuBar。

QMenuBar *QMainWindow::menuBar() const

QMenuBar类提供了一个水平菜单栏,菜单栏由一个下拉菜单项列表组成。您可以使用addMenu()添加菜单项,返回一个菜单小部件QMenu。
菜单小部件是一个选择菜单。它可以是菜单栏中的下拉菜单,也可以是独立的上下文菜单。当用户单击相应的项目或按下指定的快捷键时,下拉菜单就会显示在菜单栏上。

QMenu *QMenuBar::addMenu(const QString &title)

菜单小部件QMenu使用addAction()方法可以生成新的动作到下拉菜单中。动作使用QAction类生成,

QAction::QAction(const QString &text, QObject *parent = nullptr)
void addAction(QAction *action);

连贯代码:

QMenuBar *menubar = menuBar();
QMenu *fileMenu = menubar->addMenu("文件(F)");
QAction *new_file = new QAction(tr("新建文件或项目(N)"));
fileMenu->addAction(new_file);

添加工具栏

工具栏按钮(QAction对象)是通过使用addAction()添加操作来添加,当工具栏按钮被按下时,它会发出actionTriggered()信号。

QToolBar *fileToolBar = new QToolBar(this);
QAction *open = new QAction(tr("open"),this);
fileToolBar->addAction(open);

场景——QGraphicsScene

QGraphicsScene类提供了一个用于管理大量2D图形项的表面。该类用作QGraphicsItems的容器。它与QGraphicsView一起使用,用于在2D表面上可视化图形项,如线、矩形、文本,甚至自定义项。
场景坐标的原点在场景的中心,x轴正方向向右,y轴正方向向下。

QGraphicsScene没有自己的视觉外观,它只管理项目。您需要创建一个QGraphicsView小部件来可视化场景。

QGraphicsScene scene;
scene.addText("Hello, world!");

QGraphicsView view(&scene);
view.show();

要向场景添加项,首先要构造一个QGraphicsScene对象。然后,您有两个选项:通过调用addItem()添加现有的QGraphicsItem对象,或者可以调用一个方便的函数addEllipse()、addLine()、addPath()、addPixmap()、addPolygon()、addRect()或addText(),它们都返回指向新添加的项目的指针。使用这些函数添加的项目的尺寸是相对于项目的坐标系统的,项目的位置在场景中初始化为(0,0)。

  • 设置场景大小——setSceneRect
void setSceneRect(qreal x, qreal y, qreal w, qreal h)//x,y 是左上角坐标,w、h为实际宽高
  • 加入图元
void QGraphicsScene::addItem(QGraphicsItem *item);

视图——QGraphicsView

QGraphicsView类提供了一个用于显示QGraphicsScene内容的小部件,要可视化一个场景,首先要构造一个QGraphicsView对象,将您想要可视化的场景的地址传递给QGraphicsView的构造函数。或者,您可以调用setScene(),将场景传递进去。
视图的坐标就是窗口部件的坐标。视图坐标的每一个单位对应一个像素。QGraphicsView视图的左上角是(0,0),x轴正方向向右,y轴正方向向下。

void QGraphicsView::setScene(QGraphicsScene *scene);

在你调用show()之后,默认情况下视图会滚动到场景的中心,并显示当前可见的任何项目。

 void QGraphicsView::show();

设置视图显示的最小宽、高

void setMinimumSize(const QSize &);
void setMinimumSize(int minw, int minh);
void setMaximumSize(const QSize &);
void setMaximumSize(int maxw, int maxh);
void setMinimumWidth(int minw);
void setMinimumHeight(int minh);
void setMaximumWidth(int maxw);
void setMaximumHeight(int maxh);

将生成显示的场景设置为主窗口的中心小部件,将视图传递进去即可。

void setCentralWidget(QWidget *widget);

主窗口的中心显示区域可调整大小,设置标题

inline void QWidget::resize(int w, int h);
void setWindowTitle(const QString &);

图元——QGraphicsItem

图形视图(Graphics View)内置了一下图元:直线图元(QGraphicsLineItem)、椭圆图元(QGraphicsEllipseItem)、多边形图元(QGraphicsPolygonItem)、文本图元(QGraphicsTextItem)、图片图元(QGraphicsPixmapItem)、矩形图元(QGraphicsRectItem)。用户也可以继承QGraphicsItem实现符合自己需要的图元。
图形项使用自己的本地坐标,这个坐标系统通常以图形项中心为原点,这也是所有变换的原点。图形项坐标方向是x轴正方向向右,y轴正方向向下。

常用方法作用
void setVisible(bool visible)是否可见
bool isVisible()判断图元是否可见
void show()展示图元,等价setVisible(true)
void hide()隐藏图元,等价setVisible(false)

图片图元

生成QGraphicsPixmapItem实例两种方式,但参数都是QPixmap对象。

//利用构造函数
QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = nullptr)
//利用setPixmap方法
void QGraphicsPixmapItem::setPixmap(const QPixmap &pixmap)
常用方法作用
setOffset(qreal x, qreal y)设置偏移量,相对于左上
QPointF offset()返回偏移量

所以我们要先生成QPixmap才可以生成图片图元,

//通过构造函数
QPixmap(int width, int height);
QPixmap(const QSize &size);
QPixmap(const QString &fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor)
QPixmap(const QPixmap &pixmap)
//通过QImage对象
[static] QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor)

  • 图片来源:
  1. 本地图片路径
  2. opencv的对象——Mat
  3. QImage对象

如果图片来源是opencv的mat对象,我们就需要将Mat ⟹ \Longrightarrow QImage ⟹ \Longrightarrow QPixmap ⟹ \Longrightarrow QGraphicsPixmapItem。

//Mat转QImage
QImage image(mat.data, 
			 mat.cols, 
			 mat.rows, 
			 mat.step, 
			 QImage::Format_RGB888);
//QImage转Mat
Mat mat = Mat(image.height(), 
			  image.width(), 
			  CV_8UC(3), 
			  image.bits(),
			  image.bytesPerLine());
QImage

QImage生成方式如下:

//构造函数
QImage(const QString &fileName);
QImage(uchar *data, int width, int height, QImage::Format format);
QImage(const QImage &image);
//静态方法
fromData(const uchar *data, int size, const char *format = nullptr)

因为OpenCv 加载BGR格式,QImage加载的是RGB格式,所以有有时需要进行通道改变。

常用方法作业
QImage rgbSwapped()RGB图像转换为BGR图像
bool save(const QString &fileName)保存图片
bool isNull()图片是否为空
int height()返回图片高度
int width()返回图片宽度
int depth()返回图片位数,即单个像素的比特数

椭圆图元——QGraphicsEllipseItem

QGraphicsEllipseItem 表示一个带有填充和轮廓的椭圆,要设置 item 的椭圆,可以传递一个 QRectF 到QGraphicsEllipseItem 的构造函数,或使用setRect()

explicit QGraphicsEllipseItem(QGraphicsItem *parent = nullptr);
explicit QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = nullptr);
explicit QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = nullptr);
void QGraphicsEllipseItem::setRect(const QRectF &rect);
inline void QGraphicsEllipseItem::setRect(qreal x, qreal y, qreal w, qreal h);
//第一种
QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0, 0, 80, 60));
//第二种
QGraphicsEllipseItem *item = new QGraphicsEllipseItem;
item->setRect(QRectF(0, 0, 80, 60));

设置画笔、画刷

void setPen(const QPen &pen); //椭圆边界的类型
void setBrush(const QBrush &brush);//椭圆填充的颜色

笔的类型有很多,Qt::NoPen表示无边界。

  • 设置图元支持的操作
void setFlag(GraphicsItemFlag flag, bool enabled = true);
flag说明
QGraphicsItem::ItemIsMovable支持拖动
QGraphicsItem::ItemIsSelectable支持被选中
QGraphicsItem::ItemIsFocusable支持键盘输入焦点,允许向QGraphicsItem::keyPressEvent()和QGraphicsItem::keyReleaseEvent()传递键事件
  • 设置图元的场景坐标

场景坐标的原点在中心

inline void QGraphicsItem::setPos(qreal ax, qreal ay)
  • 重绘图元

这个函数不会立即绘制,相反,它调度一个绘制请求,该请求在控件到达事件循环后由QGraphicsView处理,其会调用paint方法绘制。

void QGraphicsItem::update(const QRectF &rect = QRectF());
inline void QGraphicsItem::update(qreal x, qreal y, qreal width, qreal height);

文本图元——QGraphicsTextItem

QGraphicsTextItem::QGraphicsTextItem(const QString &text, QGraphicsItem *parent = nullptr)
  • 设置字体

字体定义使用QFont,设置使用setFont()

QFont::QFont(const QString &family, int pointSize = -1, int weight = -1, bool italic = false)
void QGraphicsItem::setFont(const QFont &font);
  • 设置颜色
void QGraphicsItem::setDefaultTextColor(const QColor &c);
  • 设置文本宽度

如果实际文本比指定的宽度宽,那么它将被分割成多行。如果width设置为-1,那么文本不会被分割成多行,除非通过显式换行或新的段落来强制。缺省值为-1。

void QGraphicsItem::setTextWidth(qreal width);

自定义图元

定制图元类就是子类化QGraphicsItem,继承QGraphicsItem类必须重写QGraphicsItem的两个纯虚函数boundingRect和paint,前者用来指定图元的外边界,该函数返回值是一个矩形(QRectF),后者是用来绘制图元的,绘制基于图元坐标系进行。

[pure virtual] QRectF QGraphicsItem::boundingRect() const
[pure virtual] void QGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = ...)
  • 自定义闪烁圆

定时器的启动startTimer、接收定时器事件timerEvent

int QObject::startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);//返回计时器标识符,interval单位为毫秒
void QObject::killTimer(int id)//取消定时器
[virtual protected] void QObject::timerEvent(QTimerEvent *event)//接收对象的计时器事件
event->timerId() //返回该事件对应的定时器的id
  • 自定义移动的图

QGraphicsItemAnimation类为QGraphicsItem提供了简单的动画支持,通常使用带有QTimeLine的类来做变化,动画时间轴是通过setTimeLine()函数设置的。

QTimeLine类提供了一个控制动画的时间线,单位毫秒,然后通过调用setFrameRange()来设置合适的帧范围。

交互——信号和槽

connect

sender:发送信号的对象
signal:信号
receiver:接受信号的对象
slot:受到信号后调用的函数(槽函数)

connect(sender, signal, receiver, slot);

自定义信号和槽

1、信号和槽函数返回值是 void
2、信号只需要声明,不需要实现
3、槽函数需要声明也需要实现
4、任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
5、信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少。

  • 信号
signals:
	void sig1();

在头文件中初始化

public slots:
    void slot1();
  • 连接
connect(sender, SIGNAL(sig1()), receiver, SIGNAL(slot1()));

源码

---------------------mainwindow.h----------------------------------------
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMenuBar>
#include <QToolBar>
#include <QGraphicsEllipseItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include "twinkle_circle.h"
#include "butterfly.h"
#include <QDebug>
#include <QGraphicsItemAnimation>
#include <QTimeLine>
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void createMenus();
    //创建主窗体的所有动作
    void createActions();
public slots:
    void slotAddEllipseItem();
    void slotAddTextItem();
    void slotAddFlashItem();
    void slotAddButtflyItem();
    void slotAddBlingItem();
private:
    QPixmap pixmap;
    QGraphicsScene *scene;
    QAction *ellipse;
    QAction *text;
    QAction *undo;
    QAction *paste;
    QAction *open;
    QAction *close;
    QAction *bling;
};
#endif // MAINWINDOW_H
---------------------mainwindow.cpp----------------------------------------
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    //创建主窗体的所有动作
    createActions();
    //创建主窗体的菜单栏
    createMenus();
    scene = new QGraphicsScene; //场景初始化
    //setSceneRect(-width/2,-height/2,width,height)
    scene->setSceneRect(-200, -200, 400, 400);
    QGraphicsView *view = new QGraphicsView; //不加括号调用默认构造函数或唯一的构造函数
    view->setScene(scene);
    view->setMinimumSize(400, 400);
    view->show();
    setCentralWidget(view);//将给定的小部件设置为主窗口的中心小部件,即将场景窗口设置为主界面的窗口
    resize(550, 450);
    setWindowTitle(tr("视图框架试验"));

}

MainWindow::~MainWindow()
{

}
void MainWindow::slotAddEllipseItem()
{
    /*
    QGraphicsEllipseItem表示一个带有填充和轮廓的椭圆,您也可以将其用于椭圆段
    可以通过调用setPen()和setBrush()来设置
*/
    //在场景中加入椭圆形图元
    //QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0, 0, 80, 60));
    QGraphicsEllipseItem *item = new QGraphicsEllipseItem;
    item->setRect(QRectF(0,0, 80, 60));
    item->setPen(Qt::NoPen);
    item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    scene->addItem(item);
    //设置场景坐标
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}
void MainWindow::createMenus(){
    QMenuBar *menubar = menuBar();
    QMenu *fileMenu = menubar->addMenu("添加(F)");
    //QMenu *fileMenu = menuBar()->addMenu((tr("文件(F)")));
    //menuBar()返回QMenuBar对象,此对象通过addMenu添加菜单项,返回QMenu对象
    fileMenu->addAction(ellipse);
    fileMenu->addSeparator();
    fileMenu->addAction(text);
    fileMenu->addAction(bling);
    QMenu *edit = menuBar()->addMenu(tr("编辑(E)"));
    edit->addAction(undo);
    edit->addSeparator();
    edit->addAction(paste);
    open = new QAction(tr("open"),this);
    close = new QAction(tr("close"),this);
}
void MainWindow::createActions(){
    ellipse = new QAction(tr("插入椭圆"),this);
    connect(ellipse,SIGNAL(triggered()),this,SLOT(slotAddEllipseItem()));
    text = new QAction(tr("插入文本"));
    connect(text,SIGNAL(triggered()),this,SLOT(slotAddTextItem()));
    undo = new QAction(tr("插入闪烁圆"));
    connect(undo,SIGNAL(triggered()),this,SLOT(slotAddFlashItem()));
    paste = new QAction(tr("插入图片"));
    connect(paste,SIGNAL(triggered()),this,SLOT(slotAddButtflyItem()));
    bling = new QAction(tr("插入移动图片"));
    connect(bling,SIGNAL(triggered()),this,SLOT(slotAddBlingItem()));
}
void MainWindow::slotAddTextItem()
{
    //在场景中添加一个文字图元
    QFont font("Times", 14);
    QGraphicsTextItem *item = new QGraphicsTextItem("你好,QT");
    item->setFont(font);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setTextWidth(80);
    item->setDefaultTextColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddFlashItem()
{
    //添加闪烁图元
    twinkle_circle *item = new twinkle_circle;
    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddButtflyItem()
{
    if (pixmap.load("G:\\QT_Creater\\Newyear2021\\Butterfly\\003.jpg")){
        qDebug()<<"下载图片成功";
    }
    else{
         qDebug()<<"下载图片失败";
    }
    QGraphicsPixmapItem *item =scene->addPixmap(pixmap);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setPos((qrand()%int(scene->sceneRect().width()))-200,(qrand()%int(scene->sceneRect().height()))-200);
}
void MainWindow::slotAddBlingItem(){
    butterfly *item = new butterfly;
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;
    anim->setItem(item);
    QTimeLine *timeLine = new QTimeLine(4000);
    timeLine->setCurveShape(QTimeLine::SineCurve);//保存时间线曲线的形状
    timeLine->setLoopCount(-1);
    //属性保存了动画的循环计数此属性将动画的循环计数描述为一个整数。默认情况下,这个值是1,表示动画应该只运行一次,然后停止。
    //通过改变它,你可以让动画循环几次。如果值为-1,动画将根本不会运行,如果值为0,动画将永远循环直到停止。
    anim->setTimeLine(timeLine);
    int y = (qrand() % 400) - 200;
    for(int i = 0; i < 400; i++)
    {
        anim->setPosAt(i/400.0, QPointF(i-200, y));
    }
    timeLine->start();
    //启动时间。QTimeLine将进入运行状态,一旦进入事件循环,它将定期更新当前时间、帧和值。默认间隔是40毫秒(即每秒25次)。
    //您可以通过调用setUpdateInterval()来更改更新间隔。
    scene->addItem(item);
}
---------------------butterfly.h----------------------------------------
#ifndef BUTTERFLY_H
#define BUTTERFLY_H

#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
class butterfly:public QObject,public QGraphicsItem
{
public:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
    QRectF boundingRect() const;
    butterfly();
private:
    QPixmap pix;
};

#endif // BUTTERFLY_H
---------------------butterfly.cpp----------------------------------------
#include "butterfly.h"

butterfly::butterfly()
{
    pix.load("G:\\QT_Creater\\Newyear2021\\Butterfly\\003.jpg");
}

void butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    painter->drawPixmap(boundingRect().topLeft(), pix);
}

QRectF butterfly::boundingRect() const{
    return QRectF(-pix.width()/2, -pix.height()/2, pix.width(), pix.height());
}
---------------------twinkle_circle.h----------------------------------------
#ifndef TWINKLE_CIRCLE_H
#define TWINKLE_CIRCLE_H

#include <QObject>
#include <QGraphicsItem>
#include <QPainter>
#include <QTimer>
class twinkle_circle:public QObject,public QGraphicsItem
{
public:
    twinkle_circle();
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
    QRectF boundingRect() const;
    void timerEvent(QTimerEvent *event);
private:
    bool flag;
};

#endif // TWINKLE_CIRCLE_H

---------------------twinkle_circle.cpp----------------------------------------
#include "twinkle_circle.h"

twinkle_circle::twinkle_circle()
{
    flag = true;
    setFlag(QGraphicsItem::ItemIsMovable);
    startTimer(1000);

}

void twinkle_circle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    painter->setPen(Qt::NoPen);
    painter->setBrush(Qt::darkGray);//深灰色
    //
    painter->drawEllipse(-20,-20, 50, 50);
    painter->setPen(QPen(Qt::black, 0));

    painter->setBrush(flag ? (Qt::red) : (Qt::yellow));
    painter->drawEllipse(-20,-20, 50,50);
}

QRectF twinkle_circle::boundingRect() const{
    qreal adjust = 2;
    return QRectF(-30-adjust, -30-adjust, 60 + adjust, 60 + adjust);
}

void twinkle_circle::timerEvent(QTimerEvent *event){
    flag = !flag;
    update();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值