【嵌入式——QT】QT Charts

【嵌入式——QT】QT Charts

  • 概述
  • Qt提供的坐标轴类
  • QChart
  • QLineSeries
  • QValueAxis
  • 常见图表及用到的序列类
  • 图示
  • 代码示例

概述

QT Charts模块是一组易于使用的图表组件,它基于Qt的Graphics View架构,其核心组件是QChartView和QChart,QChartView父类是QGraphicsView,就是Graphics View架构的视图组件,所以QChartView是用于显示图表的视图,要想使用Qt Charts模块,就要在.pro文件中引入 Qt += charts

Qt提供的坐标轴类

  • QValueAxis:数值坐标轴;
  • QCategoryAxis:分组数值坐标轴;
  • QLongValueAxis:对数数值坐标轴;
  • QBarCategoryAxis:类别坐标轴;
  • QDateTimeAxis:日期时间坐标轴;

QChart

QChart是组合图表各部件,显示各种数据序列的绘图组件。

QChart主要函数

  • setTitle():设置图表标题;
  • setTitleFont():设置图表标题字体;
  • setTitleBrush():设置图表标题画刷;
  • setTheme():设置主题;
  • setMargins():设置绘图区与图表边界的4个边距;
  • legend():返回图表的图例;
  • setAnimationOptions():设置序列或坐标轴的动画效果;
  • addSeries():添加序列;
  • series():返回图表拥有的序列的列表;
  • removeSeries():移除一个序列,但并不删除序列对象;
  • removeAllSeries():移除并删除图表的所有序列;
  • addAxis():为图表的某个方向添加坐标轴;
  • axes():返回某个方向的坐标轴列表;
  • setAxisX():设置某个序列的水平方向的坐标轴;
  • setAxisY():设置某个序列的垂直方向的坐标轴;
  • removeAxis():移除一个坐标轴;
  • createDefaultAxes():根据已添加的序列的类型,创建缺省的坐标轴,前面已有的坐标轴会被删除;

QLineSeries

QLineSeries是用于绘制二维数据点的折线图。
QLineSeries类主要函数

  • setName():设置序列的名称 ;
  • chart():返回序列所属的图表对象 ;
  • setVisible():设置序列可见性;
  • show():显示序列;
  • hide():隐藏序列 ;
  • setColor():设置序列线条颜色 ;
  • setPen():设置绘制线条的画笔 ;
  • setBrush():设置绘制数据点的画刷 ;
  • setPointsVisible():设置数据点可见性 ;
  • append():添加一个数据点到序列;
  • insert():在某个位置插入一个数据点 ;
  • replace():替换某个数据点;
  • clear():清空所有数据点 ;
  • removePoints():从某个位置开始,删除指定个数的数据点;
  • setPointLabelsVisible():设置数据点标签的可见性;
  • setPointLabelsColor():设置数据点标签的文字颜色;
  • setPointLabelsFont():设置数据点标签的字体;
  • setPointLabelsFormat():设置数据点标签的格式;

QValueAxis

QValueAxis是数值坐标轴。

QValueAxis主要函数

  • setVisible():设置坐标轴可见性;
  • orientation():返回坐标轴方向;
  • setMin():设置坐标轴最小值;
  • setMax():设置坐标轴最大值;
  • setTitleVisible():设置轴标题可见性;
  • setRange():设置坐标轴最大、最小值范围 ;
  • setTitleText():设置轴标题文字;
  • setTitleFont():设置轴标题字体 ;
  • setLabelFromat():设置标签格式 ;
  • setLabelsBrush():设置标签的画刷;
  • setLabelsColor():设置标签的颜色 ;
  • setLabelsFont():设置标签的字体 ;
  • setTickCount():设置坐标轴主刻度的个数 ;
  • setLineVisible():设置轴线和刻度线的可见性;
  • setLinePen():设置轴线和刻度线的画笔;
  • setGridLineColor():设置网格线颜色 ;
  • setGridLinePen():设置网格线画笔;
  • setMinorTickCount():设置两个主刻度之间的次刻度的个数 ;
  • setMinorGridLineColor():设置次网格线的颜色 ;
  • setMinorGridLinePen():设置次网格线的画笔 ;
  • setMinorGridLineVisible():设置次网格线的可见性;

