QT c++和qml交互实例

news2024/9/30 5:36:18

文章目录

      • 一、demo效果图
      • 二、c++和qml交互的基本方式
        • 1、qml访问C++类对象
      • 三、关键代码
        • 1、工程结构图
        • 2、c++代码
          • MainWindow.cpp
          • MainQuickView.cpp
          • StudentInfoView.cpp
          • StudentInfoModel.cpp
        • 3、qml代码
          • main.qml
          • MainQuickTopRect.qml
          • MainQuickMiddleRect.qml
          • MainQuickMiddleTableRect.qml

一、demo效果图

该实例,主要是在已有的QWidget工程中,加入qml工程,方便qml项目的开发与维护,让qml开发者更好的上手qml。

(1)展示了c++和qml常见的交互方式。
(2)qwidget工程如何加载qml工程,如何加载自己实现的qml tool库。
(3)创建无边框qml界面,支持拖拽,窗口的缩小与展开,界面的分段实现。
(4)展示一个简单的堆栈窗口(SwipeView),相当于QStackedWidget,管理多个子窗口页面。
(5)实现一个简单的列表框(ListView),相当于QListWidget,定时请求网络数据,展示学生信息,将view和model进行分离,降低界面与数据的耦合。
(6)点击学号、年龄,实现了列表数据的排序。

在这里插入图片描述

二、c++和qml交互的基本方式

交互有很多种方式,有的比较繁杂,不易理解,此处只使用了最方便使用的方法,满足基本的交互。

1、qml访问C++类对象

需要先将C++类(MyWindow)注册到QQuickView中。和qml相关的C++类,最好都进行注册。

class MainQuickView : public QQuickView
{
    Q_OBJECT
public:
    MainQuickView(QQuickView *parent = nullptr);
    ~MainQuickView() override;
    void initialzeUI();
protected:
};

void MainQuickView ::initialzeUI()
{
    // 注册,为了qml中可以直接访问C++对象
    MyWindow *w = new MyWindow();
    this->rootContext()->setContextProperty("myWindow", w);
	...
}

这样C++的信号public槽函数Q_INVOKABLE 修饰的类成员函数

class MyWindow : public QWidget
{
      Q_OBJECT
  public:
      MyWindow();
      // Q_INVOKABLE可以将C++函数暴漏给qml引擎,注册到元对象系统
      Q_INVOKABLE void invokableMethod();
  signals:
      void dataChanged();
  public slots:
  	  void refresh();
};

就可以在qml中调用

// main.qml
Rectangle {
    id: root
    width: 1200
    height: 800
    onClicked: {
        myWindow.showNormal(); // showNormal是QWidget父类的槽函数
    }
}

三、关键代码

1、工程结构图

在这里插入图片描述

2、c++代码
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWindow)
    , m_pQuickVew(nullptr)
{
    ui->setupUi(this);
}

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

void MainWindow::on_pushButton_clicked()
{
    if (!m_pQuickVew)
    {
    	// 加载qml包含两种方式,一种是QQuickView,一种是QQmlApplicationEngine
    	// 当前使用第一种方式,MainQuickView继承自QQuickView
        m_pQuickVew = new MainQuickView();
        m_pQuickVew->setObjectName("quickView");
    }

    m_pQuickVew->show();
}
MainQuickView.cpp
static const char* s_mainPath = "qrc:/qml/main.qml";

MainQuickView::MainQuickView(QQuickView *parent)
    : QQuickView(parent)
    , m_bMin(false)
{
    this->setFlags(Qt::Window | Qt::FramelessWindowHint);
    this->setTitle(QString::fromLocal8Bit("图书馆"));
    initialize();
    setMoveable();
    setTitleData();
}

MainQuickView::~MainQuickView()
{
}

void MainQuickView::initialize()
{
    // 初始化view 和 model,降低耦合,提高可维护性
    if (!m_pStudentInfoView)
        m_pStudentInfoView = new StudentInfoView();

    if (!m_pStudentInfoModel)
        m_pStudentInfoModel = m_pStudentInfoView->getStudentInfoMode();

    // ...其他功能

    initialzeUI();
}

