嵌入式养成计划-45----QT--事件机制--定时器事件--键盘事件和鼠标事件--绘制事件

news2024/11/16 7:35:29

一百一十五、事件机制

  • 当这件事情发生时,会自动走对应的函数处理(重写的事件函数)

115.1 事件处理简介

  • 什么是事件? (重点)
    • 件是由窗口系统或者自身产生的,用以响应所发生的各类事情,
    • 比如用户按下并释放了键盘或者鼠标、窗口因暴露而需要重绘、定时器到时而应有所动作,等等
    • 从某种意义上讲,事件比信号更原始,甚至可以认为大多数信号其实都是由事件产生的。
    • 比如一个下压式按钮首先感受到的是鼠标事件,在进行必要的处理以产生按钮下沉继而弹起的视觉效果之后,才会发射 clicked()信号
  • 如何处理事件? (重点)
    • myWnd(自定义类) -继承-> QWidget -继承-> QObject
    • 当事件发生时,首先被调用的是QObject类中的虚函数event(),
      其 QEvent型参数标识了具体的事件类型
      bool QObject:: event (QEvent* e)
      {
          if (e == mouseEvent)
          {
              void QWidget::mousePressEvent (QMouseEvent* e)
              void QWidget:: mouseReleaseEvent (QMouseEvent* e)
          }
          if(e == keyEvent){
              void QWidget::keyPressEvent (QMouseEvent* e)
              void QWidget:: keyReleaseEvent (QMouseEvent* e)
          }
      }
      
    • 作为QObject类的子类, QWidget类覆盖了其基类中的
      event()虚函数,并根据具体事件调用具体事件处理函数
      void QWidget::mousePressEvent (QMouseEvent* e)
      void QWidget::mouseReleaseEvent (QMouseEvent* e)
      void QWidget::keyPressEvent (QMouseEvent* e)
      void QWidget:: keyReleaseEvent (QMouseEvent* e)
      void QWidget::paintEvent (QPaintEvent* e)
      
    • 而这些事件处理函数同样也是虚函数,也可以被 QWidget类的子类覆盖,以提供针对不同窗口部件类型的事件处理
    • 组件的使用者所关心的往往是定义什么样的槽处理什么样的信号,而组件的实现者更关心覆盖哪些事件处理函数

115.2 事件处理函数由来

QObject类 提供了那些可以重写的虚函数
    [virtual] bool QObject::event(QEvent *e) 
            // 参数:事件的类型