常见图表及用到的序列类

  • 柱状图:QBarSeries;
  • 水平柱状图:QHorizontalBarSeries;
  • 百分比柱状图:QPercentBarSeries;
  • 水平百分比柱状图:QHorizontalBarSeries;
  • 堆叠柱状图:QStackedBarSeries;
  • 水平堆叠柱状图:QHorizontalBarSeries;
  • 火柴盒图:QBoxPlotSeries;
  • 饼图:QPieSeries;
  • 折线图:QLineSeries;
  • 光滑折线图:QSplineSeries;
  • 散点图:QScatterSeries;
  • 面积图:QAreaSeries;
    这些类都是从QAbstractSeries类继承而来的。

图示

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/669535a0574b4c60ad9396172185185a.png
在这里插入图片描述
在这里插入图片描述

代码示例

QChartMainWindow.h

#ifndef QCHARTMAINWINDOW_H
#define QCHARTMAINWINDOW_H

#include <QMainWindow>
#include <QtCharts>

namespace Ui
{
    class QChartMainWindow;
}

class QChartMainWindow : public QMainWindow
{
    Q_OBJECT

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

    QLineSeries* curSeries;//当前序列
    QValueAxis* curAxis;//当前坐标轴

    void createChart();//创建图表
    void prepareData();//更新数据
    void updateFromChart();//从图表更新到界面

    void initUi();



private slots:
    void on_comboBox_currentIndexChanged(int index);

    void on_comboBox_2_currentIndexChanged(int index);

    void on_pushButton_3_clicked();

    void on_checkBox_6_stateChanged(int arg1);

    void on_checkBox_7_stateChanged(int arg1);

    void on_horizontalSlider_valueChanged(int value);

    void on_radioButton_clicked();

    void on_radioButton_2_clicked();

    void on_radioButton_3_clicked();

    void on_radioButton_4_clicked();

    void on_checkBox_2_stateChanged(int arg1);

    void on_radioButton_9_clicked();

    void on_radioButton_10_clicked();

    void on_checkBox_3_stateChanged(int arg1);

    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_6_clicked();

    void on_pushButton_7_clicked();

    void on_pushButton_8_clicked();

    void on_radioButtonX_clicked();

    void on_radioButtonY_clicked();

    void on_pushButtonRange_clicked();

    void on_pushButton_5_clicked();

private:
    Ui::QChartMainWindow* ui;

    QChart* chart;

    QLineSeries* series0;
    QLineSeries* series1;
};

#endif // QCHARTMAINWINDOW_H

QChartMainWindow.cpp

#include "QChartMainWindow.h"
#include "ui_QChartMainWindow.h"
#include <QTime>
#include <QFontDialog>
#include <QColorDialog>
QChartMainWindow::QChartMainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::QChartMainWindow)
{
    ui->setupUi(this);
    createChart();
    prepareData();
    updateFromChart();
    initUi();
}

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

void QChartMainWindow::createChart()
{
    chart = new QChart();
    chart->setTitle(u8"函数曲线");
    ui->graphicsView->setChart(chart);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);
    ui->graphicsView->chart()->legend()->setAlignment(Qt::AlignTop);
    //创建折线序列
    series0 = new QLineSeries();
    series1 = new QLineSeries();
    series0->setName(u8"Sin曲线");
    series1->setName(u8"Cos曲线");
    curSeries = series0;
    QPen pen;
    pen.setStyle(Qt::DotLine);
    pen.setWidth(2);
    pen.setColor(Qt::red);
    series0->setPen(pen);
    pen.setStyle(Qt::SolidLine);
    pen.setColor(Qt::blue);
    series1->setPen(pen);
    chart->addSeries(series0);
    chart->addSeries(series1);
    //数值坐标轴 X轴
    QValueAxis* axisX = new QValueAxis;
    curAxis = axisX;
    axisX->setRange(0, 10);
    axisX->setLabelFormat("%.1f");
    axisX->setTickCount(11);
    axisX->setMinorTickCount(4);
    axisX->setTitleText("time(secs)");
    //数值坐标轴 Y轴
    QValueAxis* axisY = new QValueAxis;
    axisY->setRange(-2, 2);
    axisY->setLabelFormat("%.2f");
    axisY->setTickCount(5);
    axisY->setMinorTickCount(4);
    axisY->setTitleText("value");
    chart->setAxisX(axisX, series0);
    chart->setAxisX(axisX, series1);
    chart->setAxisY(axisY, series0);
    chart->setAxisY(axisY, series1);
}

