Qt Example Callout Extention(about QChart/QGraphicsView/QGraphicsItem)

news2024/9/23 17:25:14

问题

Qt Example callout 展示了在平面直角坐标系中画tips。知识点涉及到QChart/QGraphicsView/QGraphicsItem。如何在平面直角坐标系中画点、折线、圆、长方形?

Example路径

D:\Qt\5.15.2\Src\qtcharts\examples\charts\callout\callout.cpp

代码

main

#include <QtWidgets/QApplication>
#include "view.h"

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

View 

#ifndef VIEW_H
#define VIEW_H
#include <QtWidgets/QGraphicsView>
#include <QtCharts/QChartGlobal>

QT_BEGIN_NAMESPACE
class QGraphicsScene;
class QMouseEvent;
class QResizeEvent;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE

class Callout;

QT_CHARTS_USE_NAMESPACE
class CircleItem;
class RectItem;
class View: public QGraphicsView
{
    Q_OBJECT

public:
    View(QWidget *parent = 0);
    void DelCallout(Callout* pCallout);
protected:
    void resizeEvent(QResizeEvent *event);
    void mouseMoveEvent(QMouseEvent *event);

public slots:
    void keepCallout();
    void tooltip(QPointF point, bool state);

private:
    QGraphicsSimpleTextItem *m_coordX;
    QGraphicsSimpleTextItem *m_coordY;
    QChart *m_chart;
    Callout *m_tooltip;
    QList<Callout*> m_lCallout;
    QList<CircleItem*>m_lCircle;
    QList<RectItem*>m_lRect;
};

#endif
#include "view.h"
#include <QtGui/QResizeEvent>
#include <QtWidgets/QGraphicsScene>
#include <QtCharts/QChart>
#include <QtCharts/QLineSeries>
#include <QtCharts/QSplineSeries>
#include <QtWidgets/QGraphicsTextItem>
#include "callout.h"
#include <QtGui/QMouseEvent>
#include <QValueAxis>
#include <QScatterSeries>
#include <QAreaSeries>
#include <QSplineSeries>
#include "CircleItem.h"
#include "RectItem.h"
View::View(QWidget *parent)
    : QGraphicsView(new QGraphicsScene, parent),
      m_coordX(0),
      m_coordY(0),
      m_chart(0),
      m_tooltip(0)
{
    setDragMode(QGraphicsView::NoDrag);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    // chart
    m_chart = new QChart;
    m_chart->setMinimumSize(640, 480);
    m_chart->setTitle(QStringLiteral("平面直角坐标系"));
    m_chart->legend()->hide();
    //点的数据源
    QList<QPointF> lptSource;
    lptSource << QPointF(0, 6.3) << QPointF(2, 6) << QPointF(3, 6) << QPointF(6, 6) << QPointF(7, 7) << QPointF(8, 8)
        << QPointF(4, 3) << QPointF(4, 7) << QPointF(5, 2);
    //点用折线连起来
    QLineSeries* line = new QLineSeries();
    line->append(lptSource);
    //点用曲线连起来
    QSplineSeries* spline = new QSplineSeries();
    spline->append(lptSource);
    //点用圆圈表示
    QScatterSeries* scatter = new QScatterSeries();
    scatter->append(lptSource);
    //区域
    QLineSeries* line1 = new QLineSeries();
    QLineSeries* line2 = new QLineSeries();
    line1->append(1, 1);
    line1->append(1, 2);
    line2->append(2, 1);
    line2->append(2, 2);
    QAreaSeries* area = new QAreaSeries(line1, line2);
    area->setName("Batman");
    QPen pen(0x059605);
    pen.setWidth(3);
    area->setPen(pen);
    QLinearGradient gradient(QPointF(0, 0), QPointF(0, 1));
    gradient.setColorAt(0.0, 0x3cc63c);
    gradient.setColorAt(1.0, 0x26f626);
    gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
    area->setBrush(gradient);

    m_chart->addSeries(scatter);
    m_chart->addSeries(line);
    //m_chart->addSeries(spline);
    m_chart->addSeries(area);

    m_chart->createDefaultAxes();
    m_chart->setAcceptHoverEvents(true);

    setRenderHint(QPainter::Antialiasing);
    scene()->addItem(m_chart);

    m_coordX = new QGraphicsSimpleTextItem(m_chart);
    m_coordX->setPos(m_chart->size().width()/2 - 50, m_chart->size().height());
    m_coordX->setText("X: ");
    m_coordY = new QGraphicsSimpleTextItem(m_chart);
    m_coordY->setPos(m_chart->size().width()/2 + 50, m_chart->size().height());
    m_coordY->setText("Y: ");

    connect(line, &QLineSeries::clicked, this, &View::keepCallout);
    connect(line, &QLineSeries::hovered, this, &View::tooltip);
    connect(spline, &QSplineSeries::clicked, this, &View::keepCallout);
    connect(spline, &QSplineSeries::hovered, this, &View::tooltip);
    connect(area, &QAreaSeries::clicked, this, &View::keepCallout);
    connect(area, &QAreaSeries::hovered, this, &View::tooltip);

    this->setMouseTracking(true);
    CircleItem* pCircle = new CircleItem(m_chart, this);
    pCircle->SetCenterR(QPointF(4,4.5),1);
    m_lCircle.push_back(pCircle);


    RectItem* pRect = new RectItem(m_chart, this);
    pRect->SetRect(QRectF(QPointF(5.6,2.2),QSizeF(2,3)));
    m_lRect.push_back(pRect);
}

