QT-自定义信号和槽对象树图形化开发计算器

news2024/9/28 10:33:21

1. 自定义信号和槽

  • 核心逻辑: 需要有两个类,一个提供信号,另一个提供槽。 然后在窗口中将 信号和槽 链接起来。

  • 示例目标: 创建一个 Teacher 类,提供信号。 创建一个 Student 类,提供槽。

实现步骤:

  1. 创建 Teacher 类,在 singals 中提供信号的定义

  2. 创建 Student 类,在 slots 中提供处理的槽函数

  3. 在 窗口(Widget)中,链接信号和槽,并触发 (使用 emit 来发射信号)

1.1 创建 Teacher 类

1)右键 项目名称 ----> Add New (添加新的)

2)选择 C++ ----> C++ Class

3)设置类名以及继承关系

1.2 Teacher中定义信号

自定义信号的特点:

  • 自定义信号写在 signals 下

  • 自定义信号是一个无返回值的函数声明,不需要实现

  • 自定义信号允许重载

// teacher,h

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>

class Teacher : public QObject
{
    Q_OBJECT //元对象系统
public:
    explicit Teacher(QObject *parent = nullptr);

    //信号定义在signals节点下
    //信号是一个无返回值的函数
    //信号不需要实现
    //信号函数允许重载
signals:

    void mySignal();
    void mySignal(QString str);

public slots:
    void response();
    void response(QString str);

};

#endif // TEACHER_H


//teacher.c

#include "teacher.h"
#include <QDebug>

Teacher::Teacher(QObject *parent) : QObject(parent)
{


}

void Teacher::response()
{
    qDebug() << "我是老师";
}

void Teacher::response(QString str)
{
    if(str == "学生")
    {
        qDebug() << "学生,你好";
    }
    else if (str == "鲨鱼") {
        qDebug() << "鲨鱼来袭";
    }
}

1.3 创建 Student 类

创建过程同 Teacher

1.4 Student 中定义槽函数

槽函数特点:

  • 槽函数写在 slots 下, 高级版本中也可以写在 public 下

  • 槽函数是一个无返回值的函数,可以重载

// student,h

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

signals:

    void mySignal();
    void mySignal(QString str);

    //槽函数定义在 public/pretected/private slots 节点下
    //槽函数是一个无返回值的函数
    //在槽函数中编写实际的业务逻辑
    //在槽函数中允许重载
public slots:
    void response();
    void response(QString str);
};

#endif // STUDENT_H


//student。c

#include "student.h"
#include <QDebug>


Student::Student(QObject *parent) : QObject(parent)
{

}

void Student::response()
{
    qDebug() <<"收到...";
}

void Student::response(QString str)
{
    //qDebug() << str;

    if (str == "下课")
    {
        qDebug()<<"下楼";
    }
    else if(str == "放学")
    {
        qDebug()<<"回家";

    }

}

1.5 窗口中链接信号和槽

//widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
};

#endif // WIDGET_H


//widget.c

#include "widget.h"

#include "teacher.h"
#include "student.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    auto *t = new Teacher(this);
    auto *s = new Student(this);
    //链接信号
    //connect(t, &Teacher::mySignal, s, &Student::response);
    //发送信号
    //emit t->mySignal();


    //如果信号和槽有多个版本的重载,需要使用SIGNAL()和SLOT()函数来指定信号和槽
    connect(t,SIGNAL(mySignal(QString)), s, SLOT(response(QString)));
    //emit t->mySignal("下课");

    QPushButton *btn1 = new QPushButton("下课",this);
    btn1->move(20,20);
    connect(btn1, &QPushButton::clicked, [t](){
        emit t->mySignal("下课");
    });

    QPushButton *btn2 = new QPushButton("放学",this);
    btn2->move(120,20);
    connect(btn2, &QPushButton::clicked, [t](){
        emit t->mySignal("放学");
    });

    //信号到槽 -> 学生到老师
    connect(s,SIGNAL(mySignal(QString)), t, SLOT(response(QString)));
    QPushButton *btn3 = new QPushButton("学生",this);
    btn3->move(20,80);
    connect(btn3, &QPushButton::clicked, [s](){
        emit s->mySignal("学生");
    });
    QPushButton *btn4 = new QPushButton("鲨鱼",this);
    btn4->move(120,80);
    connect(btn4, &QPushButton::clicked,[s](){
        emit s->mySignal("鲨鱼");
    });


}