void MainQuickView::initialzeUI()
{
    // 注册,qml中可以直接访问C++对象
    this->rootContext()->setContextProperty("mainQuickView", this);
	// qml可以通过"studentInfoView",去使用其实现的函数
    this->rootContext()->setContextProperty("studentInfoView", m_pStudentInfoView);
    this->rootContext()->setContextProperty("studentInfoModel", m_pStudentInfoModel);

    // qml根对象大小随窗口大小改变而改变
    this->setResizeMode(QQuickView::SizeRootObjectToView);
    // 导入自定义模块工具
    this->engine()->addImportPath(":/qmlTools");
    // 设置准备加载得qml文件,相当于c++的main函数入口
    this->setSource(QUrl(s_mainPath));
}

void MainQuickView::minMaxQmlWindow()
{
    m_bMin = !m_bMin;
    emit minQmlWindow(m_bMin);
}

void MainQuickView::onSendTopRectPos(QVariant pX, QVariant pY)
{
    this->setX(this->x() + pX.toInt());
    this->setY(this->y() + pY.toInt());
}

void MainQuickView::onCloseQuickView()
{
    close();
}

void MainQuickView::onShowMinimized()
{
    showMinimized();
}

void MainQuickView::setMoveable()
{
	// 当移动qml窗口时,将移动坐标告诉C++
    // 找到对象名叫topRect的qml,C++绑定qml的信号
    QQuickItem* topRect = this->rootObject()->findChild<QQuickItem*>("topRect");
    if (topRect) {
        connect(topRect, SIGNAL(sendTopRectPos(QVariant, QVariant)),
                this, SLOT(onSendTopRectPos(QVariant, QVariant)));
    }
}

void MainQuickView::setTitleData()
{
    // 找到对象名叫topRect的qml,C++向qml发送消息,触发qml中实现的setTitleText函数
    QQuickItem* topRect = this->rootObject()->findChild<QQuickItem*>("topRect");
    QMetaObject::invokeMethod(topRect, "setTitleText", Q_ARG(QVariant, QString::fromLocal8Bit("Qml窗口标题")));
}
StudentInfoView.cpp
StudentInfoView::StudentInfoView(QObject *parent)
    : QObject(parent)
    , m_sortType(StudentInfoSort::sortNone)
{
    if (!m_pStudentInfoModel)
        m_pStudentInfoModel = new StudentInfoModel(this);
	
	// 如果数据来自网络,就需要定时请求接口,并更新界面
    m_timer = new QTimer(this);
    m_timer->setInterval(10 * 1000);
    QObject::connect(m_timer, &QTimer::timeout, this, &StudentInfoView::onUpdateInfoData);

    onUpdateInfoData();
    m_timer->start();
}

StudentInfoModel *StudentInfoView::getStudentInfoMode()
{
    return m_pStudentInfoModel;
}

// qSort()比较函数不能定义为类成员函数(参数包含隐藏的this指针),会导致参数不符
// 可以定义为static类成员函数、static函数、普通函数
bool StudentInfoView::idAscend(const StudentInfoItem &stu1, const StudentInfoItem &stu2)
{
    return stu1.stuId < stu2.stuId; //学号升序
}

// 普通函数
bool idDescend(const StudentInfoItem &stu1, const StudentInfoItem &stu2)
{
    return stu1.stuId > stu2.stuId; //学号降序
}

bool ageAscend(const StudentInfoItem &stu1, const StudentInfoItem &stu2)
{
    return stu1.age < stu2.age; //年龄升序
}

void StudentInfoView::setSort(StudentInfoSort sortType)
{
    m_sortType = sortType;
    if (m_sortType == StudentInfoSort::sortIdAscend)
    {
        qSort(m_allDatas.begin(), m_allDatas.end(), idAscend);
    }
    else if (m_sortType == StudentInfoSort::sortIdDescend)
    {
        qSort(m_allDatas.begin(), m_allDatas.end(), idDescend);
    }
    else if (m_sortType == StudentInfoSort::sortAgeAscend)
    {
    	// 比较函数也可以写为lambda表达式
        qSort(m_allDatas.begin(), m_allDatas.end(),
              [](const StudentInfoItem& stu1, const StudentInfoItem& stu2)
        {
            return stu1.age < stu2.age;
        });
    }
}