QWidgets类, 提供了那些可以重写的虚函数
    [override virtual protected] bool QWidget::event(QEvent *event)
    
    [virtual protected] void QWidget::keyPressEvent(QKeyEvent *event)
    [virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event)
    [virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)
    [virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)
    [virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)
    [virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
    [virtual protected] void QObject::timerEvent(QTimerEvent *event)

QPainter类 ---> 画家类
    void SimpleExampleWidget::paintEvent(QPaintEvent *)
    {
        QPainter painter(this);
        painter.setPen(Qt::blue);
        painter.setFont(QFont("Arial", 30));
        painter.drawText(rect(), Qt::AlignCenter, "Qt");
    }

一百一十六、定时器事件

  • qt的定时器事件提供了两这种实现方式,分别是 基于对象版本基于事件处理函数

  • 基于事件处理函数

    1.不需要手动书写信号函数,不需要写信号和槽
    2.使用的是自己的成员函数,启动定时器函数、关闭定时器函数、定时器时间超时时的函数
    3.功能:让系统在每隔一定的时间,自动执行某段代码
    4.所需要的函数:
        startTimer(int sec); //自身的成员函数,表示启动一个定时器,给定毫秒,返回定时器的id
        killTimer(int id);//自身的成员函数,表示关闭一个定时器,给定定时器id
        timerEvent(QTimerEvent *e); //定时器处理的函数,表示定时器给定的时间到了,就自动执行该函数的内容        
    
  • ui界面:
    在这里插入图片描述

    • 示例 :
      #include "widget.h"
      #include "ui_widget.h"
      Widget::Widget(QWidget *parent)
          : QWidget(parent)
          , ui(new Ui::Widget)
      {
          ui->setupUi(this);
      }
      Widget::~Widget()
      {
          delete ui;
      }
      //启动按钮对应的槽函数处理
      void Widget::on_startBtn_clicked()
      {
          if(ui->startBtn->text() == "启动")
          {
              //启动一个定时器
              tId = startTimer(1000);
              //将按钮文本设置成关闭
              ui->startBtn->setText("关闭");
          }
          else
          {
              //关闭一个定时器
              killTimer(tId);
              //将文本设置成启动
              ui->startBtn->setText("启动");
          }
      }
      //时间事件的函数处理
      void Widget::timerEvent(QTimerEvent *e)
      {
          //判断哪个定时器超时
          if(e->timerId() == tId)
          {
      //        static int num = 0;
      //        ui->timeLab->setNum(++num);
              QTime sys_time = QTime::currentTime(); //获取当前系统时间
              //把系统时间转换成字符串
              QString s = sys_time.toString("hh::mm::ss");
              //将系统时间放入标签中
              ui->timeLab->setText(s);
              //居中显示
              ui->timeLab->setAlignment(Qt::AlignCenter);
          }
      }
      
  • 基于对象版本

    1. 需要用QTimer定时器类实例化一个对象
    2. 用对象调用启动定时器函数:start(int sec),让系统每隔sec毫秒,触发一个信号timeout
    3. 我们可以将timeout信号与自定义的槽函数连接,处理槽函数的逻辑代码
    4. 用对象调用关闭定时器函数: stop()
    • 示例 :
      //启动2对应的槽函数处理
      void Widget::on_startBtn2_clicked()
      {
          if(ui->startBtn2->text() == "启动")
          {
              //启动一个定时器
              t->start(1000); //每隔1秒发射一个timeout信号
              //将启动按钮设置成关闭
              ui->startBtn2->setText("关闭");
          }
          else
          {
              //关闭一个定时器
              t->stop();
              //将关闭按钮设置成启动
              ui->startBtn2->setText("启动");
          }
      }
      //定时器超时对应的槽函数处理
      void Widget::timeOut_Slot()
      {
          QTime sys_time = QTime::currentTime(); //获取当前系统时间
          //把系统时间转换成字符串
          QString s = sys_time.toString("hh-mm-ss");
          //将系统时间放入标签中
          ui->timeLab2->setText(s);
          //居中显示
          ui->timeLab2->setAlignment(Qt::AlignCenter);
      }
      

一百一十七、键盘事件和鼠标事件

  • 当程序员使用键盘或者鼠标,系统就会自动调用QWidget中的对应事件处理函数
  • 键盘事件和鼠标事件的函数原型
    [virtual protected] void QWidget::keyPressEvent(QKeyEvent *event); //键盘按下事件函数
    [virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event)//键盘抬起事件函数
    
    [virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)//鼠标双击事件函数
    [virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)//鼠标移动事件函数
    [virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)//鼠标按下事件函数
    [virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)//鼠标抬起事件函数
    

117.1 键盘事件

  • UI界面
    在这里插入图片描述
    代码示例 :
  • 头文件:
    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include<QKeyEvent> //键盘事件类
    #include<QDebug>
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class Widget; }
    QT_END_NAMESPACE
    
    class Widget : public QWidget
    {
        Q_OBJECT
    public:
        Widget(QWidget *parent = nullptr);
        ~Widget();
        void keyPressEvent(QKeyEvent *event) override; //键盘按下的重写事件函数声明
        void keyReleaseEvent(QKeyEvent *event) override;//键盘抬起的重写事件函数声明
    private:
        Ui::Widget *ui;
    };
    #endif // WIDGET_H
    
  • 源文件:
    #include "widget.h"
    #include "ui_widget.h"
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    }
    Widget::~Widget()
    {
        delete ui;
    }
    //重写键盘按下事件函数的实现
    void Widget::keyPressEvent(QKeyEvent *event)
    {
        ui->label->setText(event->text()+":被按下");
        ui->label->setAlignment(Qt::AlignCenter);
        //判断哪个键被按下
        switch (event->key())
        {
            case 'W':
            {
                if(ui->label->y() < 0-ui->label->height()) //判断标签y轴是否完全出界面
                {
                    ui->label->move(ui->label->x(), this->height()); //移动到界面的下面
                }
                ui->label->move(ui->label->x(), ui->label->y()-1);
            }
        }
    }
    //重写键盘抬起事件函数的实现
    void Widget::keyReleaseEvent(QKeyEvent *event)
    {
        ui->label->setText(event->text()+":被抬起");
        ui->label->setAlignment(Qt::AlignCenter);
    }
    