Widget::~Widget()
{

}

 核心: 使用 emit 触发信号

1.6 信号和槽的重载

信号和槽都允许重载

1)在 Teacher 中重载信号

class Teacher : public QObject
{
  Q_OBJECT
public:
  explicit Teacher(QObject *parent = nullptr);

signals:
  // 重载信号, 信号始终不需要实现
  void say();
  void say(QString str);
};

2)在 Student 头文件中重载槽函数

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

public slots:
  // 重载槽函数
  void deal();
  void deal(QString str);

};

3)在Student 源文件中实现重载

void Student::deal()
{
  qDebug() << "去吃饭";
}

void Student::deal(QString str)
{
  if (str == "下课")
  {
    qDebug() << "抽烟去咯";
  }
  else if (str == "休息")
  {
    qDebug() << "吃饭去咯";
  }
}

4)链接信号与槽

注意点: 此时,单纯的使用 connect 就无法区分哪个信号 链接 哪个槽

解决方案: 使用 SIGNAL() 函数包装要发射的信号; 使用 SLOT() 函数包装要执行的槽函数

注意事项: 要使用 SIGNAL() 和 SLOT() , 必须将槽函数放在 public slots 节点下

// 链接无参的信号和槽
connect(t, SIGNAL(say()), s, SLOT(deal()));

// 链接有参的信号和槽
connect(t, SIGNAL(say(QString)), s, SLOT(deal(QString)));

发射哪个信号,由 emit 决定

emit t->say();           // 发射无参的信号

emit t->say("放学");      // 发射有参的信号, 实参会被槽函数的形参接收

2. 对象树

  • 创建图形化应用程序时,我们只 new 了各种控件,但是没有释放过。当关闭应用时系统会自动释放

  • 通过 new 得到的对象,又通过 setParent 方法添加到了父组件中。实际上是添加到了父组件的 children()列表中,最终形成一个父子结构的树,称之为 对象树

  • 构建图形界面时,从父开始执行,父创建好了再创建子;当关闭图形界面时,析构函数会从子开始执行,再到父。系统会自动进行释放操作。

注:1.所有的部件会添加到父部件的children列表中   2.创建窗口时,被分越高的越先创建出来 3.销毁窗口时,辈分越低的越先被销毁.系统会自动找到 children 列表中的子,进行销毁。

示例: 自定义组件验证

1)创建 MyButton 组件,继承 QPushButton 组件

//mybutton.h

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QObject>
#include <QWidget>

//引入 QPushButton
#include <QPushButton>

// 修改继承为 QPushButton
class MyButton : public QPushButton
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);
    // 添加析构函数
    ~MyButton();

signals:

public slots:
};

#endif // MYBUTTON_H

2)mybutton.cpp

#include "mybutton.h"
#include <QDebug>

MyButton::MyButton(QWidget *parent) : QPushButton (parent)
{
    qDebug() << "MyButton的构造函数执行";
}

MyButton::~MyButton()
{
    qDebug() << "MyButton的析构函数执行";
}

3)MyWidget.cpp 中调用自定义组件

#include "MyWidget.h"
#include <QDebug>
#include "mybutton.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    qDebug() << "MyWidget构造函数";
    this->resize(500, 300);

    auto myBtn = new MyButton;
    myBtn->setText("我的按钮");
    myBtn->move(0, 100);
    myBtn->setParent(this);
}

Widget::~Widget()
{
    qDebug() << "MyWidget析构函数";
}

4)测试结果

启动应用时: 先执行 MyWidget 构造函数,再执行 MyButton 构造函数

关闭应用时: 先执行 MyWidget 析构函数,注意此时并没有结束。 在执行 MyWidget 析构函数时,会发现还有子控件,子控件析构函数会先执行完毕后,再完成父控件析构函数。

