嵌入式学习-QT-Day06

嵌入式学习-QT-Day06

六、多窗口编程

1、QMessageBox 消息对话框

2、QWidget类

3、parent参数

4、堆栈窗口(QStackedWidget)

5、新建自定义窗口类

6、对象传值

6.1 父对象 → 子对象

6.2 子对象 → 父对象

7、事件机制

8、QMainWindow主窗口类

8.1 QMenuBar 菜单栏

8.2 QToolBar 工具栏

8.3 QStatusBar状态栏

六、多窗口编程

1、QMessageBox 消息对话框

QMessageBox继承自QDialog。显式一个模态对话框,用于用户前台信息通知或者询问用户问题,并接收问题答案。

QDialog的Qt源码中,派生类往往都是一些在特定场合下使用的预设好的对话框窗口,这些窗口的使用无需创建对象,直接使用静态成员函数弹窗,使用函数的返回值作为这个窗口的结果。

// QMessageBox的弹窗函数
// 参数1:parent参数
// 参数2:窗口标题
// 参数3:信息内容,窗口展示的信息
// 返回值:用户点击的按钮类型
StandardButton	critical(QWidget * parent, const QString & title, const QString & text)StandardButton	information(QWidget * parent, const QString & title, const QString & text)StandardButton	question(QWidget * parent, const QString & title, const QString & text)StandardButton	warning(QWidget * parent, const QString & title, const QString & text)
[static]

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QMessageBox>
#include <QButtonGroup>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
private:
    QButtonGroup *btp;private slots:
    void buttonClickedSlot(int);
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);    btp = new QButtonGroup(this);    btp->addButton(ui->pushButtonQ,1);
    btp->addButton(ui->pushButtonI,2);
    btp->addButton(ui->pushButtonW,3);
    btp->addButton(ui->pushButtonC,4);    connect(btp,SIGNAL(buttonClicked(int)),
            this,SLOT(buttonClickedSlot(int)));
}Dialog::~Dialog()
{
    delete btp;
    delete ui;
}void Dialog::buttonClickedSlot(int id)
{
    if(id == 1)
    {
        // 设置弹窗
        QMessageBox::StandardButton stdb = QMessageBox::question(this,"question","是否需要关闭?");
        if(stdb == QMessageBox::Yes)
        {
            close();
        }
        else if(stdb == QMessageBox::No)
        {        }
    }
    else if(id == 2)
    {
        QMessageBox::information(this,"information","已加载完成!!!!");
    }
    else if(id == 3)
    {
        QMessageBox::warning(this,"warning","您的输入有误!!!");
    }
    else if(id == 4)
    {
        QMessageBox::critical(this,"critical","程序异常,缺少必要文件!!");
    }
    else
    {    }
}

2、QWidget类

QWidget类是所有窗口和组件的基类,之前认识此类更多是站在组件的角度,实际上QWidget身为所有窗口的基类,本身也具有很多窗口的特性,窗口类的继承结构如下所示:

新建一个项目,使自带的窗口类继承QWidget。

创建完成后运行时发现,与dialog的窗口并无太大区别。表面区别有:

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{
    QApplication a(argc, argv);    // 当QWidget类的构造函数parent参数使用默认值0时,表示创建的是独立窗口
    // 当QWidget类的构造函数parent参数传递参数时,新创建的QWidget类对象会成为子窗口(内嵌窗口)
    Widget w;
    w.show();    return a.exec();
}

QWidget类作为所有窗口的基类,内部也规定了很多窗口特性:

  • windowTitle : QString

  • windowFlags : Qt::WindowFlags(窗口标记)

使用setter函数设置多个窗口标记,使用 | 分割(多个窗口标记之间可能会出现冲突)。实现窗口置于最上层、且没有边框。

设置窗口状态:

// 设置窗口状态
// 参数为窗口状态
void QWidget::​setWindowState(Qt::WindowStates windowState)

3、parent参数

目前对parent参数的理解有以下几点:

  • parent参数表示子组件位于那个窗口中。
  • parent参数还决定了QWidget对象是独立窗口还是内嵌窗口

