Qt绘制动态仪表(模仿汽车仪表指针、故障灯)

背景:

项目需要,可能需要做一些仪表显示。此篇除了介绍实现方法,还要说明心路历程。对我而言,重要的是心理,而不是技术。写下来也是自勉。

本人起初心里是比较抵触的,从业20多年了,深知所谓界面,实际上最根本还是代码实现的,操作系统层面多少年来一步步发展更新,是靠不断封装演变来的。所谓的可视化开发,主要还是靠ide提供的插件控件,通常只是应用。如果要按照自己的想法做个什么,那就是绘图机制,把代码变成图不用想就知道麻烦。基于这种心理,就是再说qt可以做得很炫,个人表示一看就够那种,根本看不进去。

终究为了活下去,所以要保住工作,也是对技术的不服输,所以不忙时打开qt示例,看它的文档。其实看过很多遍了,主要是看不进去。终于要善于提炼代码,看它的主要部分,缩小规模,然后研读手册,必要时看看别人怎么说的,逐个尝试,最后形成自己的总结,就学会了。

下面只介绍干货。

用法总结:

所谓绘图机制,肯定用到paintEvent函数,每一个能看到的窗体都是使用操作系统的重绘机制显示的。说人话就是,绘图的过程要写在paintEvent函数里,只要做了更新显示操作,记着调用update函数,它会调用paintEvent函数重绘界面。

qt绘图就一个QPainter,所有事都是它干的。QPen用于设置边框边线,QBrush用于设置填充。
painter画任何东西都是有个draw***函数。

画任何东西都基于坐标系,所以要先操作坐标系,再画。比如想画仪表盘刻度,设定好间隔(循环),转一次坐标系,画一个短线,最后转完一圈,也就画了一圈刻度。

painter就是画画,肯定后画的覆盖先画的,跟图层似的。

因为能旋转坐标系,所以要记住前后的坐标系状态,所以前面调用QPainter::save(),最后调用QPainter::restore()。比如画仪表,开始画背景是正常坐标系,接着通过旋转坐标系画刻度,最后要在正常坐标系下画表轴或者其它东西。这中间,旋转坐标系那部分,就需要暂存painter状态,画完这部分再恢复。

具体下面例子说明。

下面无论我画什么,都不再贴mainwindow代码了,没有必要,每个仪表都是一个类,使用时,在界面画一个label,提升为这个类即可。

手绘仪表盘:

思路是:

先画个黑色矩形当背景;

再旋转坐标系画刻度;

通过一个全局的成员变量值,作为指针旋转角度值,通过旋转坐标系把指针画到相应位置;

最后画一个转轴盖住指针(其实也可以把指针别画那么长,留出圆心位置即可)。

我鸟语不行,注释部分,看官您忽略就好。至于表芯转轴,你们说叫hand heart还是center?要不咱别较真的了,主要看代码。

guage_watertemp.h

/**************************************************************************************************** File name:      guage_watertemp.h (Guage_WaterTemp)** Created by:     Henrick.Nie at 2024-9-8** Used for:       The car water temprature guage.**************************************************************************************************/
#ifndef GUAGE_WATERTEMP_H
#define GUAGE_WATERTEMP_H#include <QLabel>
#include <QPainter>
#include <QDebug>class Guage_WaterTemp : public QLabel
{Q_OBJECTpublic:explicit Guage_WaterTemp(QWidget *parent = nullptr);void f_SetTemp(const qreal &realTemp);private:qreal m_realTemp, m_realMin = 25, m_realMax = 155;void paintEvent(QPaintEvent *event);void f_Draw(QPainter *p);
};#endif // GUAGE_WATERTEMP_H

guage_watertemp.cpp