3. 图形化开发

3.1 创建图形化项目

  • 重点: 勾选 ui

  • 优势: 能够使用拖拽的形式向窗口添加部件

  • 注意点:

    • 勾选 ui 创建出来的项目多了 Form / widget.ui。 该文件使用 xml 形式来描述窗口结构

    • 点击 "设计" 按钮,能够切换到 图形化开发界面。

    • widget.cpp 源文件额外继承了 ui 类,调用 ui->setupUi(this) 方法将窗口设置到ui对象中

    • 调用窗口中任意部件时需要使用: ui->部件对象名

3.2 图形化创建常用部件

3.3 代码编写

  • 图形化只能进行布局,所有的功能还要依靠代码编写

  • 首先需要给所有的部件起名,再通过 ui 对象找到 具体的部件进行编码

 选中任意部件,可以在如图的两个地方进行修改对象名称

使用图形化设置, 图形化设置都匹配有对应的方法

为部件设置信号和槽

右键某个部件 ---> 跳转槽...

 

选择使用哪个槽函数

 

在 .cpp 源文件中自动成功槽函数

4. 计算器

4.1 ui 布局

4.2 数字 和 运算符

  • 当用户点击数字按钮 和 运算符按钮时,能够将对应的数字保存到 num1 、 num2 ,将运算符保存到 opt 中

  • 解决方案:

    • 在类中设置三个私有属性, num1、num2、opt

    • 在num0~num9按钮上设置信号,当用户点击时,就将当前的数字拼接到 num1 或者 num2 中。 根据 opt 中是否保存了运算符来区分,到底保存在 num1 还是 num2 中。

    • 在加减乘除按钮上设置信号,点击时保存对应的运算符到 opt 中

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

    void setNum(QString n);
    void setOpt(QString o);

private:
    Ui::Widget *ui;
    //定义操作数1、操作数2、运算符
    QString num1;
    QString num2;
    QString opt;
};

#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->setWindowTitle("计算器");
    this->setFixedSize(363,660);

    //mid(start, length):字符串截取
    //参数1:截取的起始索引号
    //参数2:截取的长度,可选。如果不给参数2,则会截取到数据末尾

    //处理数字按钮
    connect(ui->btn9, &QPushButton::clicked,[this](){this->setNum("9");});
    connect(ui->btn8, &QPushButton::clicked,[this](){this->setNum("8");});
    connect(ui->btn7, &QPushButton::clicked,[this](){this->setNum("7");});
    connect(ui->btn6, &QPushButton::clicked,[this](){this->setNum("6");});
    connect(ui->btn5, &QPushButton::clicked,[this](){this->setNum("5");});
    connect(ui->btn4, &QPushButton::clicked,[this](){this->setNum("4");});
    connect(ui->btn3, &QPushButton::clicked,[this](){this->setNum("3");});
    connect(ui->btn2, &QPushButton::clicked,[this](){this->setNum("2");});
    connect(ui->btn1, &QPushButton::clicked,[this](){this->setNum("1");});
    connect(ui->btn0, &QPushButton::clicked,[this](){this->setNum("0");});
     connect(ui->pointBtn, &QPushButton::clicked,[this](){this->setNum(".");});
    //处理运算符按钮
    connect(ui->addBtn, &QPushButton::clicked,[this](){this->setOpt("+");});
    connect(ui->subBtn, &QPushButton::clicked,[this](){this->setOpt("-");});
    connect(ui->mulBtn, &QPushButton::clicked,[this](){this->setOpt("*");});
    connect(ui->divBtn, &QPushButton::clicked,[this](){this->setOpt("÷");});
    connect(ui->perBtn, &QPushButton::clicked,[this](){this->setOpt("%");});

4.3 等号处理

  • 点击 等号 开始运算

  • 运算逻辑: 根据不同的运算符,进行不同的运算,使用 if 或者 switch 进行分支操作

  • str.toDouble() 将数字型字符串转为浮点型

  • QString::number(num) 将数字转为字符串