实际上parent参数还表示Qt的内存回收机制,如果对象a作为对象b的构造函数的parent参数时,表示对象a是对象b的父对象,这是一种内存回收的依赖关系,即对象b跟随对象a一并销毁。此时无需手动控制对象b的销毁过程(手动调用delete)。

如果堆内存对象创建时不传递parent参数,表示对对象调用需要程序员手动delete。

这样做也有缺点,缺点就是内存占用,主窗口还存在时,子窗口内存不会被释放掉。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QDebug>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;private slots:
    void buttonClickedSlot();
    void buttonThisClickedSlot();
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(buttonClickedSlot()));    connect(ui->pushButtonThis,SIGNAL(clicked()),
            this,SLOT(buttonThisClickedSlot()));
}Dialog::~Dialog()
{
    qDebug() << "析构函数";
    delete ui;
}void Dialog::buttonClickedSlot()
{
    Dialog *dlg = new Dialog;
    dlg->show();
}void Dialog::buttonThisClickedSlot()
{
    Dialog *dlg = new Dialog(this);
    dlg->show();
}

4、堆栈窗口(QStackedWidget)

通常作为独立窗口的内嵌窗口(组件),并于QListWidget进行联动。

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);    // 连接信号槽
    connect(ui->listWidget,SIGNAL(currentRowChanged(int)),
            ui->stackedWidget,SLOT(setCurrentIndex(int)));
}Dialog::~Dialog()
{
    delete ui;
}

5、新建自定义窗口类

在一个项目中新建一个Qt的窗口界面类,操作步骤如下:

  1. 在QtCreator中选中项目名称,鼠标右键,点击添加新文件。
  2. 在弹出的窗口中,按照下图所示进行操作。

在弹出的窗口中选择界面模板后,点击“下一步”

在弹出的窗口,输入类名(注意帕斯卡命名法/大驼峰命名法)然后点击下一步。

在项目管理界面点击完成,可以看到新的窗口类文件就已经添加到项目中了。

ui格式如下:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;private slots:
    void btnClickedSlot();
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
}Dialog::~Dialog()
{
    delete ui;
}void Dialog::btnClickedSlot()
{
    MyDialog *mydlg = new MyDialog(this);
    mydlg->show();
}

6、对象传值

6.1 父对象 → 子对象

此处指的是Qt的parent参数的依赖关系,并非继承关系。后文同。

【需求】转动左边球,右边球跟着转。

这种情况下最佳的解决方案是使用C++的成员函数传参。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
    MyDialog *mydlg;private slots:
    void btnClickedSlot();
    void valueChangedSlot(int);
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
}Dialog::~Dialog()
{
    delete ui;
}void Dialog::btnClickedSlot()
{
    mydlg = new MyDialog(this);
    mydlg->show();    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}void Dialog::valueChangedSlot(int value)
{
    mydlg->setDialValue(value);
}

mydialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H#include <QDialog>namespace Ui {
class MyDialog;
}class MyDialog : public QDialog
{
    Q_OBJECTpublic:
    explicit MyDialog(QWidget *parent = 0);
    ~MyDialog();
    void setDialValue(int value);private:
    Ui::MyDialog *ui;
};#endif // MYDIALOG_H

myDialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"MyDialog::MyDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MyDialog)
{
    ui->setupUi(this);
}MyDialog::~MyDialog()
{
    delete ui;
}void MyDialog::setDialValue(int value)
{
    ui->dial->setValue(value);
}

6.2 子对象 → 父对象

此处指的是Qt的parent参数的依赖关系,并非继承关系。

【需求】转动子窗口的球,父窗口的球跟着转。

这种情况最佳的解决方案是信号槽传参,子对象发射带参数的信号函数,父对象使用带参数的槽函数接收。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include "mydialog.h"namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
    MyDialog *mydlg;private slots:
    void btnClickedSlot();
    void valueChangedSlot(int);
    void valueDialogSlot(int);
};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);    connect(ui->pushButton,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
}Dialog::~Dialog()
{
    delete ui;
}void Dialog::btnClickedSlot()
{
    mydlg = new MyDialog(this);
    mydlg->show();    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));    connect(mydlg,SIGNAL(valueSignal(int)),
            this,SLOT(valueDialogSlot(int)));
}void Dialog::valueChangedSlot(int value)
{
    mydlg->setDialValue(value);
}void Dialog::valueDialogSlot(int value)
{
    ui->dial->setValue(value);
}