#include "guage_watertemp.h"Guage_WaterTemp::Guage_WaterTemp(QWidget *parent) :QLabel(parent)
{
}
void Guage_WaterTemp::paintEvent(QPaintEvent *event)
{QLabel::paintEvent(event);QPainter painter(this);f_Draw(&painter);
}
void Guage_WaterTemp::f_Draw(QPainter *p)
{QColor colorHand = QColor(Qt::red);//Init the size data.int iHeartSize = width() / 5;int iX0 = width() / 2, iY0 = height() - iHeartSize;int iBackWidth = width(), iBackHeight = width() / 2 + iHeartSize * 1.5 ;int iBackLeft = 0 - iBackWidth / 2, iBackTop = 0 - iBackWidth / 2 - iHeartSize / 2;int iMarkSize = iBackWidth / 40, iMarklength = iBackWidth / 20;int iHandSize = iBackWidth / 25, iHandLeft = iBackLeft + width() / 20, iHandLength = iBackWidth / 2 - iBackWidth / 20;int iText30Left = iBackLeft + width() / 28, iText30Top = 0 - width() / 15;int iText90Left = 0 - width() / 18, iText90Top = 0 - width() / 4;int iText150Left = width() / 3.5, iText150Top = iText30Top;//Init the origin.p->setRenderHint(QPainter::Antialiasing);p->translate(iX0, iY0);//Draw the black rect as the background.p->setPen(Qt::NoPen);p->setBrush(QBrush(Qt::black));p->drawRect(iBackLeft, iBackTop, iBackWidth, iBackHeight);//Draw the hand heart on the origin.p->setPen(QPen(QBrush(colorHand), iHeartSize, Qt::SolidLine, Qt::RoundCap));p->drawPoint(0, 0);//Draw the mark. (From 30 degrees to 150 degrees, 150-30=120, 120/10=12)p->save();p->rotate(30);for(int i = 30; i <= 150; ++i){QBrush brush = (i < 140) ? QBrush(Qt::white) : QBrush(Qt::red);p->setPen(QPen(brush, iMarkSize));p->drawPoint(iBackLeft, 0);p->rotate(1);}p->restore();QList<int> iList_Big = { 30, 90, 150 };p->save();p->rotate(30);for (int i = 30; i <= 150; i += 12){int iSize = iList_Big.contains(i) ? iMarkSize * 2 : iMarkSize;int iLeft = iList_Big.contains(i) ? iBackLeft + iMarkSize / 2 : iBackLeft;int iLength = iList_Big.contains(i) ? iMarklength + 10 : iMarklength;QBrush brush = (i < 130) ? QBrush(Qt::white) : QBrush(Qt::red);p->setPen(QPen(brush, iSize));p->drawLine(iLeft, 0, iLeft + iLength, 0);p->rotate(12);}p->restore();//Draw the mark text.p->setFont(QFont("", width() / 10));p->setPen(QPen(QBrush(Qt::white), width() / 18));p->drawText(iText30Left, iText30Top, "30");p->drawText(iText90Left, iText90Top, "90");p->drawText(iText150Left, iText150Top, "150");//Draw hands.p->save();p->setPen(QPen(QBrush(colorHand), iHandSize, Qt::SolidLine, Qt::RoundCap));if (m_realTemp < m_realMin){m_realTemp = m_realMin;}if (m_realTemp > m_realMax){m_realTemp = m_realMax;}p->rotate(m_realTemp);p->drawLine(iHandLeft, 0, iHandLeft + iHandLength, 0);p->restore();p->end();
}
void Guage_WaterTemp::f_SetTemp(const qreal &realTemp)
{m_realTemp = realTemp;update();
}

效果:

a962b05de3a946b48078be5bef15a3be.jpeg

其实我是仿照大众polo劲情的水温表画的。至于指针,既然是旋转肯定是角度。看到表盘的样式时,要大致估计一下,最左侧和左右侧的刻度大概是坐标轴上的多少度。算一下它的跨度,和实际需要的水温数值要有个转换。比方说,这个水温表的刻度刚好是水温和角度一一对应,所以不用转换。

其实做到这一步时,完全可以在demo里让它显示真实的角度,这样这个demo就成了一个量角器,有助于后期调整精确度。

图片仪表盘:

上面看到效果后会很有成就感,但要把仪表盘画得逼真可不容易,还要考虑缩放和字体,细节太多。因此有了这种方法,从网上找图片素材,自己加工仪表盘。直接先把图片画上去当背景,然后代码只控制表针即可。以后修改背景表盘,photoshop修图即可。