//等号
    connect(ui->equarBtn, &QPushButton::clicked,[this](){
        double result = 0;
        if (this->opt == "+")
        {
            result = this->num1.toDouble() + this->num2.toDouble();
        }
        else if (this->opt == "-") {
             result = this->num1.toDouble() - this->num2.toDouble();
        }
        else if (this->opt == "*") {
             result = this->num1.toDouble() * this->num2.toDouble();
        }
        else if (this->opt == "÷") {
            if(this->num2 == "0")
            {
                ui->lineEdit->setText("除数不能为0");
                return;
            }
             result = this->num1.toDouble() / this->num2.toDouble();
        }
        else if (this->opt == "%") {
            result = this->num1.toInt() % this->num2.toInt();

        }

        ui->lineEdit->setText(QString::number(result));

        //转存结果到num1,并且清空num2和opt
        this->num1 = QString::number((result));
        this->num2 = "";
        this->opt = "";

        //qDebug() << this->num1 << this->opt  <<this->num2;
        });

4.4 清空按钮

清空: 将 num1 、num2 、 opt 都置为空

 //清空
    connect(ui->clsBtn, &QPushButton::clicked,[this](){
        this->num1 = "";
        this->num2 = "";
        this->opt = "";
        ui->lineEdit->clear();
    });

4.5 连续运算

  • 点击等号时,进行加减乘除运算

  • 运算完毕之后,将 结果保存到 num1 中, 然后清空 num2、opt

 ui->lineEdit->setText(QString::number(result));

        //转存结果到num1,并且清空num2和opt
        this->num1 = QString::number((result));
        this->num2 = "";
        this->opt = "";

4.6 输入优化

1)对 . 运算符的优化

当 num1 为空时,不能输入 . ; 当 num1 中已经有 . 时,不能再输入 .

2)对 0 的优化

当0作为第一个输入的数字时,第二个字符必须为 .

void Widget::setNum(QString n)
{
    //对 . 的特殊验证:1)如果屏幕中有点,不能输入 . 2)屏幕为空 不能输入 .
    //如果屏幕为空,且输入为 . 不能向下执行(返回)
    if (ui->lineEdit->text().isEmpty() && n == ".")
    {
        return;
    }
    //如果屏幕中有 . ,并且当前输入的是 . ,则放回
    if (ui->lineEdit->text().count(".") == 1 && n == ".")
    {
        return;
    }

    //对 0 特殊验证:屏幕中如果只有一个0,则下一个输入必须是点
//    if(ui->lineEdit->text().isEmpty() && n == "0")
//    {
//        if (this->opt.isEmpty())
//        {
//            this->num1 += "0.";
//            ui->lineEdit->setText(this->num1);
//        }
//        else {
//            this->num2 += "0.";
//            ui->lineEdit->setText(this->num2);
//        }
//        return;
//    }
    if (ui->lineEdit->text() == "0" && n != ".")
    {
        return;
    }


    //判断运算符是否为空
    if(this->opt.isEmpty())
    {
        this->num1 += n;
         ui->lineEdit->setText(this->num1);
    }
    else {
        this->num2 += n;
        ui->lineEdit->setText(this->num2);
    }

}

4.7 back 退格

  • 核心逻辑: 截取掉 num1 或者 num2 的最后一位

  • 使用方法:

    • num1.mid(start, length);

    • num2.chop(1)

//Back
    connect(ui->backBtn, &QPushButton::clicked,[this](){
        QString tmp = ui->lineEdit->text();
        if (tmp.isEmpty())
        {
           return;
        }
        tmp=tmp.mid(0,tmp.size()-1);

        if (tmp.size() > 1 && tmp[tmp.size() -1] == ".")
        {
            tmp = tmp.mid(0,tmp.size()-1);
        }

        if (this->opt.isEmpty())
        {
            this->num1 = tmp;
            ui->lineEdit->setText(this->num1);

        }
        else {
            this->num2 = tmp;
            ui->lineEdit->setText(this->num2);
        }


    });