myDialog.h

#ifndef MYDIALOG_H
#define MYDIALOG_H#include <QDialog>namespace Ui {
class MyDialog;
}class MyDialog : public QDialog
{
    Q_OBJECTpublic:
    explicit MyDialog(QWidget *parent = 0);
    ~MyDialog();
    void setDialValue(int value);private:
    Ui::MyDialog *ui;signals:
    void valueSignal(int);  // 声明带参数的自定义信号private slots:
    void valueChangedSlot(int);
};#endif // MYDIALOG_H

myDialog.cpp

#include "mydialog.h"
#include "ui_mydialog.h"MyDialog::MyDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MyDialog)
{
    ui->setupUi(this);    connect(ui->dial,SIGNAL(valueChanged(int)),
            this,SLOT(valueChangedSlot(int)));
}MyDialog::~MyDialog()
{
    delete ui;
}void MyDialog::setDialValue(int value)
{
    ui->dial->setValue(value);
}void MyDialog::valueChangedSlot(int value)
{
    // 发射带参数的信号函数
    emit valueSignal(value);
}

7、事件机制

事件是Qt的一种底层机制,经过层层筛选,程序员可以在传递的层级中检测或者处理这些事件。

本次学习主要在窗口类中实现事件函数,从而检测到事件的传递。利用事件的触发机制,从而实现一些特定的效果。事件函数众多,包括但不限于:

// 绘制事件
void QWidget::paintEvent(QPaintEvent * event) [virtual protected] // 大小改变事件
void QWidget::resizeEvent(QResizeEvent * 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 QWidget::mouseMoveEvent(QMouseEvent * event) [virtual protected]// 移动事件
void QWidget::moveEvent(QMoveEvent * event) [virtual protected]// 按键按压事件
void QWidget::keyPressEvent(QKeyEvent * event) [virtual protected]
// 按键释放事件
void QWidget::keyReleaseEvent(QKeyEvent * event) [virtual protected]// 获取焦点事件
void QWidget::focusInEvent(QFocusEvent * event) [virtual protected]
// 失去焦点事件
void QWidget::focusOutEvent(QFocusEvent * event) [virtual protected]// 关闭事件
void QWidget::closeEvent(QCloseEvent * event) [virtual protected]// 鼠标进入事件
void QWidget::enterEvent(QEvent * event) [virtual protected]
// 鼠标离开事件
void QWidget::leaveEvent(QEvent * event) [virtual protected]

事件函数的基础使用只需要在对应的类中覆盖基类的事件函数即可。事件函数的参数就是包含了当前事件数据的对象。

绘制事件:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPainter> // 画家类
#include <QPixmap>
#include <QDebug>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
    void paintEvent(QPaintEvent * event);};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}Dialog::~Dialog()
{
    delete ui;
}void Dialog::paintEvent(QPaintEvent *event)
{
    // 创建画家类对象
    // 参数为 QPaintDevice *表示可绘制的对象
    QPainter painter(this);    QPixmap map(":/new/prefix1/meinv.png");
    // 绘制图片
    // 参数1:横轴坐标
    // 参数2:纵轴坐标
    // 参数3:绘制宽度
    // 参数4:绘制高度
    // 参数5:绘制内容
    painter.drawPixmap(0,0,this->width(),this->height(),map);
    qDebug() << this->width() << this->height();
    qDebug() << this->x() << this->y();
}