后期又做了小修改,因为图片作为资源文件,每个人安排的路径可能不同,通用起见,需要调用f_Init函数先初始化路径前缀。

先看我找的素材:

d814b1bb900543c890953131dc6a1ac0.jpeg

再看我修好的效果:

f45cc417af744fc0a094cea34aceea04.jpeg4b797a398adc43fe92b78c8c647bf3b3.jpeg5931d8ffe67c407ba81f61899e8e73b8.jpegd7a770143027477db7d06663705ecf2e.jpeg

上代码:

polo_base.h

/**************************************************************************************************** File name:      polo_baes.h (Polo_Base)** Created by:     Henrick.Nie at 2024-9-9** Used for:       The base class of the polo guage.** Using method:****     Firstly, a image resource path is required.****         obj->f_Init(":/images/");****************************************************************************************************/#ifndef POLO_BASE_H
#define POLO_BASE_H#include <QLabel>
#include <QPainter>
#include <QDebug>class Polo_Base : public QLabel
{Q_OBJECT
public:explicit Polo_Base(QWidget *parent = nullptr);inline virtual void f_Init(const QString &sRcPathPrefix) = 0;inline qreal f_GetDegrees() const { return m_realDegrees; }protected:inline void f_SetBack(const QString &sFileName) { m_sPicPath = sFileName; }virtual void f_SetValue(const qreal &realValue);private:QString m_sPicPath;qreal m_realDegrees, m_realMin = 40, m_realMax = 140;void paintEvent(QPaintEvent *event);void f_Draw(QPainter *p);
};#endif // POLO_BASE_H

polo_base.cpp

#include "polo_base.h"Polo_Base::Polo_Base(QWidget *parent) :QLabel(parent)
{}
void Polo_Base::paintEvent(QPaintEvent *event)
{QLabel::paintEvent(event);QPainter painter(this);f_Draw(&painter);
}
void Polo_Base::f_Draw(QPainter *p)
{QColor colorHand = QColor(Qt::red);//Init the origin.int iX0 = width() / 2, iY0 = height() - width() / 4;p->setRenderHint(QPainter::Antialiasing);p->translate(iX0, iY0);//Draw the background picture.QPixmap pic(m_sPicPath);int iPicWidth = width(), iPicHeight = width() * pic.height() / pic.width();int iLeft = 0 - iPicWidth / 2, iTop = 0 - iPicHeight + width() / 4;p->drawPixmap(iLeft, iTop, width(), width() * pic.height() / pic.width(), pic);//Draw hands.int iHandSize = width() / 25, iHandLeft = iLeft - width() / 15, iHandLength = width() / 2 - width() / 20;p->save();p->setPen(QPen(QBrush(colorHand), iHandSize, Qt::SolidLine, Qt::RoundCap));if (m_realDegrees < m_realMin){m_realDegrees = m_realMin;}if (m_realDegrees > m_realMax){m_realDegrees = m_realMax;}p->rotate(m_realDegrees);p->drawLine(iHandLeft, 0, iHandLeft + iHandLength, 0);p->restore();//Draw the hand heart on the origin.int iHeartSize = width() / 4;p->setPen(QPen(QBrush(QColor(Qt::darkGray)), iHeartSize, Qt::SolidLine, Qt::RoundCap));p->drawPoint(0, 0);p->end();
}
void Polo_Base::f_SetValue(const qreal &realValue)
{m_realDegrees = realValue;update();
}

 polo_watertemp.h

/**************************************************************************************************** File name:      polo_watertemp.h (Polo_WaterTemp)** Created by:     Henrick.Nie at 2024-9-9** Used for:       The water temprature guage of polo.** Using method:****     Firstly, a image resource path is required.****         obj->f_Init(":/images/");****************************************************************************************************/#ifndef POLO_WATERTEMP_H
#define POLO_WATERTEMP_H#include "polo_base.h"class Polo_WaterTemp : public Polo_Base
{Q_OBJECT
public:explicit Polo_WaterTemp(QWidget *parent = nullptr);void f_Init(const QString &sRcPathPrefix) override;void f_SetValue(const qreal &realValue) override;
};#endif // POLO_WATERTEMP_H