4.8 完整的计算器代码

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>


Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->setWindowTitle("计算器");
    this->setFixedSize(363,660);

    //mid(start, length):字符串截取
    //参数1:截取的起始索引号
    //参数2:截取的长度,可选。如果不给参数2,则会截取到数据末尾

    //处理数字按钮
    connect(ui->btn9, &QPushButton::clicked,[this](){this->setNum("9");});
    connect(ui->btn8, &QPushButton::clicked,[this](){this->setNum("8");});
    connect(ui->btn7, &QPushButton::clicked,[this](){this->setNum("7");});
    connect(ui->btn6, &QPushButton::clicked,[this](){this->setNum("6");});
    connect(ui->btn5, &QPushButton::clicked,[this](){this->setNum("5");});
    connect(ui->btn4, &QPushButton::clicked,[this](){this->setNum("4");});
    connect(ui->btn3, &QPushButton::clicked,[this](){this->setNum("3");});
    connect(ui->btn2, &QPushButton::clicked,[this](){this->setNum("2");});
    connect(ui->btn1, &QPushButton::clicked,[this](){this->setNum("1");});
    connect(ui->btn0, &QPushButton::clicked,[this](){this->setNum("0");});
     connect(ui->pointBtn, &QPushButton::clicked,[this](){this->setNum(".");});
    //处理运算符按钮
    connect(ui->addBtn, &QPushButton::clicked,[this](){this->setOpt("+");});
    connect(ui->subBtn, &QPushButton::clicked,[this](){this->setOpt("-");});
    connect(ui->mulBtn, &QPushButton::clicked,[this](){this->setOpt("*");});
    connect(ui->divBtn, &QPushButton::clicked,[this](){this->setOpt("÷");});
    connect(ui->perBtn, &QPushButton::clicked,[this](){this->setOpt("%");});

    //清空
    connect(ui->clsBtn, &QPushButton::clicked,[this](){
        this->num1 = "";
        this->num2 = "";
        this->opt = "";
        ui->lineEdit->clear();
    });

    //Back
    connect(ui->backBtn, &QPushButton::clicked,[this](){
        QString tmp = ui->lineEdit->text();
        if (tmp.isEmpty())
        {
           return;
        }
        tmp=tmp.mid(0,tmp.size()-1);

        if (tmp.size() > 1 && tmp[tmp.size() -1] == ".")
        {
            tmp = tmp.mid(0,tmp.size()-1);
        }

        if (this->opt.isEmpty())
        {
            this->num1 = tmp;
            ui->lineEdit->setText(this->num1);

        }
        else {
            this->num2 = tmp;
            ui->lineEdit->setText(this->num2);
        }


    });


    //等号
    connect(ui->equarBtn, &QPushButton::clicked,[this](){
        double result = 0;
        if (this->opt == "+")
        {
            result = this->num1.toDouble() + this->num2.toDouble();
        }
        else if (this->opt == "-") {
             result = this->num1.toDouble() - this->num2.toDouble();
        }
        else if (this->opt == "*") {
             result = this->num1.toDouble() * this->num2.toDouble();
        }
        else if (this->opt == "÷") {
            if(this->num2 == "0")
            {
                ui->lineEdit->setText("除数不能为0");
                return;
            }
             result = this->num1.toDouble() / this->num2.toDouble();
        }
        else if (this->opt == "%") {
            result = this->num1.toInt() % this->num2.toInt();

        }

        ui->lineEdit->setText(QString::number(result));

        //转存结果到num1,并且清空num2和opt
        this->num1 = QString::number((result));
        this->num2 = "";
        this->opt = "";

        //qDebug() << this->num1 << this->opt  <<this->num2;
        });


}