void StudentInfoView::updateSort(int sortType)
{
	// qml调用,执行哪一种排序方式,并刷新数据
    setSort((StudentInfoSort)sortType);

    if (m_pStudentInfoModel)
        m_pStudentInfoModel->clear();

    for (auto studentInfo : m_allDatas) {
        if (m_pStudentInfoModel) {
            m_pStudentInfoModel->AddModel(studentInfo);
        }
    }
}

void StudentInfoView::onUpdateInfoData()
{
    // 每隔十秒请求网络接口,根据返回的数据刷新model,该实例模拟网络数据
    m_allDatas.clear();
    if (m_pStudentInfoModel)
        m_pStudentInfoModel->clear();

    QVector<StudentInfoItem> studentInfos;

    StudentInfoItem item1;
    item1.stuId = 9704;
    item1.stuName = QString::fromLocal8Bit("百里");
    item1.sex = 1;
    item1.age = 14;

    StudentInfoItem item2;
    item2.stuId = 9207;
    item2.stuName = QString::fromLocal8Bit("黄忠");
    item2.sex = 1;
    item2.age = 26;

    StudentInfoItem item3;
    item3.stuId = 9206;
    item3.stuName = QString::fromLocal8Bit("鲁班");
    item3.sex = 1;
    item3.age = 17;

    StudentInfoItem item4;
    item4.stuId = 9787;
    item4.stuName = QString::fromLocal8Bit("女娲");
    item4.sex = 0;
    item4.age = 33;

    studentInfos << item1 << item2 << item3 << item4;

    m_allDatas = studentInfos;
    setSort(m_sortType); //每一次网络数据刷新后,执行保存的排序方式

    for (auto studentInfo : m_allDatas) {
        if (m_pStudentInfoModel) {
            m_pStudentInfoModel->AddModel(studentInfo);
        }
    }
}
StudentInfoModel.cpp
#include "StudentInfoModel.h"

StudentInfoModel::StudentInfoModel(QObject *parent)
    : QAbstractListModel(parent)
{
    roleNames();
}

StudentInfoModel::~StudentInfoModel()
{

}

void StudentInfoModel::clear()
{
    if (m_allDatas.size() <= 0)
        return;

    beginRemoveRows(QModelIndex(), 0, m_allDatas.size() - 1);
    m_allDatas.clear();
    endRemoveRows();
}

void StudentInfoModel::mremove(int index)
{
    beginRemoveRows(QModelIndex(), index, index);
    m_allDatas.erase(m_allDatas.begin() + index);
    endRemoveRows();
}

void StudentInfoModel::update(int index, const StudentInfoItem &infoModel)
{
    if (index < 0 || m_allDatas.size() < index)
        return;

    StudentInfoItem &srcModel = m_allDatas[index];
    srcModel = infoModel;
}

void StudentInfoModel::AddModel(const StudentInfoItem &md)
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    m_allDatas.push_back(md);
    endInsertRows();
}

QVariant StudentInfoModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= m_allDatas.size()) {
        return QVariant();
    }

    const StudentInfoItem &itemInfo = m_allDatas.at(index.row());

    StudentInfoRoles infoRole = static_cast<StudentInfoRoles>(role);

    switch (infoRole) {
    case StudentInfoRoles::stuIdRole :
        return itemInfo.stuId;
        break;

    case StudentInfoRoles::stuNameRole :
        return itemInfo.stuName;
        break;

    case StudentInfoRoles::stuSexRole :
        return itemInfo.sex;
        break;

    case StudentInfoRoles::stuAgeRole :
        return itemInfo.age;
        break;

    default:
        return QVariant();
        break;
    }
}

int StudentInfoModel::rowCount(const QModelIndex &parent) const
{
    return m_allDatas.size();
}

