Qt 实现自定义截图工具

目录

  • Qt 实现自定义截图工具
    • 实现效果图
    • PrintScreen 类介绍
      • PrintScreen 类的主要特性
    • 逐步实现
      • 第一步:类定义
      • 第二步:初始化截图窗口
      • 第三步:处理鼠标事件
      • 第四步:计算截图区域
      • 第五步:捕获和保存图像
    • 完整代码
      • PrintScreen.h
      • PrintScreen.cpp
      • MainWindow.h
      • MainWindow.cpp
      • main.cpp

Qt 实现自定义截图工具

本文使用Qt框架从头开始创建一个简单的屏幕截图工具。

实现效果图

截图按钮:
截图按钮
选取截图初始状态:
选取截图初始状态
选取截图区域:
选取截图区域
截图保存界面:
截图保存界面

PrintScreen 类介绍

PrintScreen 类是一个自定义的 QWidget,允许用户捕捉屏幕上的任意区域。本教程将展示如何利用 Qt 的多功能库来实现这一功能。

PrintScreen 类的主要特性

  • 全屏覆盖,用于选择要捕捉的屏幕区域。
  • 通过鼠标互动选择定义捕捉区域。
  • 拖放调整选定区域。
  • 将捕获的区域保存为图片文件。

逐步实现

第一步:类定义

首先定义继承自 QWidgetPrintScreen 类。包含必要的 Qt 头文件,并声明我们的函数和成员变量。

#include <QWidget>
#include <QPainter>/*** @brief The PrintScreen class* @param 区域截屏功能*/
class PrintScreen : public QWidget
{Q_OBJECT
public:PrintScreen(QWidget *parent = nullptr);~PrintScreen();private:/*** @brief 初始化截图窗口的背景和尺寸*/void InitWindow();/*** @brief 根据起始点和终止点计算矩形区域* @param beginPoint 矩形区域的起始点* @param endPoint 矩形区域的终止点* @return 返回根据两点计算出的 QRect 对象*/QRect GetRect(const QPoint &beginPoint, const QPoint &endPoint);protected:// 事件处理方法void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent *event);void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);private:// 成员变量bool m_isMousePress = false;     // 是否按下鼠标bool m_captureComplete = false;  // 截图是否完成bool m_isDragging = false;       // 是否正在拖动截图区域QPixmap m_loadPixmap;    // 加载的屏幕截图QPixmap m_capturePixmap; // 截取的屏幕区域int m_screenWidth;       // 屏幕宽度int m_screenHeight;      // 屏幕高度QPoint m_beginPoint;     // 截图开始点QPoint m_endPoint;       // 截图结束点QPoint m_originalBegin;  // 原始截图开始点QPoint m_originalEnd;    // 原始截图结束点QPoint m_dragPosition;   // 拖动时的鼠标位置QPainter m_painter;      // 绘图器对象
};

第二步:初始化截图窗口

InitWindow 方法设置窗口属性,如全屏模式、无边框窗口提示和鼠标跟踪。它还捕获整个屏幕并存储在 m_loadPixmap 中。

void PrintScreen::InitWindow()
{// 启用鼠标跟踪this->setMouseTracking(true);// 设置无边框窗口this->setWindowFlags(Qt::FramelessWindowHint);// 设置窗口为激活状态和全屏模式setWindowState(Qt::WindowActive | Qt::WindowFullScreen);// 确保关闭时自动删除setAttribute(Qt::WA_DeleteOnClose);// 获取主屏幕QScreen *screen = QApplication::primaryScreen();// 抓取整个屏幕内容m_loadPixmap = screen->grabWindow(QApplication::desktop()->winId());// 设置屏幕宽度、高度m_screenWidth = m_loadPixmap.width();m_screenHeight = m_loadPixmap.height();
}

第三步:处理鼠标事件

鼠标事件对于定义捕获区域至关重要。mousePressEventmouseMoveEventmouseReleaseEvent 处理捕获区域的开始、调整和最终确定。