void View::DelCallout(Callout* pCallout)
{
    m_lCallout.removeOne(pCallout);
    delete pCallout;
}

void View::resizeEvent(QResizeEvent *event)
{
    if (scene()) {
        scene()->setSceneRect(QRect(QPoint(0, 0), event->size()));
         m_chart->resize(event->size());
         m_coordX->setPos(m_chart->size().width()/2 - 50, m_chart->size().height() - 20);
         m_coordY->setPos(m_chart->size().width()/2 + 50, m_chart->size().height() - 20);
         const auto callouts = m_lCallout;
         for (Callout *callout : callouts)
             callout->updateGeometry();
         for (CircleItem* pCircle : m_lCircle)
             pCircle->updateGeometry();
         for (RectItem* pRect : m_lRect)
             pRect->updateGeometry();
    }
    QGraphicsView::resizeEvent(event);
}

void View::mouseMoveEvent(QMouseEvent *event)
{
    m_coordX->setText(QString("X: %1").arg(m_chart->mapToValue(event->pos()).x()));
    m_coordY->setText(QString("Y: %1").arg(m_chart->mapToValue(event->pos()).y()));
    QGraphicsView::mouseMoveEvent(event);
}

void View::keepCallout()
{
    m_lCallout.append(m_tooltip);
    m_tooltip = new Callout(m_chart, this);
}

void View::tooltip(QPointF point, bool state)
{
    if (m_tooltip == 0)
        m_tooltip = new Callout(m_chart, this);

    if (state) {
        m_tooltip->setText(QString("X: %1 \nY: %2 ").arg(point.x()).arg(point.y()));
        m_tooltip->setAnchor(point);
        m_tooltip->setZValue(11);
        m_tooltip->updateGeometry();
        m_tooltip->show();
    } else {
        m_tooltip->hide();
    }
}

callout 

#ifndef CALLOUT_H
#define CALLOUT_H

#include <QtCharts/QChartGlobal>
#include <QtWidgets/QGraphicsItem>
#include <QtGui/QFont>


QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE
class View;
class Callout : public QGraphicsItem
{
public:
    Callout(QChart *parent, View* pView);

    void setText(const QString &text);
    void setAnchor(QPointF point);
    void updateGeometry();

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event);
private:
    QString m_text;
    QRectF m_textRect;
    QRectF m_rect;
    QPointF m_anchor;
    QFont m_font;
    QChart *m_chart;
    View* m_view;
};

#endif // CALLOUT_H
#include "callout.h"
#include <QtGui/QPainter>
#include <QtGui/QFontMetrics>
#include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtGui/QMouseEvent>
#include <QtCharts/QChart>
#include <QDebug>
#include <view.h>
Callout::Callout(QChart *chart, View* pView):
    QGraphicsItem(chart),
    m_chart(chart),m_view(pView)
{
}