//填充数据
void QChartMainWindow::prepareData()
{
    QLineSeries* series0 = (QLineSeries*)ui->graphicsView->chart()->series().at(0);
    QLineSeries* series1 = (QLineSeries*)ui->graphicsView->chart()->series().at(1);
    series0->clear();
    series1->clear();
    qsrand(QTime::currentTime().second());
    qreal t=0, y1, y2, intv=0.1;
    qreal rd;
    int cnt = 100;
    for(int i=0; i<cnt; i++) {
        rd=(qrand()%10)-5;
        y1 = qSin(t)+rd/50;
        series0->append(t, y1);
        y2=qCos(t)+rd/50;
        series1->append(t, y2);
        t+=intv;
    }
}

void QChartMainWindow::updateFromChart()
{
    QChart* aChart = ui->graphicsView->chart();
    ui->lineEditTitle->setText(aChart->title());
    QMargins mg = aChart->margins();
    ui->spinBox->setValue(mg.left());
    ui->spinBox_2->setValue(mg.right());
    ui->spinBox_3->setValue(mg.top());
    ui->spinBox_4->setValue(mg.bottom());
}

void QChartMainWindow::initUi()
{
    ui->comboBox->addItem("NoAnimation", 0);
    ui->comboBox->addItem("GridAxisAnimations", 1);
    ui->comboBox->addItem("SeriesAnimations", 2);
    ui->comboBox->addItem("AllAnimations", 3);
    ui->comboBox_2->addItem("ChartThemeLight", 0);
    ui->comboBox_2->addItem("ChartThemeBlueCerulean", 1);
    ui->comboBox_2->addItem("ChartThemeDark", 2);
    ui->comboBox_2->addItem("ChartThemeBrownSand", 3);
    ui->comboBox_2->addItem("ChartThemeBlueNcs", 4);
    ui->comboBox_2->addItem("ChartThemeHighContrast", 5);
    ui->comboBox_2->addItem("ChartThemeBlueIcy", 6);
    ui->comboBox_2->addItem("ChartThemeQt", 7);
    ui->checkBox_7->setCheckState(Qt::Checked);
    ui->checkBox_6->setCheckState(Qt::Checked);
    ui->checkBox_2->setCheckState(Qt::Checked);
    ui->checkBox_3->setCheckState(Qt::Checked);
    ui->radioButton->setChecked(true);
    ui->horizontalSlider->setRange(0, 100);
    ui->horizontalSlider->setValue(100);
}

void QChartMainWindow::on_comboBox_currentIndexChanged(int index)
{
    switch(index) {
        case 0:
            chart->setAnimationOptions(QChart::NoAnimation);
            break;
        case 1:
            chart->setAnimationOptions(QChart::GridAxisAnimations);
            break;
        case 2:
            chart->setAnimationOptions(QChart::SeriesAnimations);
            break;
        case 3:
            chart->setAnimationOptions(QChart::AllAnimations);
            break;
    }
}


void QChartMainWindow::on_comboBox_2_currentIndexChanged(int index)
{
    switch(index) {
        case 0:
            chart->setTheme(QChart::ChartThemeLight);
            break;
        case 1:
            chart->setTheme(QChart::ChartThemeBlueCerulean);
            break;
        case 2:
            chart->setTheme(QChart::ChartThemeDark);
            break;
        case 3:
            chart->setTheme(QChart::ChartThemeBrownSand);
            break;
        case 4:
            chart->setTheme(QChart::ChartThemeBlueNcs);
            break;
        case 5:
            chart->setTheme(QChart::ChartThemeHighContrast);
            break;
        case 6:
            chart->setTheme(QChart::ChartThemeBlueIcy);
            break;
        case 7:
            chart->setTheme(QChart::ChartThemeQt);
            break;
    }
}