polo_watertemp.cpp

#include "polo_watertemp.h"Polo_WaterTemp::Polo_WaterTemp(QWidget *parent) :Polo_Base(parent)
{}
void Polo_WaterTemp::f_Init(const QString &sRcPathPrefix)
{f_SetBack(sRcPathPrefix + "polo_watertemp.jpg");
}
void Polo_WaterTemp::f_SetValue(const qreal &realValue)
{//The given water temprature value, it equals the degrees.Polo_Base::f_SetValue(realValue);
}

polo_fuel.h

/**************************************************************************************************** File name:      polo_fuel.h (Polo_Fuel)** Created by:     Henrick.Nie at 2024-9-9** Used for:       The fuel guage of polo.** Using method:****     Firstly, a image resource path is required.****         obj->f_Init(":/images/");****************************************************************************************************/#ifndef POLO_FUEL_H
#define POLO_FUEL_H#include "polo_base.h"class Polo_Fuel : public Polo_Base
{Q_OBJECT
public:explicit Polo_Fuel(QWidget *parent = nullptr);void f_Init(const QString &sRcPathPrefix) override;void f_SetValue(const qreal &realValue) override;
};#endif // POLO_FUEL_H

polo_fuel.cpp

#include "polo_fuel.h"Polo_Fuel::Polo_Fuel(QWidget *parent) :Polo_Base(parent)
{}
void Polo_Fuel::f_Init(const QString &sRcPathPrefix)
{f_SetBack(sRcPathPrefix + "polo_fuel.jpg");
}
void Polo_Fuel::f_SetValue(const qreal &realValue)
{Polo_Base::f_SetValue(40 + realValue * 2.2);
}

燃料表这个要注意数值换算了。下面转速表也是。

tachometer.h

/**************************************************************************************************** File name:      tachometer.h (TachoMeter)** Created by:     Henrick.Nie at 2024-9-9** Using method:****     Firstly, a image resource path is required.****         obj->f_Init(":/images/");****************************************************************************************************/#ifndef TACHOMETER_H
#define TACHOMETER_H#include <QLabel>
#include <QPainter>
#include <QDebug>class TachoMeter : public QLabel
{Q_OBJECT
public:explicit TachoMeter(QWidget *parent = nullptr);inline void f_Init(const QString &sRcPathPrefix) { m_sRcPathPrefix = sRcPathPrefix; }void f_SetValue(const qreal &realValue);inline qreal f_GetDegrees() const { return m_realDegrees; }private:QString m_sRcPathPrefix;qreal m_realDegrees = -45, m_realMin = -45, m_realMax = 225;void paintEvent(QPaintEvent *event);void f_Draw(QPainter* p);
};#endif // TACHOMETER_H

tachometer.cpp

#include "tachometer.h"TachoMeter::TachoMeter(QWidget *parent) :QLabel(parent)
{}
void TachoMeter::paintEvent(QPaintEvent *event)
{QLabel::paintEvent(event);QPainter painter(this);f_Draw(&painter);
}
void TachoMeter::f_Draw(QPainter *p)
{//Init the size data.int iSideSize = qMin(width(), height());int iX0 = width() / 2, iY0 = height() / 2;//Init the origin.p->setRenderHint(QPainter::Antialiasing);p->translate(iX0, iY0);//Draw the background.p->setPen(Qt::NoPen);p->setBrush(QBrush(Qt::black));p->drawRect(0 - width() / 2, 0 - height() / 2, width(), height());QPixmap pic(m_sRcPathPrefix + "tacho1.jpg");int iLeft = 0 - iSideSize / 2, iTop = 0 - iSideSize / 2;p->drawPixmap(iLeft, iTop, iSideSize, iSideSize, pic);//Draw the hand.p->save();p->setPen(QPen(QBrush(Qt::red), iSideSize / 40, Qt::SolidLine, Qt::RoundCap));if (m_realDegrees < m_realMin){m_realDegrees = m_realMin;}if (m_realDegrees > m_realMax){m_realDegrees = m_realMax;}p->rotate(m_realDegrees);p->drawLine(0 - iSideSize / 2 + iSideSize / 20, 0, 0, 0);p->restore();//centerp->setPen(Qt::NoPen);p->setBrush(QBrush(QColor(Qt::darkGray)));p->drawEllipse(QPoint(0, 0), iSideSize / 20, iSideSize / 20);p->end();
}
void TachoMeter::f_SetValue(const qreal &realValue)
{//value: 0 to 8000//degree: -45 to 225 (225-(-45))=270, -41/225/qreal realScale = 266.0 / 8000.0; //per 1 rpmm_realDegrees = 0 - 45 + realValue * realScale;update();
}