QRectF Callout::boundingRect() const
{
    QPointF anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
    QRectF rect;
    rect.setLeft(qMin(m_rect.left(), anchor.x()));
    rect.setRight(qMax(m_rect.right(), anchor.x()));
    rect.setTop(qMin(m_rect.top(), anchor.y()));
    rect.setBottom(qMax(m_rect.bottom(), anchor.y()));



    return rect;
}

void Callout::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option)
    Q_UNUSED(widget)
    QPainterPath path;
    path.addRoundedRect(m_rect, 5, 5);
    QPointF anchor = mapFromParent(m_chart->mapToPosition(m_anchor));
    if (!m_rect.isNull() && !m_rect.contains(anchor)) {
        QPointF point1, point2;

        // establish the position of the anchor point in relation to m_rect
        bool above = anchor.y() <= m_rect.top();
        bool aboveCenter = anchor.y() > m_rect.top() && anchor.y() <= m_rect.center().y();
        bool belowCenter = anchor.y() > m_rect.center().y() && anchor.y() <= m_rect.bottom();
        bool below = anchor.y() > m_rect.bottom();

        bool onLeft = anchor.x() <= m_rect.left();
        bool leftOfCenter = anchor.x() > m_rect.left() && anchor.x() <= m_rect.center().x();
        bool rightOfCenter = anchor.x() > m_rect.center().x() && anchor.x() <= m_rect.right();
        bool onRight = anchor.x() > m_rect.right();

        // get the nearest m_rect corner.
        qreal x = (onRight + rightOfCenter) * m_rect.width();
        qreal y = (below + belowCenter) * m_rect.height();
        bool cornerCase = (above && onLeft) || (above && onRight) || (below && onLeft) || (below && onRight);
        bool vertical = qAbs(anchor.x() - x) > qAbs(anchor.y() - y);

        qreal x1 = x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * !vertical * (onLeft * 10 - onRight * 20);
        qreal y1 = y + aboveCenter * 10 - belowCenter * 20 + cornerCase * vertical * (above * 10 - below * 20);;
        point1.setX(x1);
        point1.setY(y1);

        qreal x2 = x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * !vertical * (onLeft * 20 - onRight * 10);;
        qreal y2 = y + aboveCenter * 20 - belowCenter * 10 + cornerCase * vertical * (above * 20 - below * 10);;
        point2.setX(x2);
        point2.setY(y2);

        path.moveTo(point1);
        path.lineTo(anchor);
        path.lineTo(point2);
        path = path.simplified();
        qDebug() << point1 << "," << anchor << "," << point2 << "," << path<<"\n\n\n\n";
    }
    painter->setBrush(QColor(255, 255, 255,128));
    painter->drawPath(path);
    painter->drawText(m_textRect, m_text);
}

void Callout::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QPointF pt = event->pos();
    QRectF rc = mapToParent(m_rect).boundingRect();
    if (m_rect.contains(pt))
    {
        event->setAccepted(true);
    }
    else
        event->setAccepted(false);
}

void Callout::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton){
        setPos(mapToParent(event->pos() - event->buttonDownPos(Qt::LeftButton)));
        event->setAccepted(true);
    } else {
        event->setAccepted(false);
    }
}

void Callout::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
{
    m_view->DelCallout(this);
}

void Callout::setText(const QString &text)
{
    m_text = text;
    QFontMetrics metrics(m_font);
    m_textRect = metrics.boundingRect(QRect(0, 0, 150, 150), Qt::AlignLeft, m_text);
    m_textRect.translate(5, 5);
    prepareGeometryChange();
    m_rect = m_textRect.adjusted(-5, -5, 5, 5);
}

void Callout::setAnchor(QPointF point)
{
    m_anchor = point;
}

void Callout::updateGeometry()
{
    prepareGeometryChange();
    setPos(m_chart->mapToPosition(m_anchor) + QPoint(10, -50));
}

CircleItem

#pragma once
#include <QtCharts/QChartGlobal>
#include <QtWidgets/QGraphicsItem>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE
class View;
class CircleItem :
    public QGraphicsItem
{
public:
    CircleItem(QChart* parent, View* pView);
    void SetCenterR(QPointF pt,double r);//pt为在坐标系上点的坐标,r为在坐标系上的半径长度
    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
    void updateGeometry();
    QRectF boundingRect() const;
private:
    QPointF m_pt,m_ptDraw;
    double m_r,m_rDrawW,m_rDrawH;
    QChart* m_chart;
    View* m_view;
};