void PrintScreen::mousePressEvent(QMouseEvent *event)
{// 按下右键 关闭截图窗口if (event->button() == Qt::RightButton){close();}// 按下左键else if (event->button() == Qt::LeftButton){if (m_captureComplete && QRect(m_beginPoint, m_endPoint).contains(event->pos())){m_isDragging = true;                          // 开始拖动m_dragPosition = event->pos() - m_beginPoint; // 计算开始拖动位置}else{m_isMousePress = true;       // 鼠标被按下m_isDragging = false;m_beginPoint = event->pos(); // 记录开始点m_originalBegin = m_beginPoint;}}
}void PrintScreen::mouseMoveEvent(QMouseEvent *event)
{// 获取屏幕尺寸QRect screenRect = QGuiApplication::primaryScreen()->geometry();// 鼠标按下且截图未完成if (m_isMousePress && !m_captureComplete){// 确保终点坐标不超过屏幕范围int x = qBound(screenRect.left(), event->pos().x(), screenRect.right());int y = qBound(screenRect.top(), event->pos().y(), screenRect.bottom());m_endPoint = QPoint(x, y);}// 正在拖动else if (m_isDragging){QPoint newTopLeft = event->pos() - m_dragPosition;// 确保新的顶点坐标不超过屏幕范围int x = qBound(screenRect.left(), newTopLeft.x(), screenRect.right() - m_dragPosition.x());int y = qBound(screenRect.top(), newTopLeft.y(), screenRect.bottom() - m_dragPosition.y());newTopLeft = QPoint(x, y);QPoint offset = newTopLeft - m_beginPoint;m_beginPoint += offset;m_endPoint += offset;}update();return QWidget::mouseMoveEvent(event);
}void PrintScreen::mouseReleaseEvent(QMouseEvent *event)
{// 鼠标释放且截图未完成if (m_isMousePress && !m_captureComplete){m_endPoint = event->pos();  // 设置结束点m_isMousePress = false;     // 重置鼠标按下状态m_captureComplete = true;   // 标记截图完成update();}// 释放时正在拖动else if (m_isDragging){m_isDragging = false;}update();
}

第四步:计算截图区域

GetRect 方法接收两个参数:beginPointendPoint,这两个点是用户通过鼠标操作定义的截图区域的开始和结束位置。此方法用于计算并返回一个 QRect 对象,该对象表示屏幕上要截取的矩形区域。

QRect PrintScreen::GetRect(const QPoint &beginPoint, const QPoint &endPoint)
{int x = std::min(beginPoint.x(), endPoint.x());int y = std::min(beginPoint.y(), endPoint.y());int width = std::abs(beginPoint.x() - endPoint.x());int height = std::abs(beginPoint.y() - endPoint.y());if (width == 0) width = 1;   // 确保宽度至少为1像素if (height == 0) height = 1; // 确保高度至少为1像素return QRect(x, y, width, height);
}

解释:

  • 计算 x 和 y 坐标:使用 std::min 函数确定矩形的左上角 x 和 y 坐标,这保证了无论用户如何拖动鼠标(从左到右或从右到左),都能正确计算出矩形的位置。
  • 计算宽度和高度:使用 std::abs 函数计算宽度和高度,确保值总是正数。如果计算结果为0(即起点和终点在同一直线上),则将宽度或高度设为1像素,确保矩形至少有最小的可见尺寸。

第五步:捕获和保存图像

paintEvent 方法在屏幕上绘制捕获的区域。keyPressEvent 监听回车键以触发保存捕获的图像。

void PrintScreen::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)m_painter.begin(this);                                           // 开始绘制QColor shadowColor(0, 0, 0, 100);                                // 半透明遮罩颜色m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap)); // 设置画笔m_painter.drawPixmap(0, 0, m_loadPixmap);                        // 绘制加载的屏幕截图m_painter.fillRect(m_loadPixmap.rect(), shadowColor);            // 绘制半透明遮罩QRect selectedRect = GetRect(m_beginPoint, m_endPoint);          // 获取选择区域m_capturePixmap = m_loadPixmap.copy(selectedRect);               // 截取选择区域的屏幕截图m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);   // 绘制截取的区域m_painter.drawRect(selectedRect);                                // 绘制选择区域的边框m_painter.end();                                                 // 结束绘制
}
void PrintScreen::keyPressEvent(QKeyEvent *event)
{// 按下回车键if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return){// 保存图片QString filePath = QFileDialog::getSaveFileName(nullptr, "保存图片",QString(),"Images (*.png *.jpg)");if(!filePath.isEmpty()){m_capturePixmap.save(filePath); // 保存截图到文件}close();}
}

完整代码

PrintScreen.h