效果:

06057548e3274a0897c4917e90f396a0.jpeg

效果解析:

上面效果图中,我在界面上放置了滑动条,实际操作时,可以改变滑块位置,直接看到仪表动作。

警告灯:

在上述基础上,还可以使用label的setmovie函数,播放一些动态的gif图片。以实现警告灯的效果。

 label_movie.h

/**************************************************************************************************** File name:      label_movie.h (Label_Movie)** Created by:     Henrick.Nie at 2024-9-10** Using method:****     Firstly, a image resource path is required.****         obj->f_Init(":/images/");****************************************************************************************************/#ifndef LABEL_MOVIE_H
#define LABEL_MOVIE_H#include <QLabel>
#include <QPainter>
#include <QMovie>
#include <QDebug>class Label_Movie : public QLabel
{Q_OBJECT
public:explicit Label_Movie(QWidget *parent = nullptr);inline void f_Init(const QString &sRcPathPrefix) { m_sRcPathPrefix = sRcPathPrefix; }void f_SetJpg(const QString &sFileName);void f_SetGif(const QString &sFileName);private:QString m_sRcPathPrefix;QMovie m_movie;
};#endif // LABEL_MOVIE_H

label_movie.cpp

#include "label_movie.h"Label_Movie::Label_Movie(QWidget *parent) :QLabel(parent)
{}
void Label_Movie::f_SetJpg(const QString &sFileName)
{this->setPixmap(QPixmap(m_sRcPathPrefix + sFileName));
}
void Label_Movie::f_SetGif(const QString &sFileName)
{m_movie.stop();m_movie.setFileName(m_sRcPathPrefix + sFileName);this->setMovie(&m_movie);m_movie.start();
}

之所以要包装一个label,因为qt手册提到ownership,也许qt这样处理有其它用意,但对于本次情况,每次单独处理不方便。

 [slot] void QLabel::setMovie(QMovie *movie)
Sets the label contents to movie. Any previous content is cleared. The label does NOT take ownership of the movie.
The buddy shortcut, if any, is disabled.

效果如下:

72c76309eae54449bba63d82be13a2fe.jpeg

当水温和油量到达警戒值时,自动亮起故障灯。

故障灯整合面板:

guage_warning.h

/**************************************************************************************************** File name:      guage_warning.h (Guage_Warning)** Created by:     Henrick.Nie at 2024-9-11** Used for:       The warning light of the engine.** Using method:****     Firstly, a image resource path is required.****         obj->f_Init(":/images/");****************************************************************************************************/#ifndef GUAGE_WARNING_H
#define GUAGE_WARNING_H#include <QWidget>namespace Ui {
class Guage_Warning;
}class Guage_Warning : public QWidget
{Q_OBJECTpublic:explicit Guage_Warning(QWidget *parent = nullptr);~Guage_Warning();enum EWarningType { eNone, eWater, eOil, eFuel, eEngine, eBattery, eBrake };void f_Init(const QString &sRcPathPrefix);void f_SetStatus(const EWarningType &eType, const bool &bIsWarning);private:Ui::Guage_Warning *ui;QString m_sRcPathPrefix;EWarningType m_eType = eNone;};#endif // GUAGE_WARNING_H

guage_warning.cpp