void Widget::setNum(QString n)
{
    //对 . 的特殊验证:1)如果屏幕中有点,不能输入 . 2)屏幕为空 不能输入 .
    //如果屏幕为空,且输入为 . 不能向下执行(返回)
    if (ui->lineEdit->text().isEmpty() && n == ".")
    {
        return;
    }
    //如果屏幕中有 . ,并且当前输入的是 . ,则放回
    if (ui->lineEdit->text().count(".") == 1 && n == ".")
    {
        return;
    }

    //对 0 特殊验证:屏幕中如果只有一个0,则下一个输入必须是点
//    if(ui->lineEdit->text().isEmpty() && n == "0")
//    {
//        if (this->opt.isEmpty())
//        {
//            this->num1 += "0.";
//            ui->lineEdit->setText(this->num1);
//        }
//        else {
//            this->num2 += "0.";
//            ui->lineEdit->setText(this->num2);
//        }
//        return;
//    }
    if (ui->lineEdit->text() == "0" && n != ".")
    {
        return;
    }


    //判断运算符是否为空
    if(this->opt.isEmpty())
    {
        this->num1 += n;
         ui->lineEdit->setText(this->num1);
    }
    else {
        this->num2 += n;
        ui->lineEdit->setText(this->num2);
    }

}

void Widget::setOpt(QString o)
{
    this->opt = o;
    ui->lineEdit->clear();
}


Widget::~Widget()
{
    delete ui;
}

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

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

相关文章

策略路由控制选路

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏 华为_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 一、 实验拓扑 二、 实验简述 三、 实验配置 配置路由信息 配置控制选路 四、 实验验证 ​ 一、 实验…

「安装」 Windows下安装CUDA和Pytorch

「安装」 Windows下安装CUDA和Pytorch 文章目录 「安装」 Windows下安装CUDA和PytorchMac、Linux、云端Windows安装CUDA安装miniconda安装PyTorch测试总结 其他 Mac、Linux、云端 Mac、Linux、云端安装Miniconda和Pytorch的方法参考其他资料。 Windows 下面进行Windows下安装…

CSS选择器的全面解析与实战应用

CSS选择器的全面解析与实战应用 一、基本选择器1.1 通配符选择器&#xff08;*&#xff09;2.标签选择器&#xff08;div&#xff09;1.3 类名选择器&#xff08;.class&#xff09;4. id选择器&#xff08;#id&#xff09; 二、 属性选择器&#xff08;attr&#xff09;三、伪…

转行大模型的必要性与未来前景:迎接智能时代的浪潮

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;特别是大型语言模型&#xff08;LLM, Large Language Models&#xff09;的崛起&#xff0c;各行各业正迎来一场前所未有的技术革命。对于普通程序员而言&#xff0c;转行进入大模型领域不仅是对个人职业发展…

通配符与Powershell

通配符与正则表达式 通配符 通配符是一种特殊的语句&#xff0c;主要有*、?和[]&#xff0c;用来模糊搜索文件。 通配符表达意思举例说明*星号、匹配任何字符*.cpp匹配.cpp文件?问号、匹配任意一个字符*.?d匹配具有特定格式的文件[]中括号、匹配括号中的一个字符.[a-z]d代…

DC00020基于springboot新闻网站系统java web项目MySQL新闻管理系统

1、项目功能演示 DC00020基于springboot新闻网站系统java web项目MySQL 2、项目功能描述 基于springbootvue新闻网站包括用户和系统管理员两个角色。 2.1 用户功能 1、用户登录、用户注册 2、新闻信息&#xff1a;点赞、点踩、收藏、查看 3、用户分享&#xff1a;点赞、点踩…

分库分表还是分布式?如何用 OceanBase的单机分布式一体化从根本上解决问题

随着企业业务规模的不断增长&#xff0c;单机集中式的数据库系统逐渐难以承载企业日益增长的数据存储与处理需求。因此&#xff0c;MySQL 的分库分表方案成为了众多企业应对数据存储量激增及数据处理能力需求扩张的“止痛药”。尽管这一方案短期内有效缓解了企业面临的大规模数…

封装左侧抽屉可拖拽组件【可多个】

一、案例效果 二、案例代码 封装抽屉组件 <template><div class"drag-drawer"><div class"out-box" :style"style"><mtd-tooltip:content"collapse ? 展开面板 : 收起面板"class"tool-tip":placeme…

828华为云征文|部署敏捷项目管理系统工具 ZenTao