void QChartMainWindow::on_pushButton_3_clicked()
{
    bool ok = false;
    QFont font = QFontDialog::getFont(&ok);
    if(ok) {
        ui->graphicsView->chart()->legend()->setFont(font);
    }
}


void QChartMainWindow::on_checkBox_6_stateChanged(int arg1)
{
    if(arg1 ==2) {
        curSeries->setVisible(true);
    } else {
        curSeries->setVisible(false);
    }
}


void QChartMainWindow::on_checkBox_7_stateChanged(int arg1)
{
    if(arg1 ==2) {
        curSeries->setPointsVisible(true);
    } else {
        curSeries->setPointsVisible(false);
    }
}


void QChartMainWindow::on_horizontalSlider_valueChanged(int value)
{
    curSeries->setOpacity(value);
}


void QChartMainWindow::on_radioButton_clicked()
{
    ui->graphicsView->chart()->legend()->setAlignment(Qt::AlignTop);
}


void QChartMainWindow::on_radioButton_2_clicked()
{
    ui->graphicsView->chart()->legend()->setAlignment(Qt::AlignBottom);
}


void QChartMainWindow::on_radioButton_3_clicked()
{
    ui->graphicsView->chart()->legend()->setAlignment(Qt::AlignLeft);
}


void QChartMainWindow::on_radioButton_4_clicked()
{
    ui->graphicsView->chart()->legend()->setAlignment(Qt::AlignRight);
}


void QChartMainWindow::on_checkBox_2_stateChanged(int arg1)
{
    if(arg1 == 2) {
        ui->graphicsView->chart()->legend()->setVisible(true);
    } else {
        ui->graphicsView->chart()->legend()->setVisible(false);
    }
}


void QChartMainWindow::on_radioButton_9_clicked()
{
    curSeries=series0;
}


void QChartMainWindow::on_radioButton_10_clicked()
{
    curSeries=series1;
}


void QChartMainWindow::on_checkBox_3_stateChanged(int arg1)
{
    if(arg1 == 2) {
        ui->graphicsView->chart()->legend()->backgroundVisibleChanged(true);
    } else {
        ui->graphicsView->chart()->legend()->backgroundVisibleChanged(false);
    }
}


void QChartMainWindow::on_pushButton_clicked()
{
    chart->setTitle(ui->lineEdit->text());
}


void QChartMainWindow::on_pushButton_2_clicked()
{
    bool ok = false;
    QFont font = QFontDialog::getFont(&ok);
    if(ok) {
        ui->graphicsView->chart()->setTitleFont(font);
    }
}


void QChartMainWindow::on_pushButton_6_clicked()
{
    ui->lineEdit_2->setText(curSeries->name());
}


void QChartMainWindow::on_pushButton_7_clicked()
{
    QColor color = QColorDialog::getColor(curSeries->color(), this, u8"选择颜色");
    if(color.isValid()) {
        curSeries->setColor(color);
    }
}


void QChartMainWindow::on_pushButton_8_clicked()
{
    //TODO 曲线pen
}


void QChartMainWindow::on_radioButtonX_clicked()
{
    curAxis = (QValueAxis*)ui->graphicsView->chart()->axisX();
    ui->doubleSpinBoxMin->setValue(curAxis->min());
    ui->doubleSpinBoxMax->setValue(curAxis->max());
    ui->lineEditTitle->setText(curAxis->titleText());
    ui->checkBox->setChecked(curAxis->isTitleVisible());
}


void QChartMainWindow::on_radioButtonY_clicked()
{
    curAxis = (QValueAxis*)ui->graphicsView->chart()->axisY();
    ui->doubleSpinBoxMin->setValue(curAxis->min());
    ui->doubleSpinBoxMax->setValue(curAxis->max());
    ui->lineEditTitle->setText(curAxis->titleText());
    ui->checkBox->setChecked(curAxis->isTitleVisible());
}