【案例】按下键盘A、D、W、S键控制进度条加或者减

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QPainter> // 画家类
#include <QPixmap>
#include <QDebug>
#include <QKeyEvent>namespace Ui {
class Dialog;
}class Dialog : public QDialog
{
    Q_OBJECTpublic:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();private:
    Ui::Dialog *ui;
    void paintEvent(QPaintEvent * event);
    void keyPressEvent(QKeyEvent * event);};#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}Dialog::~Dialog()
{
    delete ui;
}void Dialog::paintEvent(QPaintEvent *event)
{
    // 创建画家类对象
    // 参数为 QPaintDevice *表示可绘制的对象
    QPainter painter(this);    QPixmap map(":/new/prefix1/meinv.png");
    // 绘制图片
    // 参数1:横轴坐标
    // 参数2:纵轴坐标
    // 参数3:绘制宽度
    // 参数4:绘制高度
    // 参数5:绘制内容
    painter.drawPixmap(0,0,this->width(),this->height(),map);
    qDebug() << this->width() << this->height();
    qDebug() << this->x() << this->y();
}void Dialog::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A)  // 如果按键是A
    {
        int value = ui->progressBar->value();
        ui->progressBar->setValue(--value);
    }
    else if(event->key() == Qt::Key_D)
    {
        int value = ui->progressBar->value();
        ui->progressBar->setValue(++value);
    }
    else if(event->key() == Qt::Key_W)
    {
        ui->progressBar->setValue(100);
    }
    else if(event->key() == Qt::Key_S)
    {
        ui->progressBar->setValue(0);
    }
    else
    {
    }
}

8、QMainWindow主窗口类

QMainWindow是最适合作为主窗口的类型,因为其中包含了多个组成部分:

8.1 QMenuBar 菜单栏

菜单栏的组成如下所示:

菜单栏的构建可以通过Designer,也可以通过C++代码实现,但是不要混用。

// 向菜单栏中添加一级菜单
// 参数为菜单的文字
// 返回值是添加的菜单对象
QMenu * QMenuBar::​addMenu(const QString & title)
// 向菜单中添加动作
// 参数为菜单的文字
// 返回值是添加的动作对象
QAction * QMenu::​addAction(const QString & text)

QMainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);    QMenu* menuFile = ui->menuBar->addMenu("文件");
    QMenu* menuEdit = ui->menuBar->addMenu("编辑");
    QMenu* menuHelp = ui->menuBar->addMenu("帮助");    // 向一级菜单中添加动作
    QAction* actionNew = menuFile->addAction("新建");
    QAction* actionSave = menuFile->addAction("保存");
    QAction* actionOpen = menuFile->addAction("打开");    // 向一级菜单中添加二级菜单
    QMenu* menuRecent = menuFile->addMenu("最近访问的文件");    // 向二级菜单中添加动作
    QAction* actionCpp = menuRecent->addAction("hello.cpp");
    QAction* actionH = menuRecent->addAction("hello.h");}MainWindow::~MainWindow()
{
    delete ui;
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QMenu>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
    Q_OBJECTpublic:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();private:
    Ui::MainWindow *ui;private slots:
    void actionNewTriggredSlot();
    void actionCppTriggredSlot();};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);//    QMenu* menuFile = ui->menuBar->addMenu("文件");
//    QMenu* menuEdit = ui->menuBar->addMenu("编辑");
//    QMenu* menuHelp = ui->menuBar->addMenu("帮助");//    // 向一级菜单中添加动作
//    QAction* actionNew = menuFile->addAction("新建");
//    QAction* actionSave = menuFile->addAction("保存");
//    QAction* actionOpen = menuFile->addAction("打开");//    // 向一级菜单中添加二级菜单
//    QMenu* menuRecent = menuFile->addMenu("最近访问的文件");//    // 向二级菜单中添加动作
//    QAction* actionCpp = menuRecent->addAction("hello.cpp");
//    QAction* actionH = menuRecent->addAction("hello.h");    connect(ui->action_2,SIGNAL(triggered()),
            this,SLOT(actionNewTriggredSlot()));    connect(ui->actionHello_cpp,SIGNAL(triggered()),
            this,SLOT(actionCppTriggredSlot()));}MainWindow::~MainWindow()
{
    delete ui;
}void MainWindow::actionNewTriggredSlot()
{
    ui->textBrowser->append("新建了一个文件");
}void MainWindow::actionCppTriggredSlot()
{
    ui->textBrowser->append("打开了hello.cpp");
}

8.2 QToolBar 工具栏

工具栏按钮往往使用菜单栏中的QAction对象,但是需要给QAction设置图标。

8.3 QStatusBar状态栏

QStatusBar支持自定义样式,可以通过下面的函数添加组件。

// 状态栏显式信息
// 参数1:组件对象
// 参数2:拉伸因子
void QStatusBar::​addWidget(QWidget * widget, int stretch = 0)

普通使用可以通过下面槽函数进行显示和消除。