828华为云征文&#xff5c;部署敏捷项目管理系统工具 ZenTao 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 ZenTao3.1 ZenTao 介绍3.2 ZenTao 部署3.3 ZenTao 使用 四、总…

云 安 全 (Cloud Security)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

robomimic基础教程(四)——开源数据集

robomimic开源了大量数据集及仿真环境&#xff0c;数据集标准格式为HDF5 目录 一、基础要求 二、使用步骤 1. 下载数据集 2. 后处理 3. 训练 4. 查看训练结果 三、HDF5数据集结构与可视化 1. 数据集结构 &#xff08;1&#xff09;根级别&#xff08;data 组 group&a…

overlayscrollbars使用

官网 https://github.com/KingSora/OverlayScrollbars 使用 <link href"https://cdn.bootcdn.net/ajax/libs/overlayscrollbars/2.10.0/styles/overlayscrollbars.css" rel"stylesheet"> <script src"https://cdn.bootcdn.net/ajax/libs/…

AP配置(leaderAP组网模式)

1.前言 由于业务需求&#xff0c;临时组建一个网络环境使用 网络设备&#xff1a;华为 AirEngine 5762-10、5762S-12 2.网络结构 参考文档&#xff0c;使用leader ap组网模式 使用一台5862S-12作为leaderAP&#xff0c;AP通电后默认是fit模式&#xff0c;需要进入修改 如果…

HA Peer-mode非对称路由配置

目录 前言 一、组网拓扑 二、配置步骤 1.Hillstone-A 2.Hillstone-B 总结 前言 网络环境有非对称流量且需要双活部署时&#xff0c;防火墙可配置HA的peer-mode非对称路由模式进行实现。 一、组网拓扑 数据流量的路径是非对称的&#xff08;即 Flow0和Flow1是两条不同流量…

线性代数~行列式计算

来自b站博主&#xff0c;我爱一高数

【系统交付资料】软件文档交付清单整理套用原件(Word,PPT,Excel)

软件文档交付清单是指在软件开发项目完成后&#xff0c;开发团队需要准备的一份详细清单&#xff0c;用于确保交付的软件产品符合客户需求并达到预期的质量标准。以下是软件文档交付清单中可能包含的一些关键要素 软件资料清单列表部分文档清单&#xff1a;工作安排任务书&…

音视频入门基础:FLV专题(7)——Tag header简介

一、引言 从《音视频入门基础&#xff1a;FLV专题&#xff08;3&#xff09;——FLV header简介》中可以知道&#xff0c; 在FLV header之后&#xff0c;FLV文件剩下的部分应由PreviousTagSize和Tag组成。FLV文件 FLV header PreviousTagSize0 Tag1 PreviousTagSize1 Ta…

顺序表算法题 —— 移除元素、删除有序数组中的重复项、合并两个有序数组

目录 一、顺序表算法题 1、移除元素 2、删除有序数组中的重复项 3、 合并两个有序数组 二、顺序表问题与思考 一、顺序表算法题 1、移除元素 移除元素 - 力扣&#xff08;LeetCode&#xff09; 思路分析&#xff1a; 思路一&#xff1a;创建一个新数组&#xff0c;开辟…

828华为云征文|在Flexus X实例上安装JDK和Tomcat保姆教学

目录 一、Flexus云服务器X实例 1.1 Flexus X实例概述 1.2 Flexus X实例场景优势 1.3 其他型号与Flexus X实例比较 二、Flexus X实例上安装JDK 2.1 确定安装版本 2.2 yum命令直接安装 2.3 查看版本 三、Flexus X实例上安装tomcat 3.1 上传安装包到Flexus X实例服务器 …

拯救Air780EP模块紧急项目:异常断链的吐血经历。。。

小编最近被老板驱使&#xff0c;要用Air780EP模块做几个紧急项目 并且由于时间紧任务重&#xff0c;遇到了一些棘手问题&#xff0c;简直呕心沥血…… 左思右想&#xff0c;还是在这里把遇到的问题&#xff0c;排查记录下来 也许可以帮到因遇到类似的问题&#xff0c;并且一…