void QChartMainWindow::on_pushButtonRange_clicked()
{
    curAxis->setRange(ui->doubleSpinBoxMin->text().toDouble(), ui->doubleSpinBoxMax->text().toDouble());
}


void QChartMainWindow::on_pushButton_5_clicked()
{
    QColor color = QColorDialog::getColor(curSeries->color(), this, u8"选择颜色");
    if(color.isValid()) {
        ui->graphicsView->chart()->legend()->setLabelColor(color);
    }
}


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端开发经验分享:写页面时总是有预期之外的滚动条怎么办?

问题描述&#xff1a; 在制作一个页面时常常会出现一些预期之外的滚动条&#xff0c;一般有以下原因&#xff1a;1.内容过多&#xff1a;当容器内的内容&#xff08;如文本、图片等&#xff09;的总高度或总宽度超过容器的可视区域时&#xff0c;滚动条就会出现。2.样式设置&a…

一维前缀和一维差分(下篇讲解二维前缀和二维差分)(超详细,python版,其他语言也很轻松能看懂)

本篇博客讲解一维前缀和&#xff0c;一维差分&#xff0c;还会给出一维差分的模板题&#xff0c;下篇博客讲解 二维前缀和&二维差分。 一维前缀和&#xff1a; 接触过算法的小伙伴应该都了解前缀和&#xff0c;前缀和在算法中应用很广&#xff0c;不了解也没有关系&#…

基于SSM的中国旅游网站管理系统+数据库+数据库表结构文档+免费远程调试

项目介绍&#xff1a; Javaee项目&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc Mybatis JspBootstrap来实现。MySQL数据库作为系统数据储存平台&#xff…

阻止默认行为 e.preventDefault()搭配passive:false才有效

正确情况 如果想阻止默认行为,那么 e.preventDefault()搭配passive:false才是正解 document.addEventListener(touchmove,(e)>{ e.preventDefault() console.log(123,123);},{passive:false}) 如果搭配 passive:false,则会报警告 e.preventDefault()搭配passive:true会报…

php 对接Vungle海外广告平台收益接口Reporting API

今天对接的是Vungle广告reporting api接口&#xff0c;拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到Vungle后台就能看到文档地址以及参数&#xff1a; 文档地址&#xff1a;https://support.vungle.com/hc/en-us/articles/211365828-Publisher-Reporting…

线程池实现“线程复用”的原理

线程池实现“线程复用”的原理 学习线程复用的原理&#xff0c;以及对线程池的 execute 这个非常重要的方法进行源码解析。 线程复用原理 我们知道线程池会使用固定数量或可变数量的线程来执行任务&#xff0c;但无论是固定数量或可变数量的线程&#xff0c;其线程数量都远远…

3.3网安学习第三阶段第三周回顾(个人学习记录使用)

本周重点 ①渗透测试介绍 ②sqlmap注入扫描工具 ③XSS脚本注入 本周主要内容 ①渗透测试介绍 一、渗透测试 通过模拟黑客对系统进行攻击的手段或技术&#xff0c;在被测系统中发现漏洞的行为。除了提供漏洞之外&#xff0c;还需提供安全意见。 与黑站不同&#xff0c;渗…

Vue响应式原理全解析

前言 大家好&#xff0c;我是程序员蒿里行。浅浅记录一下面试中的高频问题&#xff0c;请你谈一下Vue响应式原理。 必备前置知识&#xff0c;​​Vue2​​官方文档中​​深入响应式原理​​​及​​Vue3​​官方文档中​​深入响应式系统​​。 什么是响应式 响应式本质是当…

RabbitMQ集群部署

集群部署 我们看看如何安装RabbitMQ的集群。 1.集群分类 在RabbitMQ的官方文档中&#xff0c;讲述了两种集群的配置方式&#xff1a; 普通模式&#xff1a;普通模式集群不进行数据同步&#xff0c;每个MQ都有自己的队列、数据信息&#xff08;其它元数据信息如交换机等会同…

基于Android的Appium+Python自动化脚本编写