#ifndef PRINTSCREEN_H
#define PRINTSCREEN_H#include <QWidget>
#include <QPainter>/*** @brief The PrintScreen class* @param 区域截屏功能*/
class PrintScreen : public QWidget
{Q_OBJECT
public:PrintScreen(QWidget *parent = nullptr);~PrintScreen();private:/*** @brief 初始化截图窗口的背景和尺寸*/void InitWindow();/*** @brief 根据起始点和终止点计算矩形区域* @param beginPoint 矩形区域的起始点* @param endPoint 矩形区域的终止点* @return 返回根据两点计算出的 QRect 对象*/QRect GetRect(const QPoint &beginPoint, const QPoint &endPoint);protected:// 事件处理方法void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent *event);void keyPressEvent(QKeyEvent *event);void paintEvent(QPaintEvent *event);private:// 成员变量bool m_isMousePress = false;     // 是否按下鼠标bool m_captureComplete = false;  // 截图是否完成bool m_isDragging = false;       // 是否正在拖动截图区域QPixmap m_loadPixmap;    // 加载的屏幕截图QPixmap m_capturePixmap; // 截取的屏幕区域int m_screenWidth;       // 屏幕宽度int m_screenHeight;      // 屏幕高度QPoint m_beginPoint;     // 截图开始点QPoint m_endPoint;       // 截图结束点QPoint m_originalBegin;  // 原始截图开始点QPoint m_originalEnd;    // 原始截图结束点QPoint m_dragPosition;   // 拖动时的鼠标位置QPainter m_painter;      // 绘图器对象
};#endif // PRINTSCREEN_H

PrintScreen.cpp

#include "PrintScreen.h"#include <QScreen>
#include <QFileDialog>
#include <QMouseEvent>
#include <QApplication>
#include <QDesktopWidget>PrintScreen::PrintScreen(QWidget *parent): QWidget{parent}
{InitWindow();
}PrintScreen::~PrintScreen(){}void PrintScreen::InitWindow()
{// 启用鼠标跟踪this->setMouseTracking(true);// 设置无边框窗口this->setWindowFlags(Qt::FramelessWindowHint);// 设置窗口为激活状态和全屏模式setWindowState(Qt::WindowActive | Qt::WindowFullScreen);// 确保关闭时自动删除setAttribute(Qt::WA_DeleteOnClose);// 获取主屏幕QScreen *screen = QApplication::primaryScreen();// 抓取整个屏幕内容m_loadPixmap = screen->grabWindow(QApplication::desktop()->winId());// 设置屏幕宽度、高度m_screenWidth = m_loadPixmap.width();m_screenHeight = m_loadPixmap.height();
}QRect PrintScreen::GetRect(const QPoint &beginPoint, const QPoint &endPoint)
{int x = std::min(beginPoint.x(), endPoint.x());int y = std::min(beginPoint.y(), endPoint.y());int width = std::abs(beginPoint.x() - endPoint.x());int height = std::abs(beginPoint.y() - endPoint.y());if (width == 0) width = 1;   // 确保宽度至少为1像素if (height == 0) height = 1; // 确保高度至少为1像素return QRect(x, y, width, height);
}void PrintScreen::mousePressEvent(QMouseEvent *event)
{// 按下右键 关闭截图窗口if (event->button() == Qt::RightButton){close();}// 按下左键else if (event->button() == Qt::LeftButton){if (m_captureComplete && QRect(m_beginPoint, m_endPoint).contains(event->pos())){m_isDragging = true;                          // 开始拖动m_dragPosition = event->pos() - m_beginPoint; // 计算开始拖动位置}else{m_isMousePress = true;       // 鼠标被按下m_isDragging = false;m_beginPoint = event->pos(); // 记录开始点m_originalBegin = m_beginPoint;}}
}void PrintScreen::mouseMoveEvent(QMouseEvent *event)
{// 获取屏幕尺寸QRect screenRect = QGuiApplication::primaryScreen()->geometry();// 鼠标按下且截图未完成if (m_isMousePress && !m_captureComplete){// 确保终点坐标不超过屏幕范围int x = qBound(screenRect.left(), event->pos().x(), screenRect.right());int y = qBound(screenRect.top(), event->pos().y(), screenRect.bottom());m_endPoint = QPoint(x, y);}// 正在拖动else if (m_isDragging){QPoint newTopLeft = event->pos() - m_dragPosition;// 确保新的顶点坐标不超过屏幕范围int x = qBound(screenRect.left(), newTopLeft.x(), screenRect.right() - m_dragPosition.x());int y = qBound(screenRect.top(), newTopLeft.y(), screenRect.bottom() - m_dragPosition.y());newTopLeft = QPoint(x, y);QPoint offset = newTopLeft - m_beginPoint;m_beginPoint += offset;m_endPoint += offset;}update();return QWidget::mouseMoveEvent(event);
}void PrintScreen::mouseReleaseEvent(QMouseEvent *event)
{// 鼠标释放且截图未完成if (m_isMousePress && !m_captureComplete){m_endPoint = event->pos();  // 设置结束点m_isMousePress = false;     // 重置鼠标按下状态m_captureComplete = true;   // 标记截图完成update();}// 释放时正在拖动else if (m_isDragging){m_isDragging = false;}update();
}void PrintScreen::keyPressEvent(QKeyEvent *event)
{// 按下回车键if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return){// 保存图片QString filePath = QFileDialog::getSaveFileName(nullptr, "保存图片",QString(),"Images (*.png *.jpg)");if(!filePath.isEmpty()){m_capturePixmap.save(filePath); // 保存截图到文件}close();}
}void PrintScreen::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)m_painter.begin(this);                                           // 开始绘制QColor shadowColor(0, 0, 0, 100);                                // 半透明遮罩颜色m_painter.setPen(QPen(Qt::blue, 1, Qt::SolidLine, Qt::FlatCap)); // 设置画笔m_painter.drawPixmap(0, 0, m_loadPixmap);                        // 绘制加载的屏幕截图m_painter.fillRect(m_loadPixmap.rect(), shadowColor);            // 绘制半透明遮罩QRect selectedRect = GetRect(m_beginPoint, m_endPoint);          // 获取选择区域m_capturePixmap = m_loadPixmap.copy(selectedRect);               // 截取选择区域的屏幕截图m_painter.drawPixmap(selectedRect.topLeft(), m_capturePixmap);   // 绘制截取的区域m_painter.drawRect(selectedRect);                                // 绘制选择区域的边框m_painter.end();                                                 // 结束绘制
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QPushButton>#include "PrintScreen.h"class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:QPushButton *m_screenBtn;PrintScreen *m_printScree;// QObject interface
public:bool eventFilter(QObject *watched, QEvent *event);
};
#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"
#include <QLayout>
#include <QMouseEvent>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), m_screenBtn(new QPushButton("截图", this))
{// 设置中心窗口setCentralWidget(m_screenBtn);// 安装事件过滤器m_screenBtn->installEventFilter(this);// 隐藏标题栏setWindowFlags(Qt::FramelessWindowHint);resize(150, 50);
}MainWindow::~MainWindow() {}bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{if (watched == m_screenBtn && event->type() == QEvent::MouseButtonPress){QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);if (mouseEvent->button() == Qt::RightButton){close();return true;}else if (mouseEvent->button() == Qt::LeftButton){m_printScree = new PrintScreen();m_printScree->show();return true;}}return QMainWindow::eventFilter(watched, event);
}