#include "CircleItem.h"
#include "View.h"
#include <QChart>
CircleItem::CircleItem(QChart* parent, View* pView):QGraphicsItem(parent),
    m_chart(parent),m_view(pView)
{

}

void CircleItem::SetCenterR(QPointF pt, double r)
{
    m_pt = pt;
    m_r = r;
    m_ptDraw = mapFromParent(m_chart->mapToPosition(m_pt));
    QPointF ptTemp0 = mapFromParent(m_chart->mapToPosition(QPointF(0, 0)));
    QPointF ptTempW = mapFromParent(m_chart->mapToPosition(QPointF(m_r, 0)));
    QPointF ptTempH = mapFromParent(m_chart->mapToPosition(QPointF(0, m_r)));
    m_rDrawW = abs(ptTempW.x() - ptTemp0.x());
    m_rDrawH = abs(ptTempH.y() - ptTemp0.y());
}

void CircleItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    QPainterPath path;
    QPointF pt = mapFromParent(m_chart->mapToPosition(m_pt));
    path.addEllipse(pt,m_rDrawW,m_rDrawH);
    painter->setBrush(QColor(255, 255, 0, 128));
    painter->drawPath(path);
}

void CircleItem::updateGeometry()
{
    prepareGeometryChange();
    m_ptDraw = mapFromParent(m_chart->mapToPosition(m_pt));
    QPointF ptTemp0 = mapFromParent(m_chart->mapToPosition(QPointF(0, 0)));
    QPointF ptTempW = mapFromParent(m_chart->mapToPosition(QPointF(m_r, 0)));
    QPointF ptTempH = mapFromParent(m_chart->mapToPosition(QPointF(0, m_r)));
    m_rDrawW = abs(ptTempW.x() - ptTemp0.x());
    m_rDrawH = abs(ptTempH.y() - ptTemp0.y());
    setPos(m_ptDraw+QPointF(-m_rDrawW, -m_rDrawH));
}

QRectF CircleItem::boundingRect() const
{
    QPointF pt = mapFromParent(m_chart->mapToPosition(m_pt));
    QRectF rect;
    rect.setLeft(pt.x() - m_rDrawW);
    rect.setRight(pt.x() + m_rDrawW);
    rect.setTop(pt.y() - m_rDrawH);
    rect.setBottom(pt.y() + m_rDrawH);
    return rect;
}

RectItem 

#pragma once
#include <QtCharts/QChartGlobal>
#include <QtWidgets/QGraphicsItem>
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE

QT_CHARTS_BEGIN_NAMESPACE
class QChart;
QT_CHARTS_END_NAMESPACE

QT_CHARTS_USE_NAMESPACE
class View;
class RectItem : public QGraphicsItem
{
public:
    RectItem(QChart* parent, View* pView);
    void SetRect(QRectF rc);
    void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
    void updateGeometry();
    QRectF boundingRect() const;
private:
    QRectF m_rc,m_rcDraw;
    QChart* m_chart;
    View* m_view;
};

#include "RectItem.h"
#include "View.h"
#include <QChart>
RectItem::RectItem(QChart* parent, View* pView) :QGraphicsItem(parent),
m_chart(parent), m_view(pView)
{

}

void RectItem::SetRect(QRectF rc)
{
    m_rc = rc;
    m_rcDraw.setTopLeft(mapFromParent(m_chart->mapToPosition(m_rc.topLeft())));
    m_rcDraw.setBottomRight(mapFromParent(m_chart->mapToPosition(m_rc.bottomRight())));
}

void RectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    QPainterPath path;
    m_rcDraw.setTopLeft(mapFromParent(m_chart->mapToPosition(m_rc.topLeft())));
    m_rcDraw.setBottomRight(mapFromParent(m_chart->mapToPosition(m_rc.bottomRight())));
    path.addRect(m_rcDraw);
    painter->setBrush(QColor(255, 128, 0, 128));
    painter->drawPath(path);
}

void RectItem::updateGeometry()
{
    prepareGeometryChange();
    m_rcDraw.setTopLeft(mapFromParent(m_chart->mapToPosition(m_rc.topLeft())));
    m_rcDraw.setBottomRight(mapFromParent(m_chart->mapToPosition(m_rc.bottomRight())));
    setPos(m_rcDraw.topLeft());
}