#include "guage_warning.h"
#include "ui_guage_warning.h"Guage_Warning::Guage_Warning(QWidget *parent) :QWidget(parent),ui(new Ui::Guage_Warning)
{ui->setupUi(this);this->setStyleSheet("background: black;");ui->gridLayout->setSpacing(0);
}Guage_Warning::~Guage_Warning()
{delete ui;
}void Guage_Warning::f_Init(const QString &sRcPathPrefix)
{m_sRcPathPrefix = sRcPathPrefix;ui->labWater  ->setPixmap(QPixmap(m_sRcPathPrefix + "warning_water.jpg"));ui->labOil    ->setPixmap(QPixmap(m_sRcPathPrefix + "warning_oil.jpg"));ui->labFuel   ->setPixmap(QPixmap(m_sRcPathPrefix + "warning_fuel.jpg"));ui->labEngine ->setPixmap(QPixmap(m_sRcPathPrefix + "warning_engine.jpg"));ui->labBattery->setPixmap(QPixmap(m_sRcPathPrefix + "warning_battery.jpg"));ui->labBrake  ->setPixmap(QPixmap(m_sRcPathPrefix + "warning_brake.jpg"));
}
void Guage_Warning::f_SetStatus(const EWarningType &eType, const bool &bIsWarning)
{Label_Movie *lab;QString sJpg, sGif;switch (eType) {case eWater:lab = ui->labWater;sJpg = "warning_water.jpg";sGif = "warning_water.gif";break;case eOil:lab = ui->labOil;sJpg = "warning_oil.jpg";sGif = "warning_oil.gif";break;case eFuel:lab = ui->labFuel;sJpg = "warning_fuel.jpg";sGif = "warning_fuel.gif";break;case eEngine:lab = ui->labEngine;sJpg = "warning_engine.jpg";sGif = "warning_engine.gif";break;case eBattery:lab = ui->labBattery;sJpg = "warning_battery.jpg";sGif = "warning_battery.gif";break;case eBrake:lab = ui->labBrake;sJpg = "warning_brake.jpg";sGif = "warning_brake.gif";break;default:lab = nullptr;break;}if (nullptr == lab){return;}lab->f_Init(m_sRcPathPrefix);void (Label_Movie::*f_ptr)(const QString &sFileName) = bIsWarning ? &Label_Movie::f_SetGif : &Label_Movie::f_SetJpg;QString sPic = bIsWarning ? sGif : sJpg;(lab->*f_ptr)(sPic);
}

guage_warning.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>Guage_Warning</class><widget class="QWidget" name="Guage_Warning"><property name="geometry"><rect><x>0</x><y>0</y><width>316</width><height>134</height></rect></property><property name="minimumSize"><size><width>129</width><height>66</height></size></property><property name="windowTitle"><string>Form</string></property><layout class="QGridLayout" name="gridLayout"><item row="0" column="0"><widget class="Label_Movie" name="labWater"><property name="text"><string>TextLabel</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item><item row="0" column="1"><widget class="Label_Movie" name="labOil"><property name="text"><string>TextLabel</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item><item row="0" column="2"><widget class="Label_Movie" name="labFuel"><property name="text"><string>TextLabel</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item><item row="1" column="0"><widget class="Label_Movie" name="labEngine"><property name="text"><string>TextLabel</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item><item row="1" column="1"><widget class="Label_Movie" name="labBattery"><property name="text"><string>TextLabel</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item><item row="1" column="2"><widget class="Label_Movie" name="labBrake"><property name="text"><string>TextLabel</string></property><property name="alignment"><set>Qt::AlignCenter</set></property></widget></item></layout></widget><customwidgets><customwidget><class>Label_Movie</class><extends>QLabel</extends><header>label_movie.h</header></customwidget></customwidgets><resources/><connections/>
</ui>

使用的时候更简洁:

void MainWindow::on_sbWaterTemp_valueChanged(int value)
{ui->lab_WaterTemp->f_SetTemp(value);ui->lab_WaterTempPolo->f_SetValue(value);ui->wWarning->f_SetStatus(Guage_Warning::eWater, (value > 120));
}void MainWindow::on_sbWaterTemp_2_valueChanged(int value)
{on_sbWaterTemp_valueChanged(value);
}void MainWindow::on_sbFuel_valueChanged(int value)
{ui->lab_FuelPolo->f_SetValue(value);ui->wWarning->f_SetStatus(Guage_Warning::eFuel, (value < 10));
}void MainWindow::on_sbTacho_valueChanged(int value)
{ui->lab_Tacho->f_SetValue(value);
}