QHash<int, QByteArray> StudentInfoModel::roleNames() const
{
    // 映射C++端的枚举与QML端的字符串
    QHash<int, QByteArray> data;

    data[int(StudentInfoRoles::stuIdRole)]   = "stuId";
    data[int(StudentInfoRoles::stuNameRole)] = "stuName";
    data[int(StudentInfoRoles::stuSexRole)]  = "sex";
    data[int(StudentInfoRoles::stuAgeRole)]  = "age";
    return data;
}
3、qml代码
main.qml
import QtQuick 2.0
import QtQuick.Layouts 1.0

Item {
    id: root
    width: 1200
    height: 800

    Rectangle {
        anchors.fill: parent
        color: "red"
        ColumnLayout {
            spacing: 0
            MainQuickTopRect {
                id: topRect
                objectName: "topRect"
                width: root.width
                height: 50
            }

            MainQuickMiddleRect {
                id: middleRect
                objectName: "middleRect"
                width: root.width
                height: root.height - topRect.height
            }
        }
    }
}
MainQuickTopRect.qml
import QtQuick 2.12
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.12
import "../qmlTools/ButtonTools"

Rectangle {
    id: root
    color: "#181D33"

    signal sendTopRectPos(var x, var y)

    function setTitleText(text) {
        titleText.text = text
    }

    function onMinQmlWindow(bMin){
        if (bMin)
            narrowBtn.clicked() // narrowBtn是最小化按钮,当然也可以直接mainQuickView.onShowMinimized()
        else
            mainQuickView.showNormal()
    }

    Component.onCompleted: {
        mainQuickView.minQmlWindow.connect(onMinQmlWindow)
    }

    RowLayout {
        id: rowLayout
        anchors.fill: root
        anchors.leftMargin: 16
        anchors.rightMargin: 16
        Text {
            id: titleText
            anchors.fill: root
            anchors.left: rowLayout.left
            verticalAlignment: Text.AlignVCenter
            horizontalAlignment: Text.AlignHCenter
            color: "white"
            font.pixelSize: 18
            font.family: "Microsoft YaHei UI"
            font.bold: true
            text: ""

            // 设置文本框背景颜色
            Rectangle {
                id: titleTextBack
                anchors.fill: titleText
                color: "#000000"
                z: -1
            }
        }

        // 最小化
        ImageBtn {
            id: narrowBtn
            width: 24
            height: 24
            anchors.right: closeBtn.left

            normalUrl: "qrc:/resource/minNormal.png"
            hoveredUrl: "qrc:/resource/minHover.png"
            pressedUrl: "qrc:/resource/minHover.png"

            onClicked: {
                mainQuickView.onShowMinimized();
                console.log("min");
            }
        }

        // 关闭
        ImageBtn {
            id: closeBtn
            width: 24
            height: 24
            anchors.right: rowLayout.right

            normalUrl: "qrc:/resource/closeNormal.png"
            hoveredUrl: "qrc:/resource/closeHover.png"
            pressedUrl: "qrc:/resource/closeHover.png"

            onClicked: {
                mainQuickView.onCloseQuickView();
            }
        }
    }

    MouseArea {
        anchors.fill: parent
        acceptedButtons: Qt.LeftButton
        propagateComposedEvents: true  //传递鼠标事件
        property point clickPos: "0, 0"

        onPressed: {
            clickPos = Qt.point(mouse.x, mouse.y)
            console.log("onPressed " + clickPos);
        }

        onPositionChanged: {
            var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y)
            sendTopRectPos(delta.x, delta.y)
        }
    }
}
MainQuickMiddleRect.qml
import QtQuick 2.0
import QtQuick 2.12
import QtQuick.Controls 1.2
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
import "../qmlTools/ButtonTools"