// 在状态栏展示信息
// 参数1:显示的信息内容
// 参数2:信息显示的时间(单位毫秒),默认值0表示持续显示
void QStatusBar::​showMessage(const QString & message, int timeout = 0)[slot]

// 清空显示
void QStatusBar::​clearMessage()[slot]

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

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

相关文章

《战神:诸神黄昏》游戏运行时提示找不到gamede.dll文件怎么办?gamede.dll丢失的修复指南

在沉浸于《战神&#xff1a;诸神黄昏》的壮阔世界时&#xff0c;突然弹出的“找不到gamede.dll文件”错误提示可能会让玩家措手不及。作为一名经验丰富的软件开发从业者&#xff0c;我深知这类问题对游戏体验的影响。今天&#xff0c;我将为大家详细解析gamede.dll文件丢失的原…

1.系统学习-线性回归

系统学习-线性回归 前言线性回归介绍误差函数梯度下降梯度下降示例 回归问题常见的评价函数1. MAE, mean absolutely error2. MSE, mean squared error3. R square &#xff08;决定系数或R方&#xff09; 机器学习建模流程模型正则化拓展阅读作业 链接: 2.系统学习-逻辑回归 …

基于微信小程序的校园访客登记系统

基于微信小程序的校园访客登记系统 功能列表 用户端功能 注册与登录 &#xff1a;支持用户通过手机号短信验证码注册和登录。个人资料管理 &#xff1a;允许用户编辑和更新个人信息及其密码。站内信消息通知&#xff1a;通知公告。来访预约&#xff1a;提交来访预约支持车牌…

H3C MPLS跨域optionB

实验拓扑 实验需求 如图,VPN1 和 VPN2 分别通过运营商 MPLS VPN 连接各自分支机构按照图示配置 IP 地址,VPN1 和 VPN2 连接同一个 PE 设备的私网 IP 网段存在地址复用,使用多 VRF 技术来防止 IP 冲突AS 100 和 AS 200 内部的公共网络中各自运行 OSPF 使 AS 内各设备的 Loo…

【项目管理】根据业务流程进行函数结构设计和模块化设计

在开发一个复杂的系统时&#xff0c;根据业务流程进行函数结构设计和模块化设计是一个非常重要的步骤。通过这种方式&#xff0c;能够将复杂的业务逻辑拆分成多个功能模块和函数&#xff0c;使代码更清晰、易维护、易扩展。我们在写代码的时候需要基于对于业务的理解来编程&…

VMware虚拟机中CentOS系统/dev/mapper/centos-home分区扩容指南

要将VMware上新扩展的磁盘添加到CentOS虚拟机,并将其扩容到/dev/mapper/centos-home下,你可以按照以下步骤操作: 一、在VMware中扩展虚拟机磁盘 关闭CentOS虚拟机:确保在扩展磁盘之前,CentOS虚拟机已经关闭。 编辑虚拟机设置:在VMware中,右键点击CentOS虚拟机,选择“设…

GPUStack v0.4.1 单节点与多节点安装与部署指南 Docker PowerShell

Introduce GPUStack 是一个开源的 GPU 集群管理器&#xff0c;专为运行 AI 模型而设计。它以其广泛的硬件兼容性而闻名&#xff0c;支持多种品牌的 GPU&#xff0c;并能在 Apple MacBook、Windows PC 和 Linux 服务器上运行。 GPUStack支持各种AI模型&#xff0c;包括大型语言…

【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

Hiヽ(゜▽゜ )&#xff0d;欢迎来到蓝染Aizen的CSDN博客~ &#x1f525; 博客主页&#xff1a; 【✨蓝染 の Blog&#x1f618;】 &#x1f496;感谢大家点赞&#x1f44d; 收藏⭐ 评论✍ 文章目录 行为型模式1、模板方法模式&#xff08;1&#xff09;概述&#xff08;2&…

【解决报错】AttributeError: ‘NoneType‘ object has no attribute ‘group‘

学习爬虫时&#xff0c;遇到如下报错&#xff1a; 报错原因&#xff1a; 正则表达式的 search 或 finditer 方法没有找到任何匹配项&#xff0c;可能是换行符处理不当等。 解决方法如下&#xff1a; 在正则表达式末尾加上re.S即可&#xff0c;re.S是一个编译标志&#xff0c…