117.2 鼠标事件

  • 源文件:
    #include "widget.h"
    #include "ui_widget.h"
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
        //窗口开启追踪功能
        this->setMouseTracking(true);
    }
    Widget::~Widget()
    {
        delete ui;
    }
    //重写键盘按下事件函数的实现
    void Widget::keyPressEvent(QKeyEvent *event)
    {
        ui->label->setText(event->text()+":被按下");
        ui->label->setAlignment(Qt::AlignCenter);
        //判断哪个键被按下
        switch (event->key())
        {
            case 'W':
            {
                if(ui->label->y() < 0-ui->label->height()) //判断标签y轴是否完全出界面
                {
                    ui->label->move(ui->label->x(), this->height()); //移动到界面的下面
                }
                ui->label->move(ui->label->x(), ui->label->y()-1);
            }
        }
    }
    //重写键盘抬起事件函数的实现
    void Widget::keyReleaseEvent(QKeyEvent *event)
    {
        ui->label->setText(event->text()+":被抬起");
        ui->label->setAlignment(Qt::AlignCenter);
    }
    //鼠标按下重写事件函数的实现
    void Widget::mousePressEvent(QMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton)
        {
            QString s = QString("左键被按下\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
        else if(event->button() == Qt::RightButton)
        {
            QString s = QString("右键被按下\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
        else if(event->button() == Qt::MiddleButton)
        {
            QString s = QString("中间键被按下\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
    }
    //鼠标移动重写事件函数的实现
    void Widget::mouseMoveEvent(QMouseEvent *event)
    {
        ui->label->move(event->pos()); //跟着鼠标所在位置移动
    }
    //鼠标抬起重写事件函数的实现
    void Widget::mouseReleaseEvent(QMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton)
        {
            QString s = QString("左键被抬起\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
        else if(event->button() == Qt::RightButton)
        {
            QString s = QString("右键被抬起\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
        else if(event->button() == Qt::MiddleButton)
        {
            QString s = QString("中间键被抬起\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
    }
    //鼠标双击重写事件函数的实现
    void Widget::mouseDoubleClickEvent(QMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton)
        {
            QString s = QString("左键被双击\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
        else if(event->button() == Qt::RightButton)
        {
            QString s = QString("右键被双击\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
        else if(event->button() == Qt::MiddleButton)
        {
            QString s = QString("中间键被双击\n所在位置:x:%1,y:%2").arg(event->x()).arg(event->y());
            ui->label->setText(s);
        }
    }
    

117.3 移动窗口案例

  • 加到上边的源文件中
    void Widget::mousePressEvent(QMouseEvent *event)
    {
        //p = event->globalPos()-this->frameGeometry().topLeft();
             //鼠标点击全局位置       //窗口一开始位置
        p=event->pos();
    }
    void Widget::mouseMoveEvent(QMouseEvent *event)
    {
           if(event->buttons() == Qt::LeftButton)
           {
               this->move(event->globalPos()-p);
                           //鼠标点击全局位置   鼠标相对于窗口的位置
           }
    }
    

一百一十八、绘制事件

  • 绘制事件是qt提供的二维图形引擎,能够让用户绘制各种图形,例如:适量文字、绘制图形、图像等
  • 绘制事件处理函数触发情况:窗口第一次展示、窗口最小化、最大化、窗口从覆盖状态显示出来、手动拖动窗口调大小、调用update函数
  • 绘制事件,依赖于画家类(QPainter)实现相关绘制工作

示例 :

  • 重写的函数
    //绘制事件处理函数
    void Widget::paintEvent(QPaintEvent *event)
    {
    //    static int num = 0;
    //    qDebug() << ++num;
        //实例化一个画家
        QPainter p(this); //指定绘制地方
    
        //给画家设置画笔
        p.setPen(QColor("pink"));
    
        //给画家的笔设置字体类型
        p.setFont(QFont("宋体",40,10,false));
    
        p.drawText(this->rect(),Qt::AlignCenter,"好好学习,天天向上");
                  //区域范围
    }
    

小作业

  • 写一个闹钟
    在这里插入图片描述

我写的

clock.h

#ifndef CLOCK_H
#define CLOCK_H

#include <QWidget>
#include <QTextToSpeech>
#include <QTime>
#include <QTimer>
#include <QTimeEdit>
#include <QTimerEvent>
#include <QDate>
#include <QDateTime>
#include <QPushButton>
#include <QDebug>
#include <QMouseEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class Clock; }
QT_END_NAMESPACE

class Clock : public QWidget
{
    Q_OBJECT

public:
    Clock(QWidget *parent = nullptr);
    ~Clock();

    void timerEvent(QTimerEvent *event) override;

signals:
    void speak();

private slots:
    void timeOut_solt();
    void speak_slot();

    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

private:
    Ui::Clock *ui;

    QDateTime sys_date;
    QTimer *sys_time,*t;
    int tid;
    QPoint p;
    QTextToSpeech *speecher;
};
#endif // CLOCK_H

clock.cpp

#include "clock.h"
#include "ui_clock.h"

Clock::Clock(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Clock)
{
    ui->setupUi(this);
    //  设置窗口为纯净模式
    this->setWindowFlags(Qt::FramelessWindowHint);

    //  直接先初始化当前时间
    tid = startTimer(1000);
    sys_time = new QTimer(this);

    speecher = new QTextToSpeech(this);

    //  初始化t
    t = new QTimer(this);
    //  连接超时信号与处理的槽函数
    connect(t, &QTimer::timeout, this, &Clock::timeOut_solt);
}

Clock::~Clock()
{
    killTimer(tid);
    delete ui;
}

void Clock::timerEvent(QTimerEvent *event)
{
    if(event->timerId() == tid){
        sys_date = QDateTime::currentDateTime();
        ui->nowTimeLab->setText(sys_date.toString("yyyy-MM-dd  HH:mm:ss"));
        ui->nowTimeLab->setAlignment(Qt::AlignCenter);
    }
}

void Clock::timeOut_solt()
{
    QTime the_time = QTime::currentTime();
    //  时间超过则直接发送语音播报信号
    if(the_time.toString("hh:mm:ss") >= ui->clockTimeEdit->toPlainText()){
        emit speak();
    }
}

//  语音播报
void Clock::speak_slot()
{
    speecher->say(ui->textEdit->toPlainText());
}

void Clock::mousePressEvent(QMouseEvent *event)
{
    p = event->pos();
    if(event->button() == Qt::LeftButton){
        //  鼠标按下位置在 关闭上
        if(p.x() >= ui->closeLab->x() && p.x() <= ui->closeLab->x()+ui->closeLab->width() \
                && p.y() >= ui->closeLab->y() && p.y() <= ui->closeLab->y()+ui->closeLab->height()){
            //  按下关闭,关闭变红
            ui->closeLab->setStyleSheet("background-color:red");
        }
        //  鼠标按下位置在 打开上
        else if (p.x() >= ui->openLab->x() && p.x() <= ui->openLab->x()+ui->openLab->width() \
                  && p.y() >= ui->openLab->y() && p.y() <= ui->openLab->y()+ui->openLab->height()){
        }
    }
}

void Clock::mouseReleaseEvent(QMouseEvent *event)
{
    p = event->pos();
    if(event->button() == Qt::LeftButton){
        //  鼠标松开位置在 关闭上
        if(p.x() >= ui->closeLab->x() && p.x() <= ui->closeLab->x()+ui->closeLab->width() \
                && p.y() >= ui->closeLab->y() && p.y() <= ui->closeLab->y()+ui->closeLab->height()){
            //  松开关闭
            t->stop();
            ui->openLab->setStyleSheet("background-color:white");
            ui->openLab->setText("启动闹钟");
            ui->closeLab->setStyleSheet("background-color:white");
            disconnect(this, &Clock::speak, this, &Clock::speak_slot);
        }
        //  鼠标松开位置在 打开上
        else if (p.x() >= ui->openLab->x() && p.x() <= ui->openLab->x()+ui->openLab->width() \
                  && p.y() >= ui->openLab->y() && p.y() <= ui->openLab->y()+ui->openLab->height()){
            //  松开打开
            t->start(3000);
            ui->openLab->setText("已启动");
            ui->openLab->setStyleSheet("background-color:green");
            //  将语音播报信号和语音播报槽函数连接
            connect(this, &Clock::speak, this, &Clock::speak_slot);
        }
    }
}

main.cpp

#include "clock.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Clock w;
    w.show();
    return a.exec();
}

执行的 UI 界面

在这里插入图片描述

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

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

相关文章

vscode调试技巧 断言 assert

目录 调试技巧标题debug release介绍调试技巧断点 断点的意思 就是代码执行到断点处停下来&#xff0c;让你去调试。不管前面有多少代码&#xff0c;直接跳到断点处&#xff08;当然前面的已经执行&#xff09;逐过程 不会进入调用函数内部&#xff0c;不管里面怎么执行。 逐语…

精讲stable diffusion的controlNet插件

controlNet插件是stable diffusion的一个重要插件&#xff0c;甚至可以说正是因为有了controlNet插件&#xff0c;stable diffusion才会具有midjourney所不具备的独特魅力&#xff01; 我们今天就一起来学习下controlNet插件的安装和每个模型的用法 插件主页 独立的controlN…

MSP430F5529时钟系统配置

1、为什么要进行时钟管理&#xff1f;   时钟系统是一个数字器件的命脉&#xff0c;对于普通的51单片机来说&#xff0c;它的时钟来源只有外部晶振&#xff0c;然后每12个振荡周期完成一个基本操作&#xff0c;所以也叫做12T单片机&#xff0c;但对于当前高级一点的单片机来…

牛客:NC59 矩阵的最小路径和

牛客&#xff1a;NC59 矩阵的最小路径和 文章目录 牛客&#xff1a;NC59 矩阵的最小路径和题目描述题解思路题解代码 题目描述 题解思路 动态规划&#xff0c;递推公式&#xff1a;matrix[i][j] min(matrix[i-1][j], matrix[i][j-1]) 题解代码 func minPathSum( matrix [][…

性能压测工具 —— wrk

一般我们压测的时候&#xff0c;需要了解衡量系统性能的一些参数指标&#xff0c;比如。 1、性能指标简介 1.1 延迟 简单易懂。green:一般指响应时间 95线&#xff1a;P95。平均100%的请求中95%已经响应的时间 99线&#xff1a;P99。平均100%的请求中99%已经响应的时间 平…

maven聚合和继承

一、什么是maven的聚合和继承&why 随着技术飞速发展&#xff0c;各类用户对软件的要求越来越高&#xff0c;软件也变得越来越复杂。 软件设计人员往往会采用各种方式对软件划分模块&#xff0c;已得到更加清晰的设计及更高的复用性。 当把Maven应用到实际项目中的时候&am…

多年没有遇到如此流畅的面试了

美东一公司的面试&#xff0c;有多年没有遇到如此流畅的面试了。 本来说的面试时间是 30 分钟&#xff0c;这个还是第一轮处于电话面试那种&#xff0c;但是不知道为什么最后面试整个时间都延长到了快一个小时&#xff0c;貌似双方都还继续沟通下&#xff0c;有点意犹未尽的感觉…

ZKP5.1 Plonk Interactive Oracle Proofs (KZG‘10)

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 5: The Plonk SNARK (Dan Boneh) 5.1 KZG’10 general SNARK A polynomial commitment scheme A polynomial interactive oracle proof (IOP) Review: polynomial commitments The KZG poly-commit scheme commit a bind…

自动化测试07Selenium01

目录 什么是自动化测试 Selenium介绍 Selenium是什么 Selenium特点 工作原理 SeleniumJava环境搭建 Selenium常用的API使用 定位元素findElement CSS选择语法 id选择器&#xff1a;#id 类选择 .class 标签选择器 标签名 后代选择器 父级选择器 自己选择器 xpath …

AM@两种余项型泰勒公式的对比和总结@常用函数的麦克劳林公式

文章目录 abstract两种余项型泰勒公式的对比和总结Maclaurin公式常用函数的Maclaurin公式推导例求极限按幂展开 abstract 泰勒公式的两种余项型(Penao&Lagrange)泰勒公式的对比和总结常用的Maclaurin公式列举(Peano余项型为主) 两种余项型泰勒公式的对比和总结 Taylor公式…

Youtrack Linux 安装

我们考虑最后应该使用的是 ZIP 方式的安装。 按照官方的说法如何设置运行 YouTrack 应该是非常简单的。 准备环境 根据官方的说法&#xff0c;我们需要做的就是下载 Zip 包&#xff0c;然后把 Zip 包解压到指定的目录中就可以了。 下载 当前官方的下载地址为&#xff1a;Ge…

Vue解决 npm -v 报错(一)

报错内容&#xff1a; npm WARN config global --global, --local are deprecated. Use --locationglobal instead. 解决方案&#xff1a; 代码&#xff1a; prefix -g 替换为&#xff1a; prefix --locationglobal 原创作者&#xff1a;吴小糖 创作时间&#xff1a;2023.1…

盒式交换机堆叠配置

目录 1.配置环形拓扑堆叠 2.设备组建堆叠 3.设备组件堆叠 堆叠 istack&#xff0c;是指将多台支持堆叠特性的交换机设备组合在一起&#xff0c;从逻辑上组合成一台交换设备。如图所示&#xff0c;SwitchA与 SwitchB 通过堆叠线缆连接后组成堆叠 istack&#xff0c;对于上游和…

Windows Server服务器下的Linux子系统

Windows、Linux看似死敌一对&#xff0c;但其实微软对于开源实业还是相当支持的&#xff0c;Windows 10系统内就首次内置了一个Linux子系统(Windows Subsystem for Linux/WSL)&#xff0c;允许开发者模拟Linux环境&#xff0c;而且有需要的可以直接从Windows应用商店下载SUSE、…

软件项目管理【UML-组件图】

目录 一、组件图概念 二、组件图包含的元素 1.组件&#xff08;Component&#xff09;->构件 2.接口&#xff08;Interface&#xff09; 3.外部接口——端口 4.连接器&#xff08;Connector&#xff09;——连接件 4.关系 5.组件图表示方法 三、例子 一、组件图概念…

Linux简单安装ffmpeg 实现用PHP压缩音频

一、下载安装 1、官方下载地址&#xff1a;Download FFmpeg 2、下载完上传到服务器然 然后解压就算安装完成了 tar -xf ffmpeg-git-amd64-static.tar.xz 3、然后配置一下全局变量&#xff08;当然也可以不用配置 使用的时候带上文件路径就行&#xff09; cd /usr/bin ln -s…

互联网Java工程师面试题·Java 总结篇·第十一弹

目录 90、简述一下你了解的设计模式。 91、用 Java 写一个单例类。 92、什么是 UML&#xff1f; 93、UML 中有哪些常用的图&#xff1f; 94、用 Java 写一个冒泡排序。 95、用 Java 写一个折半查找。 90、简述一下你了解的设计模式。 所谓设计模式&#xff0c;就是一套被…

Ae 效果:CC Overbrights

实用工具/CC Overbrights Utility/CC Overbrights CC Overbrights&#xff08;CC 高光溢出&#xff0c;CC 过于鲜亮&#xff09;主要用于改变图像中高光溢出&#xff08;又称高光剪切、过曝&#xff09;区域的显示方式&#xff0c;以便配合其它效果来更好地处理和控制这些区域的…

分类预测 | MATLAB实现SSA-CNN-LSTM麻雀算法优化卷积长短期记忆神经网络数据分类预测

分类预测 | MATLAB实现SSA-CNN-LSTM麻雀算法优化卷积长短期记忆神经网络数据分类预测 目录 分类预测 | MATLAB实现SSA-CNN-LSTM麻雀算法优化卷积长短期记忆神经网络数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现SSA-CNN-LSTM数据分类预测&…

Maven系列第8篇:大型Maven项目,快速按需任意构建

本篇涉及到的内容属于神技能&#xff0c;多数使用maven的人都经常想要的一种功能&#xff0c;但是大多数人都不知道如何使用&#xff0c;废话不多说&#xff0c;上干货。 需求背景 我们需要做一个电商项目&#xff0c;一般都会做成微服务的形式&#xff0c;按业务进行划分&am…