main.cpp

#include "MainWindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《程序猿之设计模式实战 · 池化思想》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

LSS如何做深度和语义预测

get_cam_feats() 先来看看代码: def get_cam_feats(self, x):"""Return B x N x D x H/downsample x W/downsample x C"""B, N

解锁编程潜力,从掌握GitHub开始

目录&#xff1a; 一、搜索开源项目 1、什么是Git 2、Github常用词含义 3、一个完整的项目界面 4、使用Github搜索项目 1&#xff09;in关键词 2&#xff09;star或fork数量去查找 3&#xff09;awesome加强搜索 二、访问速度慢的解决 1、使用网易UU加速器 2、使用…

基于SSM的大学新生报到系统+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

VSCode创建C++项目和编译多文件

前言 在刚安装好VSCode后&#xff0c;我简单尝试了仅main.cpp单文件编译代码&#xff0c;没有问题&#xff0c;但是当我尝试多文件编译时&#xff0c;就出现了无法识别cpp文件。 内容 创建项目 首先点击左上角“文件”&#xff1b;在菜单中选择“打开文件夹”&#xff1b;在…

【Elasticsearch系列二】安装 Kibana

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

ClickHouse 24.8 LTS 版本发布说明

本文字数&#xff1a;13885&#xff1b;估计阅读时间&#xff1a;35 分钟 作者&#xff1a;ClickHouse Team 本文在公众号【ClickHouseInc】首发 时间飞逝&#xff0c;又到了新版本发布的时刻&#xff01; 发布概要 本次ClickHouse 24.8 版本包含了19个新功能&#x1f381;、18…