1.Appium Appium是一个开源测试自动化框架&#xff0c;可用于原生&#xff0c;混合和移动Web应用程序测试&#xff0c; 它使用WebDriver协议驱动iOS&#xff0c;Android和Windows应用程序。 通过Appium&#xff0c;我们可以模拟点击和屏幕的滑动&#xff0c;可以获取元素的id…

动态规划(算法竞赛、蓝桥杯)--单调队列优化DP琪露诺

1、B站视频链接&#xff1a;E46 单调队列优化DP 琪露诺_哔哩哔哩_bilibili 题目链接&#xff1a;琪露诺 - 洛谷

自定义类型--结构体、联合体、枚举类型

**Ladies and gentlemen**&#xff0c;今天&#xff0c;我们将来进行对自定义类型的学习&#xff01; 目录 1.结构的特殊声明2. 结构体内存对齐2.1 对齐规则2.1.12.1.22.1.32.1.4 2.2 为什么存在内存对齐?1. 平台原因 (移植原因)&#xff1a;2. 性能原因&#xff1a; 2.3 修改…

这个简单的生活方式,为你带来满满的幸福感

在今天文章的开头&#xff0c;我想请你思考一个问题&#xff1a;影响幸福感的最大因素是什么&#xff1f; 不妨先想一想&#xff0c;再往下拉&#xff0c;继续阅读。 可能不少朋友的回答&#xff0c;会是财富、事业、理想、生活环境、社会地位…… 这些因素当然对幸福感都非常重…

Python正则表达式之模式修正符,你get了吗?

​大家好&#xff0c;今天我要和大家分享一个Python编程中的神秘武器——正则表达式模式修正符&#xff01;正则表达式&#xff0c;对于很多编程新手来说&#xff0c;可能是一个头疼的问题。但别担心&#xff0c;模式修正符就像是你手中的魔法棒&#xff0c;让你的正则表达式更…

3.21系统栈、数据结构栈、栈的基本操作、队列、队列的基本操作------------》

栈 先进后出、后进先出 一、系统栈 大小&#xff1a;8MB 1、局部变量 2、未经初始化为随机值 3、代码执行到变量定义时为变量开辟空间 4、当变量的作用域结束时回收空间 5、函数的形参和返回值 6、函数的调用关系、保护现场和恢复现场 7、栈的增长方向&#xff0c;自高…

C语言例:设 int x; 则表达式 (x=4*5,x*5),x+25 的值

代码如下&#xff1a; #include<stdio.h> int main(void) {int x,m;m ((x4*5,x*5),x25);printf("(x4*5,x*5),x25 %d\n",m);//x4*520//x*5100//x2545return 0; } 结果如下&#xff1a;

必学干货!使用Python正则表达式匹配多个字符

1.匹配多个字符 今天我们来聊一聊正则表达式中一个很强大的功能&#xff1a;匹配多个字符&#xff01;正则表达式是一个非常强大的工具&#xff0c;可以帮助我们轻松地处理和匹配字符串。通过使用不同的符号和技巧&#xff0c;我们可以匹配多个字符&#xff0c;从而更加灵活地…

【智能算法】海洋捕食者算法(MPA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2020年&#xff0c;Afshin Faramarzi 等人受到海洋生物适者生存启发&#xff0c;提出了海洋捕食者算法(Marine Predators Algorithm&#xff0c;MPA)。 2.算法原理 2.1算法思想 MPA根据模拟自然界…

WSL2的安装步骤

WSL2&#xff08;Windows Subsystem for Linux 2&#xff09;是微软公司开发的一项创新性技术&#xff0c;它在Windows操作系统上提供了一个完整的Linux内核&#xff0c;并允许用户在Windows环境中运行Linux发行版。之前想在Windows上使用Linux系统必须先安装VirtualBox或VMWar…

做跨境用哪种代理IP比较好?怎么选到干净的IP?

代理IP对于做跨境的小伙伴来说&#xff0c;都是必不可少的工具&#xff0c;目前出海的玩法已经是多种多样&#xff0c;开店、账号注册、短视频运营、直播带货、网站SEO等等都是跨境人需要涉及到的业务。而国外代理IP的获取渠道非常多&#xff0c;那么做跨境到底应该用哪种代理I…