一款5k star的 Redis 客户端!!简洁高效!

作为一名热爱编程的程序员&#xff0c;对于高效的工具总是格外追求。在日常的开发中&#xff0c;Redis 作为一款优秀的内存数据库&#xff0c;是我们不可或缺的利器之一。了不起之前也推荐过一些出色的 Redis 客户端&#xff0c;它们在提升我们的开发效率和便利性方面发挥了巨大…

关于科研中使用linux服务器的集锦

文章目录 常用的linux命令下载COCO2017数据集 常用的linux命令 一个文件移动到另一个目录下的命令是&#xff1a;mv -v ./old_name ./new_name 如果目标文件夹中已经有同名文件或文件夹&#xff0c;mv 会覆盖它们&#xff08;除非使用了 -i 选项来提示确认&#xff09;。 使用…

Vue开发环境搭建上篇:安装NVM和NPM(cpnm、pnpm)

文章目录 引言I 安装NVM1.1 Windows系统安装NVM,实现Node.js多版本管理1.2 配置下载镜像1.3 NVM常用操作命令II NPM永久使用淘宝源安装 cnpm安装pnpm【推荐】see also: vscode常用插件引言 淘宝镜像:http://npm.taobao.org 和 http://registry.npm.taobao.org 已在 2022.06.3…

x86_64 Ubuntu 编译安装英伟达GPU版本的OpenCV

手把手带你在Linux上安装带GPU加速的opencv库&#xff08;C版本&#xff09;_opencv linux-CSDN博客 cmake \-D CMAKE_BUILD_TYPERELEASE \-D OPENCV_GENERATE_PKGCONFIGON \-D CMAKE_INSTALL_PREFIX/usr/local \-D OPENCV_EXTRA_MODULES_PATH/home/hwj/opencv/opencv_contrib…

计算机毕业设计Python+卷积神经网络租房推荐系统 租房大屏可视化 租房爬虫 hadoop spark 58同城租房爬虫 房源推荐系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

bypy上传配置

bypy upload 上传文件权限不足时 使用此方法,改变权限保存 : w ! sudo tee % 好使但是没有进度条 CMAKE 的配置方法

三维动画的常用“视觉特效”有哪些?

在当今的视觉盛宴中&#xff0c;三维动画技术宛如一位神奇的魔法师&#xff0c;为视觉特效&#xff08;VFX&#xff09;领域施下了变革的咒语。从大荧幕上的震撼电影&#xff0c;到让人沉浸其中的视频游戏&#xff0c;再到夺人眼球的广告以及精细的模拟场景&#xff0c;三维动画…

《Cocos Creator游戏实战》非固定摇杆实现原理

为什么要使用非固定摇杆 许多同学在开发摇杆功能时&#xff0c;会将摇杆固定在屏幕左下某一位置&#xff0c;不会让其随着大拇指触摸点改变&#xff0c;而且玩家只有按在了摇杆上才能移动人物&#xff08;触摸监听事件在摇杆精灵上)。然而&#xff0c;不同玩家的大拇指长度不同…

Text组件的用法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了页面之间传递数据相关的内容,本章回中将介绍如何使用Text Widget。闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的Text Widget就是显示文字内容的组件,其实我们一直在使用它,只是没有详细介…

强大且灵活的终端工具Tabby的强大功能与详细配置指南

文章目录 前言1. Tabby下载安装2. Tabby相关配置3. Tabby简单操作4. ssh连接Linux4.1 ubuntu系统安装ssh4.2 Tabby远程ssh连接ubuntu 5. 安装内网穿透工具5.1 创建公网地址5.2 使用公网地址远程ssh连接 6. 配置固定公网地址 前言 大家好&#xff01;今天我要给大家安利一个超级…

基于Spring Boot的阿坝州旅游系统

一、系统背景与目的 随着旅游业的快速发展和互联网技术的不断进步&#xff0c;越来越多的游客开始通过网络平台来查询旅游信息、预订旅游产品。为了满足游客对阿坝州旅游信息的需求&#xff0c;提升阿坝州旅游业的整体服务水平&#xff0c;基于Spring Boot技术框架开发了一款阿…