整合故障灯后效果如下:

本文完。

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

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

相关文章

springboot Web基础开发

Spring Boot 是一个用于简化 Spring 应用开发的框架&#xff0c;它通过自动配置和开箱即用的功能&#xff0c;使得创建和部署 Spring 应用变得更为高效。以下是 Spring Boot 基础 Web 开发的一些关键点和实操总结&#xff1a; 1. 项目搭建 使用 Spring Initializr: 访问 Spring…

【Centos】关于容器启动Centos7缺失字符集的问题

最近做一些软件测试和打包&#xff0c;需要频繁的装系统&#xff0c;索性用docker启Centos容器来做&#xff0c;基础镜像做好直接启就好&#xff0c;过程中遇到一个和字符集有关的问题&#xff0c;记录一下&#xff0c;方便遇到同样问题的小伙伴。 问题描述 运行某些python脚本…

Stable Diffusion绘画 | ControlNet应用-Inpaint(局部重绘):更完美的重绘

Inpaint(局部重绘) 相当于小号的AI版PS&#xff0c;不但可以进行局部画面的修改&#xff0c;还可以去除背景中多余的内容&#xff0c;或者是四周画面内容的扩充。 预处理器说明 Inpaint_Global_Harmonious&#xff1a;重绘-全局融合算法&#xff0c;会对整个图片的画面和色调…

达梦CASE_SENSITIVE参数解析

1. 参数含义 标识符大小写敏感&#xff0c;默认值为 Y。 当大小写敏感时&#xff0c;小写的标识符应用双引号括起&#xff0c;否则被转换为大写&#xff1b;当大小写不敏感时&#xff0c;系统不自动转换标识符的大小写&#xff0c;在标识符比较时也不区分大小写。 CASE_SENS…

QtCreator学习(二).在stm32mp1中使用

0.配置编译环境 复制【正点原子】STM32MP157开发板&#xff08;A盘&#xff09;-基础资料\05、开发工具\01、交叉编译器st-example-image-qtwayland-openstlinux-weston-stm32mp1-x86_64-toolchain-3.1-snapshot.sh到虚拟机chmod添加可执行文件&#xff0c;./st*运行&#xff…

【JAVA】Tomcat性能优化、安全配置、资源控制以及运行模式超详细

文章目录 一、Tomcat性能优化application.yml配置maxThreads 连接数限制压缩传输AJP禁用 二、JVM方向优化设置并行垃圾回收器查看gc日志文件 三、Tomcat安全配置入侵防范禁用非法HTTP请求方法禁止目录列出防止恶意关闭服务配置HTTPS加密协议HttpOnly标记安全头配置 四、Tomcat资…

【鸿蒙】HarmonyOS NEXT星河入门到实战8-自定义组件-组件通信

目录 1、模块化语法 1.1 模块化基本认知 1.2 默认导出和导入 1.3 按需导出和导入 1.4 全部导入 2、自定义组件 -基础 2.1 自定义组件 - 基本使用 2.2 自定义组件 -通用样式 2.3 自定义组件 -成员函数变量 3、 状态管理 3.1 状态管理概述 3.2 State 自己的状态 3.3…

硬盘格式化后能恢复数据吗?教你如何恢复硬盘数据

在数字时代&#xff0c;硬盘作为存储数据的重要设备&#xff0c;承载着人们大量的工作文件、珍贵照片、重要视频等。然而&#xff0c;由于误操作、病毒感染或系统升级等原因&#xff0c;有时我们不得不对硬盘进行格式化。那么&#xff0c;硬盘格式化后&#xff0c;里面的数据还…

spring综合性利用工具-SpringBootVul-GUI(五)

项目地址 https://github.com/wh1t3zer/SpringBootVul-GUI 0x01简介 本着简单到极致的原则&#xff0c;开发了这么一款半自动化工具&#xff08;PS&#xff1a;这个工具所包含了20个漏洞&#xff0c;开发不易&#xff0c;有任何问题可提issue&#xff09; 尽管是一个为懒人量…