QRectF RectItem::boundingRect() const
{
    QPointF ptTopLeft = mapFromParent(m_chart->mapToPosition(m_rc.topLeft()));
    QPointF ptBottomRight = mapFromParent(m_chart->mapToPosition(m_rc.bottomRight()));
    return QRectF(ptTopLeft,ptBottomRight);
}

运行效果

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

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

相关文章

C++ 有向图拓扑排序算法

代码 #include <algorithm> #include <cassert> #include <functional> #include <map> #include <memory> #include <queue> #include <set> #include <unordered_set> #include <vector>namespace jc {template <…

【JAVA基础】位运算

文章目录 位运算按位与操作按位或操作按位取反按位亦或 移位运算有符号左移有符号右移 位运算 处理数据的时候可以直接对组成整形数值的各个位完成操作 &|~^andornotxor 下面我们以byte类型为例子&#xff1a; 按位与操作 两个操作数&#xff0c;如果同为1则为1&#…

【JavaEE初阶】IP协议

目录 &#x1f4d5;引言 &#x1f334;IP协议的概念 &#x1f333;IP数据报 &#x1f6a9;IPv4协议头格式 &#x1f6a9;IPv6的诞生 &#x1f3c0;拓展 &#x1f384;IP地址 &#x1f6a9;IP地址的格式&#xff1a; &#x1f6a9;IP地址的分类 &#x1f3c0;网段划分…

【计算机三级-数据库技术】操作题大题(第七套)

第七套操作题 第46题 假定要建立一个关于篮球职业联盟的数据库&#xff0c;需管理如下信息&#xff1a; 每个球队有球队名称、所在城市&#xff1b; 每位球员有球员姓名、薪酬; 每场比赛有比赛编号、比赛时间、比赛结果、参加比赛的主场球队、参加比赛的客场球队。 其中带下划…

Redis—基础篇

Redis基础 1. Redis 简介2. Redis 应用3. Redis 数据结构3.1 String3.2 hash3.3 list3.4 set3.5 sorted set 4. Redis 为什么快&#xff1f;5. Redis I/O 多路复用6. Redis 6.0多线程 1. Redis 简介 Redis 是一种基于键值对的 NoSQL 数据库 Redis 中的 value 支持 string、ha…

关于jupyter notebook 的输出 (outputs )

jupyter notebook 的输出 (outputs )在元素达到一定的个数后&#xff0c;就会按一行一个元素进行展示&#xff0c;百来个还好&#xff0c;一旦过千&#xff0c;那滚轮势必撸冒烟&#xff0c;所以能不能解决呢&#xff1f; 先看个例子&#xff0c; 一个找质数、合数的函数 cal3&…

【Linux篇】vim编译器

1. 介绍 vi / vim是visual interface的简称&#xff0c;是Linux中最典型的文本编辑器。 同图形化界面中的文本编辑器一样&#xff0c;vi是命令行下对文本文件进行编辑的绝佳选择。 vim是vi的加强版本&#xff0c;兼容vi的所有指令&#xff0c;不仅能编译文本&#xff0c;而且…

排序补充之快排的三路划分法

排序补充之快排的三路划分法 快排性能的关键点分析&#xff1a; 决定快排性能的关键点是每次单趟排序后&#xff0c;key对数组的分割&#xff0c;如果每次选key基本⼆分居中&#xff0c;那么快 排的递归树就是颗均匀的满⼆叉树&#xff0c;性能最佳。但是实践中虽然不可能每次…

数学建模笔记(四):熵权

背景&基本思想介绍 在实际的评价类问题中&#xff0c;在前面所说的层次分析法以及Topsis法中&#xff0c;指标权重的确定往往是通过主观的评价得来的&#xff0c;如果在没有专家的情况下&#xff0c;我们自己的权重分配往往可能带有一定的主观性&#xff0c;有没有一种可以…

linux系统离线安装docker并配置阿里云镜像源

制作docker.service文件 创建docker.service文件 cd /etc/systemd/system/ touch docker.service编辑docker.service文件 vim docker.service// 注意&#xff0c;将其中的ip地址&#xff0c;改成您的服务器地址&#xff0c;其它参数不用改。 //--insecure-registry192.168.8…