Rectangle {
    id: root
    color: "#2E3449"
    property int oneCount: 50
    property int twoCount: 50
    property int threeCount: 50
    readonly property int pageWidth  : 400

    Rectangle {
        id: titleSwitchBtn
        width: parent.width / 2
        anchors.top: parent.top
        anchors.topMargin: 30
        anchors.left: parent.left
        anchors.leftMargin: width - width / 2
        height: 46
        color: "#2C5CA5"

        RowLayout {
            spacing: 20
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 40

            DownLineBtn { // qmlTool中自定义实现的下划线按钮
                id: cover_one_btn
                btn_width: 100
                btn_string: qsTr("一班") + oneCount + qsTr("人")
                onMyClicked: {
                    coverBtnStat(cover_one_btn, true)
                    coverBtnStat(cover_two_btn, false)
                    coverBtnStat(cover_three_btn, false)
                    swipeView.currentIndex = 0
                }
            }

            DownLineBtn {
                id: cover_two_btn
                btn_width: 100
                btn_string: qsTr("二班") + twoCount + qsTr("人")
                onMyClicked: {
                    coverBtnStat(cover_one_btn, false)
                    coverBtnStat(cover_two_btn, true)
                    coverBtnStat(cover_three_btn, false)
                    swipeView.currentIndex = 1
                }
            }

            DownLineBtn {
                id: cover_three_btn
                btn_width: 100
                btn_string: qsTr("三班") + threeCount + qsTr("人")
                onMyClicked: {
                    coverBtnStat(cover_one_btn, false)
                    coverBtnStat(cover_two_btn, false)
                    coverBtnStat(cover_three_btn, true)
                    swipeView.currentIndex = 2
                }
            }
        }
    }

    Rectangle {
        id: view
        anchors.top: titleSwitchBtn.bottom
        anchors.topMargin: 4
        anchors.left: titleSwitchBtn.left
        width: titleSwitchBtn.width
        height: pageWidth
        color: "white"
        radius: 4

        SwipeView {
            id: swipeView
            objectName: "outSideSwipView"
            anchors.fill: parent
            currentIndex: 0
            clip: true  //隐藏未选中的界面
            interactive: false  //鼠标能否滑动

            Item {  //St: 0,第一页
                id: onePage
                Rectangle {
                    id: oneView
                    anchors.fill: parent
                    color: "#D7B9A1"
                }
            }

            Item {  //St: 1,第二页
                id: twoPage
                MainQuickMiddleTableRect {
                    id: tableView
                    color: "green"
                    width: titleSwitchBtn.width
                    height: pageWidth
                }
            }

            Item { //St: 2,第三页
                id: defaultPage

                Rectangle {
                    anchors.fill: parent
                    color: "#E6EC12"
                    radius: 4
                    Text {
                        text: qsTr("没有数据")
                        font.pixelSize:16
                        color: "red"
                        font.family: "Microsoft YaHei"
                        verticalAlignment: Text.AlignVCenter
                        horizontalAlignment: Text.AlignHCenter
                        anchors.verticalCenter: parent.verticalCenter
                        anchors.horizontalCenter: parent.horizontalCenter
                    }
                }
            }

        }
    }

    Component.onCompleted: {
    	// 初始化按钮状态
        coverBtnStat(cover_one_btn, true)
        coverBtnStat(cover_two_btn, false)
        coverBtnStat(cover_three_btn, false)
    }

    /*  btn: object
     *  st : modify state
    */
    function coverBtnStat(btn, st) {
        btn.bold_st = st
        btn.show_line = st
    }
}
MainQuickMiddleTableRect.qml
import QtQuick 2.0
import "../qmlTools/ButtonTools"
import QtQuick.Controls 1.4
import QtQuick.Controls 2.5