基于51单片机的16X16点阵显示屏proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1JQ225NSKweqf1Zlad_f1Mw 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

管家婆云辉煌手机端怎么连接蓝牙打印机?

管家婆云辉煌手机端可以连接蓝牙打印机&#xff0c;这样手机可以发送打印任务到蓝牙打印机&#xff0c;完成打印任务。具体的设置步骤如下&#xff1a; 一、首先完成手机和蓝牙打印机配对&#xff0c;打开蓝牙打印机后。手机开启蓝牙和定位服务 点击手机设置&#xff0c;进入手…

分类预测|基于差分优化DE-支持向量机数据分类预测完整Matlab程序 DE-SVM

分类预测|基于差分优化DE-支持向量机数据分类预测完整Matlab程序 DE-SVM 文章目录 一、基本原理DE-SVM 分类预测原理和流程总结 二、实验结果三、核心代码四、代码获取五、总结 一、基本原理 DE-SVM 分类预测原理和流程 1. 差分进化优化算法&#xff08;DE&#xff09; 原理…

【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署

【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署前言Windows平台搭建依赖环境模型转换--pytorch转onnxONN…

走进低代码表单开发(一):可视化表单数据源设计

在前文&#xff0c;我们已对勤研低代码平台的报表功能做了详细介绍。接下来&#xff0c;让我们深入探究低代码开发中最为常用的表单设计功能。一个完整的应用是由众多表单组合而成的&#xff0c;所以高效的表单设计在开发过程中起着至关重要的作用。让我们一同了解勤研低代码开…

[网络]http/https的简单认识

文章目录 一. 什么是http二. http协议工作过程三. http协议格式1. 抓包工具fiddler2. http请求报文3. http响应报文 一. 什么是http HTTP (全称为 “超⽂本传输协议”) 是⼀种应⽤⾮常⼴泛的 应⽤层协议 HTTP 诞⽣与1991年. ⽬前已经发展为最主流使⽤的⼀种应⽤层协议 HTTP 往…

FPGA实现串口升级及MultiBoot(四)MultiBoot简介

缩略词索引&#xff1a; K7:Kintex 7V7:Vertex 7A7:Artix 7 我们在正常升级的过程&#xff08;只使用一个位流文件&#xff09;&#xff0c;假如&#xff1a;&#xff08;1&#xff09;因为干扰通信模块收到了一个错误位&#xff1b;&#xff08;2&#xff09;或者烧写进FLASH时…

《深度学习》—— 神经网络模型中的损失函数及正则化惩罚和梯度下降

文章目录 前言一、损失函数二、正则化惩罚三、梯度下降 前言 在神经网络中&#xff0c;损失函数、正则化惩罚和梯度下降是三个关键的概念&#xff0c;它们共同作用于网络的训练过程&#xff0c;以提升网络的性能和泛化能力。神经网络模型结构如下图所示&#xff1a; 在构建好一…

LCSS—最长回文子序列

思路分析 关于”回文串“的问题&#xff0c;是面试中常见的&#xff0c;本文提升难度&#xff0c;讲一讲”最长回文子序列“问题&#xff0c;题目很好理解&#xff1a; 输入一个字符串 s&#xff0c;请找出 s 中的最长回文子序列长度。 比如输入 s"aecda"&#xff0c…

【AI-18】Adam和SGD优化算法比较

Adam&#xff08;Adaptive Moment Estimation&#xff09;和 SGD&#xff08;Stochastic Gradient Descent&#xff0c;随机梯度下降&#xff09;是两种常见的优化算法&#xff0c;它们在不同方面有各自的特点。 一、算法原理 SGD&#xff1a; 通过计算损失函数关于每个样本的…

S7-1500T分布式同步功能

1. 功能描述工控人加入PLC工业自动化精英社群 在一些实际应用中&#xff0c;会需要很多轴进行同步运行&#xff0c;如印刷机、纸尿裤生产线等。由于一个 PLC 的运动控制资源有限&#xff0c;控制轴的数量也是有限的&#xff0c;就会需要多个 PLC 间协调实现轴工艺对象的跨CPU的…

k8s以及prometheus

#生成控制器文件并建立控制器 [rootk8s-master ~]# kubectl create deployment bwmis --image timinglee/myapp:v1 --replicas 2 --dry-runclient -o yaml > bwmis.yaml [rootk8s-master ~]# kubectl expose deployment bwmis --port 80 --target-port 80 --dry-runclient…