【免费刷题】实验室安全第一知识题库分享

道路千万条&#xff0c;实验安全第一条。 嘿&#xff0c;实验室的小伙伴们&#xff01;是不是还在为实验室安全考试而烦恼&#xff1f;别担心&#xff0c;今天就让我来分享一些实用的题库&#xff0c;帮助你轻松应对考试&#xff0c;同时也更好地保护自己和实验室的安全。 一、…

petalinux开发 添加iperf

如何把iperf编译到petalinux工程中去 目录&#xff1a; /home/xxx/7z020/project-spec/meta-user/conf 里面有一个user-rootfsconfig文件 它默认里面有 CONFIG_gpio-demo CONFIG_peekpoke 把iperf添加进去 #Note: Mention Each package in individual line #These packages w…

网络安全实训八(y0usef靶机渗透实例)

1 信息收集 1.1 扫描靶机IP 1.2 收集靶机的端口开放情况 1.3 探测靶机网站的目录 1.4 发现可疑网站 1.5 打开可疑网站 2 渗透 2.1 使用BP获取请求 2.2 使用工具403bypasser.py探测可疑网页 2.3 显示可以添加头信息X-Forwarded-For:localhost来访问 2.4 添加之后转发&#xff…

如何在Django中创建新的模型实例

在 Django 中&#xff0c;创建新的模型实例可以通过以下几个步骤进行&#xff0c;通常包括定义模型、创建模型实例、保存数据到数据库&#xff0c;以及访问和操作这些实例。 1、问题背景 在 Django 中&#xff0c;可以使用 models.Model 类来创建模型&#xff0c;并使用 creat…

sqlguna靶场get shell

一、打开靶场&#xff0c;发现一个搜索框&#xff0c;尝试sql注入&#xff0c;发现可以注入&#xff0c;爆破数据库&#xff0c;表名&#xff0c;字段名以及 用户名密码 二、发现密码被MD5&#xff0c;解密后得到密码 三、进入后台界面登陆查看 四、发现添加新闻出可以上传图片…

前端开发macbook——NVM环境配置以及git配置流程

本文主要针对前端使用mac电脑时需要安装nvm对应环境&#xff0c;一文解决环境安装问题 主要步骤如下&#xff1a; 安装homebrew 安装nvm 安装git 第一步&#xff1a;安装homebrew /bin/bash -c "$(curl -fsSL https:/raw.githubusercontent.com/Homebrew/install/HE…

Redis 篇-深入了解分布式锁 Redisson 原理(可重入原理、可重试原理、主从一致性原理、解决超时锁失效)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 本章目录 1.0 基于 Redis 实现的分布式锁存在的问题 2.0 Redisson 功能概述 3.0 Redisson 具体使用 4.0 Redisson 可重入锁原理 5.0 Redisson 锁重试原理 6.0 Redisson WatchDo…

第7篇:【系统分析师】计算机网络

考点汇总 考点详情 1网络模型和协议&#xff1a;OSI/RM七层模型&#xff0c;网络标准和协议&#xff0c;TCP/IP协议族&#xff0c;端口 七层&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff0c;网络层&#xff0c;数据链路层&#xff0c;…

如何为Google RSA安排广告定制器 [2024]

近年来&#xff0c;响应式搜索广告&#xff08;RSA&#xff09;的人气稳步上升&#xff0c;这也就不足为奇了。通过谷歌的机器学习能力&#xff0c;RSA 提供了一种强大的方式来自动测试多个标题和描述&#xff0c;以确保更接近用户的意图。其好处显而易见&#xff1a;RSA 意味着…

Docker容器技术1——docker基本操作

Docker容器技术 随着云计算和微服务架构的普及&#xff0c;容器技术成为了软件开发、测试和部署过程中的重要组成部分。其中&#xff0c;Docker作为容器技术的代表之一&#xff0c;以其简便易用的特点赢得了广大开发者的青睐。 Docker允许开发者在轻量级、可移植的容器中打包和…