Rectangle {
    id: win
    anchors.fill: parent
    color: "green"

    property var current_numbers      : 0
    property var stu_id_sort_state    : 1
    property var stu_id_sort_open     : false

    // 绘制表头
    Rectangle {
        id: table_Head
        height: 48
        anchors.top: titleSwitchBtn.bottom

        Rectangle {
            id: table_Text
            height: 47  // 比整个表头高度小1,为了容纳下划线

            TextShow {
                id: name_text
                text: qsTr("姓名")
                anchors.left: table_Text.left
                anchors.leftMargin: 68
                anchors.verticalCenter: table_Text.verticalCenter
            }

            TextShow {
                id: id_text
                // 学号未点击时,显示"↕",表示不排序,点击后再判断时升序还是降序
                text: qsTr("学号") + (!stu_id_sort_open ?
                                     qsTr("↕") :
                                     (stu_id_sort_state ? qsTr("↓") : qsTr("↑")))
                anchors.left: table_Text.left
                anchors.leftMargin: 150
                anchors.verticalCenter: table_Text.verticalCenter

                MouseArea {
                    anchors.fill: parent
                    propagateComposedEvents: true
                    onPressed: {
                        console.log("student id clicked")
                        studentInfoView.updateSort(stu_id_sort_state ? 1 : 2) // 通知C++修改排序方式
                        stu_id_sort_state = !stu_id_sort_state
                        stu_id_sort_open = true
                    }
                }
            }

            TextShow {
                id: sex_text
                text: qsTr("性别")
                anchors.left: table_Text.left
                anchors.leftMargin: 220
                anchors.verticalCenter: table_Text.verticalCenter
            }

            TextShow {
                id: age_text
                text: qsTr("年龄")
                anchors.left: table_Text.left
                anchors.leftMargin: 290
                anchors.verticalCenter: table_Text.verticalCenter

                MouseArea {
                    anchors.fill: parent
                    propagateComposedEvents: true
                    onPressed: {
                        console.log("student age clicked")
                        studentInfoView.updateSort(3)
                        stu_id_sort_open = false
                    }
                }
            }

            LongLine {
                anchors.top: table_Text.bottom
            }
        }
    }

    //listView
    Rectangle {
        width: parent.width
        height: parent.height - table_Head.height
        color: "green"
        anchors.top: table_Head.bottom

        ListView {
            id: list_view
            anchors.rightMargin: 10
            anchors.bottomMargin: 50
            anchors.leftMargin: 0
            anchors.topMargin: 0
            anchors.fill: parent
            maximumFlickVelocity: 800
            clip: true
            delegate: studentInfoDelegate
            model: studentInfoModel
            boundsBehavior: Flickable.StopAtBounds
            highlightMoveDuration: 0

            ScrollBar.vertical: ScrollBar {
                id: scrollbar
                //visible: (current_numbers > 8)
                visible: true
                anchors.right: list_view.right
                width: 8
                active: true
                background: Item {
                    Rectangle {
                        anchors.right: parent.right
                        height: parent.height
                        color: "yellow"
                        radius: 4
                    }
                }
                contentItem: Rectangle {
                    radius: 4
                    color: "red"
                }
            }
        }

        //studentInfoDelegate 渲染每一个item
        Component {
            id: studentInfoDelegate
            Rectangle {
                id: list_item
                width: parent.width
                height: 46
                color: "green"

                Rectangle {
                    width: parent.width
                    height: parent.height
                    color: "green"
                    anchors.verticalCenter: parent.verticalCenter

                    Rectangle {
                        id: rect_item
                        color: "#333333"
                        height: 45

                        TextShow {
                            id: stu_name
                            text: model.stuName
                            anchors.verticalCenter: rect_item.verticalCenter
                            anchors.left: rect_item.left
                            anchors.leftMargin: 68
                        }

                        TextShow {
                            id: id_type
                            text: model.stuId
                            anchors.verticalCenter: rect_item.verticalCenter
                            anchors.left: rect_item.left
                            anchors.leftMargin: 150
                        }

                        TextShow {
                            id: sex_type
                            text: (model.sex == 1) ? qsTr("男") : qsTr("女")
                            anchors.verticalCenter: rect_item.verticalCenter
                            anchors.left: rect_item.left
                            anchors.leftMargin: 220
                        }

                        TextShow {
                            id: age_type
                            text: model.age + qsTr(" 岁")
                            anchors.verticalCenter: rect_item.verticalCenter
                            anchors.left: rect_item.left
                            anchors.leftMargin: 290
                        }
                    }

                    LongLine {
                        anchors.top: rect_item.bottom
                    }
                }
            }
        }
    }

    Component.onCompleted: {
    	// qml加载完成后,可以获取C++中数据的个数,用来标识是否需要展示滚动条
        current_numbers = 4
    }
}

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

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