代码随想录算法day22 | 回溯算法part04 | 491.递增子序列,46.全排列,47.全排列 II

491.递增子序列 本题和大家做过的 90.子集II 非常像&#xff0c;但又很不一样&#xff0c;很容易掉坑里。 力扣题目链接(opens new window) 给定一个整型数组, 你的任务是找到所有该数组的递增子序列&#xff0c;递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4,…

【学习笔记】时间序列模型(ARIMA)

文章目录 前言一、时间序列时间序列数据 二、ARIMA 模型大纲模型前提平稳性检验 差分整合移动平均自回归模型 ARIMA(p,q,d)自回归模型 (AR( p ))移动平均模型 (MA( q ))自回归移动平均模型(ARMA(p,q))差分自回归移动平均模型 ARIMA(p,d,q) 确定 p&#xff0c;q结果分析和模型检…

SpringBoot集成kafka-消费者批量消费消息

SpringBoot集成kafka-消费者批量消费消息 1、消费者2、生产者3、application.yml配置文件4、实体类5、生产者发送消息测试类6、测试6.1、测试启动生产者6.2、测试启动消费者 1、消费者 设置批量接收消息 package com.power.consumer;import org.apache.kafka.clients.consume…

IC-Light容器构建详细指南

一、介绍 IC-Light 是一个操纵图像照明的项目&#xff0c;能够让一张普普通通的照片焕发光彩。 IC-Light&#xff0c;全称为“Imposing Consistent Light”&#xff0c;是一款由 AI 图像处理专家张吕敏&#xff08;ControlNet 的作者&#xff09;精心开发的创新工具。主要用于…

启用 UFW 防火墙后如何打开 80 和 443 端口?

UFW&#xff08;Uncomplicated Firewall&#xff09;是一款 Linux 系统上用户友好的管理防火墙规则的工具。它简化了控制网络流量的过程&#xff0c;使用户更容易开放或阻止端口。 本文将引导您使用 UFW 打开端口 80 (HTTP) 和 443 (HTTPS) 端口。您将了解如何启用这些端口&am…

uni-app项目搭建和模块介绍

工具:HuilderX noed版本:node-v17.3.1 npm版本:8.3.0 淘宝镜像:https://registry.npmmirror.com/ 未安装nodejs可以进入这里https://blog.csdn.net/a1241436267/article/details/141326585?spm1001.2014.3001.5501 目录 1.项目搭建​编辑 2.项目结构 3.使用浏览器运行…

华为Cloud连接配置

Cloud(云)连接意思为本地电脑和eNSP中的虚拟的VRP系统连接的 配置Cloud 先添加UDP 再添加需要使用的网卡 网卡建议使用虚拟机的网卡&#xff0c;如果没有虚拟机也可以使用其他网卡&#xff0c;自己设定一下IP就行 端口映射设置 配置R1 [R1]int e0/0/0 [R1-Ethernet0/0/0]ip …

B. 不知道该叫啥

题意&#xff1a;求长度为n的数列方案数&#xff0c;数列需满足两个条件&#xff1a;1.均为正整数。2.相邻两个数乘积不能超过m 思路&#xff1a;考虑dp。 设表示前i个点以j结尾的方案数&#xff0c;则有&#xff1a; 可以得出&#xff1a; 双指针数论分块解决。把每个m/i相…

一个下载镜像非常快的网站--华为云

1、镜像的下载飞速 链接&#xff1a;mirrors.huaweicloud.com/ubuntu-releases/24.04/ 下载一个的ubuntu24.04的镜像文件&#xff0c;5.7G的大文件&#xff0c;不到1分钟就下完毕了&#xff0c; 比起阿里云下载的速度600K/S,这个速度是100多倍。 非常的神速&#xff0c;非常…

如何选择高品质科研实验室用太阳光模拟器

概述 太阳光模拟器是一种能够模拟太阳光照射条件的设备&#xff0c;主要用于实验室环境中对太阳能相关材料和设备进行性能测试。这类模拟器能够提供与自然太阳光谱相似的光照&#xff0c;同时还能精确控制光照强度和照射角度&#xff0c;以满足不同测试需求。 对于被归类为太…