相关文章

服务器cpu占用很高如何排查问题

前段时间&#xff0c;运维监控发现有个项目cpu占用很高&#xff0c;并且还在持续不断增长&#xff0c;服务不能正常响应&#xff0c;如下图&#xff1a; 在服务器上面安装了arthas&#xff0c;下载地址&#xff1a; https://alibaba.github.io/arthas/arthas-boot.jar 我使用了…

Linux stm32串口下载程序

一、工具 使用stm32flash进行串口下载 二、stm32flash安装 sudo apt-get install stm32flash 三、查看串口设备名称 先拔掉串口运行下面指令&#xff0c;获得所有设备名称,插上串口再运行一次&#xff0c;新增的就是串口设备名称&#xff0c;记住串口设备名称&#xff0c;以…

【信息论与编码】习题-判断题-第一部分

目录 判断题1. 对于N个对立并联信道&#xff0c;其信道容量CN2. 汉明码是一种线性分组码。3. 某一信源&#xff0c;不管它是否输出符号&#xff0c;只要这些符号具有某些概率特性&#xff0c;就有信息量。4. 若检错码的最小距离为dmin&#xff0c;则可以检测出任意小于等于dmin…

集团企业OA办公协同平台建设方案

一、企业对协同应用的需求分析 实现OA最核心、最基础的应用 业务流转&#xff1a;收/发文、汇报、合同等各种审批事项的业务协作与办理 信息共享&#xff1a;规章制度、业务资料、共享信息资源集中存储、统一管理 沟通管理&#xff1a;电子邮件、手机短信、通讯录、会议协作等…

期货日数据维护与使用_日数据维护_日数据更新

目录 写在前面&#xff1a; 下载日数据 下载“新增合约”日数据 下载“待更新合约”日数据 日数据文件 “选择日数据所在目录”按钮点击 “执行”按钮点击 sqlite3代码 按钮点击后执行的代码 子线程代码 写在前面&#xff1a; 本文默认已经创建了项目&#xff0c;如…

Archlinux下自启动rclone mount

路径&#xff1a; /etc/systemd/system/rclonemount.service [Unit] Descriptionrclonemount Requiresnetwork-online.target.wants Afteralist.service[Service] Typesimple ExecStartPre/bin/mkdir -p /media ExecStart/usr/bin/rclone mount \aliyun: /media \--config /ro…

Docker学习与应用(五)-DockerFile

1、DockerFile 1&#xff09;DockerFile介绍 dockerfile是用来构建docker镜像的文件&#xff01;命令参数脚本&#xff01; 构建步骤&#xff1a; 1. 编写一个dockerfile文件 2. docker build 构建称为一个镜像 3. docker run运行镜像 4. docker push发布镜像&#xff08;D…

2024最新前端源码分享(附效果图及在线演示)

分享10款非常有趣的前端特效源码 其中包含css动画特效、js原生特效、svg特效以及小游戏等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 粒子文字动画特效 基于canvas实现的粒子文字动画特效 会来回切换设定的文字特效 图…

Docker学习与应用(四)-容器数据卷

1、容器数据卷 1&#xff09;什么是容器数据卷 docker的理念回顾 将应用和环境打包成一个镜像&#xff01; 数据&#xff1f;如果数据都在容器中&#xff0c;那么我们容器删除&#xff0c;数据就会丢失&#xff01;需求&#xff1a;数据可以持久化 MySQL&#xff0c;容器删…

java推荐系统:好友推荐思路

1.表的设计 表里面就两个字段&#xff0c;一个字段是用户id&#xff0c;另外一个字段是好友id&#xff0c;假如A跟B互为好友&#xff0c;那在数据库里面就会有两条数据 2.推荐好友思路 上面的图的意思是&#xff1a;h跟a的互为好友&#xff0c;a跟b&#xff0c;c&am…

webgl调试之排查内存泄漏

内存泄漏自然而然是要看内存是不是涨了 然后我们如何确认泄露了呢&#xff0c;我们需要把代码梳理清楚&#xff0c;知道哪个时机&#xff0c;在delete&#xff0c;在create&#xff0c;那么这个时候&#xff0c;按道理&#xff0c;delete了n个对象&#xff0c;create了N个对象&…

[Excel]如何找到非固定空白格數列的條件數據? 以月份報價表單為例

在群組中看到上述問題&#xff0c;研判應是一份隨月份變動的產品報價表單&#xff0c;空白欄可能表示該月份價格與上個月份一致。這個問題是需要取得最近一次單價和倒數第二次單價&#xff0c;常用且實務的excel案例值得紀錄。 最近一次單價: INDEX($B2:$G2,1,LARGE(IF(ISBLAN…

贯穿设计模式-享元模式思考

写享元模式的时候&#xff0c;会想使用ConcurrentHashMap来保证并发&#xff0c;没有使用双重锁会不会有问题&#xff1f;但是在synchronize代码块里面需要尽量避免throw异常&#xff0c;希望有经验的同学能够给出解答&#xff1f; 1月6号补充&#xff1a;没有使用双重锁会有问…

【Qt- C++ Qml 交互】

Qt编程指南 VX&#xff1a;hao541022348 ■ 将C对象注册到 QML中&#xff0c;在QML使用C对象&#xff08;Q_INVOKABLE宏&#xff09;■ C对象注册到元对象系统■ Q_INVOKABLE 宏■ 演示步骤 ■ 将C对象注册到 QML中&#xff0c;在QML使用C对象&#xff08;Q_PROPERTY宏 属性绑定…

SpringCloud系列篇:核心组件之负载均衡组件

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.负载均衡组件是什么 二.负载均衡…

PDF文档转换工具箱流量主小程序开发

PDF转换小助手&#xff0c;不仅是文件格式转换的利器&#xff0c;更是一位得力的助手。它精通PDF与各类文档间的自由转换&#xff0c;如Word、Excel、PowerPoint等。 转换选项丰富多样&#xff0c;满足您对文件保护、页面设置、图像品质等细致要求。处理大量文件&#xff1f;…

软件工程:数据流图相关知识和多实例分析

目录 一、数据流图相关知识 1. 基本介绍 2. 常用符号 3. 附加符号 二、数据流图实例分析 1. 活期存取款业务处理系统 2. 工资计算系统 3. 商业自动化系统 4. 学校人事管理系统 5. 教材征订系统 6. 高考录取统分子系统 7. 订货系统 8. 培训中心管理系统 9. 考务处…

模仿Activiti工作流自动建表机制,实现Springboot项目启动后自动创建多表关联的数据库与表的方案

文/朱季谦 熬夜写完&#xff0c;尚有不足&#xff0c;但仍在努力学习与总结中&#xff0c;而您的点赞与关注&#xff0c;是对我最大的鼓励&#xff01; 在一些本地化项目开发当中&#xff0c;存在这样一种需求&#xff0c;即开发完成的项目&#xff0c;在第一次部署启动时&…

【视频图像篇】模糊图像处理之车辆运动造成的字体模糊还原

【视频图像篇】模糊图像处理之车辆运动造成的字体模糊还原 处理车辆运动过程中造成字体模糊重影的图像处理过程—【蘇小沐】 0、目录 1、实验环境 2、路径 3、去运动模糊&#xff08;有噪声&#xff09; 4、其它参数 5、结果展示 1、实验环境 系统环境Windows 11 专业…

phpstudy面板Table ‘mysql.proc‘ doesn‘t exist解决办法

原因分析&#xff1a;误删了mysql数据库 解决办法如下&#xff1a; 1、停止服务 2、先把mysql文件夹下的data文件夹备份&#xff0c;因为data文件里存有数据库文件。然后再删除data文件。 3、cmd管理员命令进入到mysql中的bin目录下 &#xff0c;执行mysqld --initialize-…