[Qt学习笔记]QT下获取Halcon图形窗口鼠标事件并执行相应操作

目录

  • 1、背景
  • 2、参考信息
  • 3、目标
  • 4、步骤
    • 4.1 Halcon库的配置
    • 4.2 读取图像,并实现图像自适应窗体控件大小
    • 4.3 主要的图形绘制和贴图操作见如下代码,其中重点为全局函数的创建来实现选择Select、拖拽Drag和尺寸Resize事件响应。
  • 5、总结

1、背景

在视觉项目开发过程中碰到了需要使用Halcon进行图像算法开发的需求,估计很多视觉工程师都用到过Halcon软件开发库,但是完成Halcon算法开发后就会遇到一个问题,就是图像的显示、读写、UI交互等问题,由于Halcon具有特殊的图像文件格式HObject和数据格式HTuple,所以说需要格式转换后才能实现相对应的操作,不过Halcon本身也有比较实用的显示、界面交互的功能,所以如何在C++或QT下使用这些功能成为了接下来需要去研究和实践的工作。

2、参考信息

Halcon针对不同的开发环境,给出了不同的开发例程,针对图形显示及界面操作这一块,Halcon只给出了C#的相关例程,其运行结果如下:
DrawingObject.png

Draw.png
其中可以实现在窗口界面创建矩形、圆、椭圆等形状的Region,并根据鼠标来选择、拖动和设置尺寸,并实现设置颜色,获取坐标,region区内二值化、轮廓化等一系列后续操作。

3、目标

实现在QT环境下,将Halcon窗口贴在QT的控件上,并实现上述创建和操作region的基本动作。

4、步骤

4.1 Halcon库的配置

本人使用的是Halcon12.0的破解版,目前调用Halcon的函数不会出错,但是项目中有调用新版本的Halcon库有出错状况,目前未查证是不是版本的问题,Halcon配置主要在PRO文件中添加Include和Lib的引用路径。其中HALCONROOT是环境变量中Halcon的安装路径。

  #includes
  INCLUDEPATH   += "$$(HALCONROOT)/include"
  INCLUDEPATH   += "$$(HALCONROOT)/include/halconcpp"

  #libs
  QMAKE_LIBDIR  += "$$(HALCONROOT)/lib/$$(HALCONARCH)"
  unix:LIBS     += -lhalconcpp -lhalcon -lXext -lX11 -ldl -lpthread
  win32:LIBS    += "$$(HALCONROOT)/lib/$$(HALCONARCH)/halconcpp.lib" \
                   "$$(HALCONROOT)/lib/$$(HALCONARCH)/halcon.lib"

4.2 读取图像,并实现图像自适应窗体控件大小

这里我首先创建了一个QHalconWindow类,然后在qt的ui界面将widget提升为QHalconWindow类,这样就免去了Halcon窗口句柄和ui句柄的绑定,直接通过QHalconWindow类来调用就行。

qhalconwindow.h文件

#include <QObject>
#include <QWidget>
#include "HalconCpp.h"

class QHalconWindow : public QWidget
{
    Q_OBJECT
public:
    explicit QHalconWindow(QWidget *parent = 0,long Width=0,long Height=0);
    virtual ~QHalconWindow(void);

    HalconCpp::HTuple WindowID(void) {return WinID;}   //f返回窗口句柄

protected:
    void resizeEvent(QResizeEvent*);                 //窗口大小尺寸调整事件
private:
    HalconCpp::HTuple WinID;
    void OpenWindow(void);
}

Cpp文件主要是关于窗口基本操作的实现函数

#include "qhalconwindow.h"

using namespace HalconCpp;

QHalconWindow::QHalconWindow(QWidget *parent,long Width,long Height)
    : QWidget(parent)
{
    resize(Width,Height);
    show();
    OpenWindow();

}

QHalconWindow::~QHalconWindow(void)
{
    CloseWindow(WindowID());
}

void QHalconWindow::OpenWindow(void)
{
    SetWindowAttr("border_width",0);
    SetCheck("~father");
    HalconCpp::OpenWindow(0,0,100,100,(Hlong)winId(),"visible","",&WinID);
    SetCheck("father");
}

//修改窗口尺寸
void QHalconWindow::resizeEvent(QResizeEvent *)
{
    SetWindowExtents(WindowID(),0,0,width(),height());
}

参考Halcon中关于SetDrawingObjectCallback函数的描述,需要在c++下面调用时,调用C++格式的函数,即下图的Void的回调函数指针。
回调函数.PNG
但是这个回调函数在程序中需要定义为一个全局函数,主要依据是Halcon中介绍,如下:
回调函数要求.PNG
所以根据这些需求完成Halcon窗口中绘制矩形、圆形和直线的操作

4.3 主要的图形绘制和贴图操作见如下代码,其中重点为全局函数的创建来实现选择Select、拖拽Drag和尺寸Resize事件响应。

Widget.h文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QList>
#include <QStack>
#include <functional>
#include "HalconCpp.h"
//#include "qhalconwindow.h"

using namespace HalconCpp;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    void InitWin(void);
    static Widget* getInstance();

protected:
    void resizeEvent (QResizeEvent*);
    void InitFg(void);

private slots:
    void on_HalconWinD_customContextMenuRequested(const QPoint &pos);
    void onTaskBoxContextMenuEvent();
    void  onTaskDeleteObj();
    void on_btn_DrawRectangle_clicked();
    void on_btn_DrawCircle_clicked();
    void on_btn_DrawLine_clicked();
    void on_btn_ClearAllObj_clicked();
    void AttachDrawObj(HDrawingObject obj);
    void slot_ReceiveData(long);

signals:
    void signal_data(long);
private:
    Ui::Widget *ui;
    //Halcon窗口的参数
    HTuple WindowIDBuf,FGHandle,Width,Height,Area;
    HTuple WindowWidth,WindowHeight;
    HObject Image;
    QStack<HObject> graphic_stack;
    QList<HDrawingObject> drawing_objects;
    HTuple Draw_Text;
    QList<HTuple>Drawing_Index;
};

#endif // WIDGET_H

主要实现代码

#pragma execution_character_set("utf-8")
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QDebug>
#include <QMenu>

void CallBackFunc_Set(long DrawID,long WindowHandle, char* type);
void CallBackFunc_DrawObj(long DrawID,long WindowHandle, char* type);
HTuple selected_drawing_object;
Widget* instance;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    WindowIDBuf = -1;
    Draw_Text=HTuple();
    InitWin();
    instance = this;
    connect(this,SIGNAL(signal_data(long)),this,SLOT(slot_ReceiveData(long)));
}

Widget::~Widget()
{
    HalconCpp::CloseWindow(WindowIDBuf);
    delete ui;
}

//建立自身调用
Widget *Widget::getInstance()
{
    return instance;
}

void Widget::InitFg(void)
{
    Hlong disp_width, disp_height;
    //读取一张图像并获取图像大小
    ReadImage(&Image,"D:/Test_Image/kobe.jpg");
    GetImageSize(Image,&Width,&Height);
    
    //根据图像的大小修改界面的尺寸大小
    //    disp_width = ui->HalconWinD->width();
    //    disp_height = ui->HalconWinD->height();
    //    ui->HalconWinD->resize(Width[0].L(),Height[0].L());
    //    resize(width()+Width[0].L()-disp_width,height()+Height[0].L()-disp_height);
}

void Widget::InitWin(void)
{
    InitFg();
    //    HTuple hv_WindowHandleCurrent;
    Hlong WinIDcurrent = (Hlong)ui->HalconWinD->winId();
    WindowWidth = ui->HalconWinD->width();
    WindowHeight = ui->HalconWinD->height();
    OpenWindow(0,0,WindowWidth,WindowHeight,WinIDcurrent,"","",&WindowIDBuf);    
    AttachBackgroundToWindow(Image,WindowIDBuf);
    //    DispObj(Image,ui->HalconWinD->WindowID());
}

void Widget::resizeEvent(QResizeEvent *)
{
    if(WindowIDBuf>0 )
    {
        WindowWidth = ui->HalconWinD->width();
        WindowHeight = ui->HalconWinD->height();
        SetWindowExtents(WindowIDBuf,0,0,WindowWidth,WindowHeight);
        //       DispObj(Image,WindowIDBuf);
    }
}

//右键选取后的Menu的对应操作函数
void Widget::onTaskBoxContextMenuEvent()
{
    QAction *pEven = qobject_cast<QAction *>(this->sender()); //this->sender()就是发信号者 QAction
    
    int iType = pEven->data().toInt();
    HTuple position;
    GetDrawingObjectParams(selected_drawing_object,(HTuple("row1").Append("column1")),&position);    
    switch (iType)
    {
    case 1:
    {
        SetDrawingObjectParams(selected_drawing_object,"color","green");
        QMessageBox::about(this, "tip", pEven->text());
        break;
    }
    case 2:
    {
        SetDrawingObjectParams(selected_drawing_object,"color","blue");
        QMessageBox::about(this, "tip", pEven->text());
        break;
    }
    case 3:
    {
        SetDrawingObjectParams(selected_drawing_object,"color","yellow");
        QMessageBox::about(this, "tip", pEven->text());
        break;
    }
    case 4:
    {
        SetDrawingObjectParams(selected_drawing_object,"color","black");
        QMessageBox::about(this, "tip", pEven->text());
        break;
    }
    default:
        break;
    }
    int Select_DrawID;
    for(int i=0;i!=Drawing_Index.size();++i)
    {
        if(Drawing_Index.at(i) == selected_drawing_object)
        {
            Select_DrawID=i;
            qDebug()<<"select ID:"<<i<<endl;
        }
    }
    for(int i=0;i!=Drawing_Index.size();++i)
    {
        if(Drawing_Index.at(i) == selected_drawing_object)
        {
            Select_DrawID=i;
        }
    }
    QString Message_test = pEven->text();
    QByteArray ba = Message_test.toLocal8Bit();
    const char *str = ba.data();
    HTuple Draw_Message(str);
    HTuple Draw_MesObj;    
    CreateDrawingObjectText(position[0],position[1], Draw_Message,&Draw_MesObj);
    AttachDrawingObjectToWindow(WindowIDBuf,Draw_MesObj);
    Draw_Text[Select_DrawID]=Draw_MesObj;    
}

//右键选取删除操作对应函数
void Widget::onTaskDeleteObj()
{
    int Select_DrawID;
    for(int i=0;i!=Drawing_Index.size();++i)
    {
        if(Drawing_Index.at(i) == selected_drawing_object)
        {
            Select_DrawID=i;
            qDebug()<<"select ID:"<<i<<endl;
        }
    }
    if(Draw_Text.Length() >Select_DrawID)
    {
        DetachDrawingObjectFromWindow(WindowIDBuf,Draw_Text[Select_DrawID]);
        DetachDrawingObjectFromWindow(WindowIDBuf,selected_drawing_object);
    }
    else
    {
        DetachDrawingObjectFromWindow(WindowIDBuf,selected_drawing_object);
    }
}

//右键响应事件
void Widget::on_HalconWinD_customContextMenuRequested(const QPoint &pos)
{    
    HTuple Row_Mouse,Column_Mouse,Button,position;
    GetMposition(WindowIDBuf,&Row_Mouse,&Column_Mouse,&Button);
    GetDrawingObjectParams(selected_drawing_object,(HTuple("column1").Append("column2").Append("row1").Append("row2")),&position);
    qDebug()<<Column_Mouse.D()<<Row_Mouse.D()<<position[0].D()<<position[1].D()<<position[2].D()<<position[3].D()<<endl;
    
    if(Column_Mouse>position[0] && Column_Mouse<position[1])
    {
        if(Row_Mouse>position[2] && Row_Mouse<position[3])
        {           
            //创建菜单对象
            QMenu *pMenu = new QMenu(this);
            
            QAction *pTask1 = new QAction(tr("得分王"), this);
            QAction *pTask2 = new QAction(tr("总冠军"), this);
            QAction *pTask3 = new QAction(tr("MVP"), this);
            QAction *pTask4 = new QAction(tr("单场81分"), this);
            QAction *action=new QAction(this);
            QAction *pDelete = new QAction(tr("追随黑曼巴!"), this);
            
            pTask1->setData(1);
            pTask2->setData(2);
            pTask3 ->setData(3);
            pTask4->setData(4);
            action->setSeparator(true);
            pDelete ->setData(5);
            
            //把QAction对象添加到菜单上
            pMenu->addAction(pTask1);
            pMenu->addAction(pTask2);
            pMenu->addAction(pTask3);
            pMenu->addAction(pTask4);
            pMenu->addAction(action);
            pMenu->addAction(pDelete);
                       
            //连接鼠标右键点击信号
            connect(pTask1, SIGNAL(triggered()), this, SLOT(onTaskBoxContextMenuEvent()));
            connect(pTask2, SIGNAL(triggered()), this, SLOT(onTaskBoxContextMenuEvent()));
            connect(pTask3, SIGNAL(triggered()),this, SLOT(onTaskBoxContextMenuEvent()));
            connect(pTask4, SIGNAL(triggered()), this, SLOT(onTaskBoxContextMenuEvent()));
            connect(pDelete, SIGNAL(triggered()),this, SLOT(onTaskDeleteObj()));
            
            //在鼠标右键点击的地方显示菜单
            pMenu->exec(cursor().pos());
            qDebug()<<cursor().pos().x()<<cursor().pos().y()<<endl;
            
            //释放内存
            QList<QAction*> list = pMenu->actions();
            foreach (QAction* pAction, list) delete pAction;
            delete pMenu;
        }
    }
}
//画矩形框
void Widget::on_btn_DrawRectangle_clicked()
{   
    HTuple Rect_ID;
    CreateDrawingObjectRectangle1(100,100,200,200,&Rect_ID);
    SetDrawingObjectParams(Rect_ID,"color","red");
    qDebug()<<"Rect_ID"<<Rect_ID.D()<<endl;
    Drawing_Index.append(Rect_ID);
    //转换句柄为HDrawingObject
    HDrawingObject draw=HDrawingObject(Rect_ID);
    AttachDrawingObjectToWindow(WindowIDBuf,Rect_ID);
    AttachDrawObj(draw);
}


void Widget::AttachDrawObj(HDrawingObject obj)
{
    drawing_objects.append(obj);
    obj.SetDrawingObjectCallback("on_resize",(void*)CallBackFunc_DrawObj);
    obj.SetDrawingObjectCallback("on_drag",(void*)CallBackFunc_DrawObj);
    //    obj.SetDrawingObjectCallback("on_attach",CallBackFunc_Set);
    obj.SetDrawingObjectCallback("on_select",(void*)CallBackFunc_Set);
    //    AttachDrawingObjectToWindow(ui->HalconWinD->WindowID(),obj);
}

//Drag和Resize对应的回调函数,这里用UI的一个自身指针将全局函数的变量传递给UI,从而调用UI下的函数
void CallBackFunc_DrawObj(long DrawID,long WindowHandle, char* type)
{
    Widget::getInstance()->signal_data(DrawID);
}

//Drag和Resize对应的UI中的处理函数
void Widget::slot_ReceiveData(long DrawID)
{
    int Select_DrawID;
    for(int i=0;i!=Drawing_Index.size();++i)
    {
        if(Drawing_Index.at(i) == (HTuple)DrawID)
        {
            Select_DrawID=i;
            qDebug()<<"delete ID:"<<i<<endl;
        }
    }
    if(Draw_Text.Length() >Select_DrawID)
    {
        DetachDrawingObjectFromWindow(WindowIDBuf,Draw_Text[Select_DrawID]);
    }
}

//选取矩形框对应的回调函数
void CallBackFunc_Set(long DrawID,long WindowHandle, char* type)
{  
    selected_drawing_object=DrawID;
    SetDrawingObjectParams(DrawID,"color","blue");
    HObject Region;
    HTuple Area,row,column;
    GetDrawingObjectIconic(&Region,DrawID);
    AreaCenter(Region,&Area,&row,&column);
}

//清除窗口所有图形
void Widget::on_btn_ClearAllObj_clicked()
{
    for(int i=0;i!=Drawing_Index.size();++i)
    {
        ClearDrawingObject(Drawing_Index.at(i));       
    }
    for(int j=0;j<Draw_Text.Length();++j)
    {
        ClearDrawingObject(Draw_Text[j]);
    }    
    Drawing_Index.clear();
    Draw_Text=HTuple();
}

//画圆形
void Widget::on_btn_DrawCircle_clicked()
{
    HTuple Circle_ID;
    CreateDrawingObjectCircle(300,300,200,&Circle_ID);
    SetDrawingObjectParams(Circle_ID,"color","red");
    AttachDrawingObjectToWindow(WindowIDBuf,Circle_ID);
}

//画直线
void Widget::on_btn_DrawLine_clicked()
{
    HTuple Line_ID;
    CreateDrawingObjectLine(300,300,600,600,&Line_ID);
    SetDrawingObjectParams(Line_ID,"color","yellow");
    AttachDrawingObjectToWindow(WindowIDBuf,Line_ID);
}

5、总结

这个知识点本身并不难,而且Halcon也带有c#的例程,主要当初碰到的难点是无法理解其回调函数的Draw_ID是如何传递的,最后查到Halcon的帮助资料才发现,按照全局回调函数的样子去定义,回调会自动返回你当前所选择的Draw_ID,从而可以使用该Draw_ID进行你所需要的操作。
最后放上最终的效果:
缅怀.png

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

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

相关文章

大广赛都有哪些命题可以选择,已更新命题汇总

截止到2024年3月19日&#xff0c;今年的大广赛一共发布了6个命题&#xff0c;本文就给大家汇总一下今年的命题细节都有哪些&#xff1f; 即时设计命题 即时设计命题素材和资源下载 一、UI类 1、界面设计   针对当下社会所关注的热点问题&#xff0c;包括但不限于&#xff1…

【c语言篇】每日一题-pta-实验11-2-9 链表逆置

题目如下&#xff1a; 裁判测试程序样例&#xff1a; #include <stdio.h> #include <stdlib.h>struct ListNode {int data;struct ListNode *next; };struct ListNode *createlist(); /*裁判实现&#xff0c;细节不表*/ struct ListNode *reverse( struct ListNod…

Flutter Widget:StatefulWidget StatelessWidget

Widget 概念 Widget 将是构建Flutter应用的基石&#xff0c;在Flutter开发中几乎所有的对象都是一个 Widget 。 在Flutter中的widget 不仅表示UI元素&#xff0c;也表示一些功能性的组件&#xff0c;如&#xff1a;手势 、主题Theme 等。而原生开发中的控件通常只是指UI元素。…

耐腐蚀高纯特氟龙塑料量瓶进口聚四氟乙烯材质PFA容量瓶

PFA容量瓶&#xff0c;也叫特氟龙量瓶&#xff0c;是用于配制标准浓度溶液的精确实验室器皿&#xff0c;是有着细长颈、梨形肚的耐强腐蚀平底塑料瓶&#xff0c;颈上有标线&#xff0c;常用来直接配制标准溶液和准确稀释溶液以及制备样品溶液。因其有着不易碎、材质纯净、化学稳…

如何让自己上百度百科?个人百科词条创建

百度百科&#xff0c;作为我国最大的中文百科全书&#xff0c;其影响力和权威性不言而喻。能够登上百度百科&#xff0c;意味着个人的知名度、成就和社会影响力得到了广泛认可。那么&#xff0c;如何才能让自己上百度百科呢&#xff1f;接下来伯乐网络传媒就来给大家讲解一下。…

基于Spring Boot网络相册设计与实现

摘 要 网络相册设计与实现的目的是让使用者可以更方便的将人、设备和场景更立体的连接在一起。能让用户以更科幻的方式使用产品&#xff0c;体验高科技时代带给人们的方便&#xff0c;同时也能让用户体会到与以往常规产品不同的体验风格。 与安卓&#xff0c;iOS相比较起来&am…

Unity 学习笔记 2.预制体,Instantiate()生成,Destroy()销毁

下载源码 UnityPackage 1. 动态创建预制体 // 在外部拖入预制体public GameObject enemy;void Start(){for (int i 0; i < 5; i){// 生成游戏对象&#xff1a;Instantiate();GameObject ENEMY Instantiate(enemy);// 根据i的增大&#xff0c;一字排开ENEMY.GetComponent&l…

大数据面试题 —— HBase

目录 什么是HBase简述HBase 的数据模型HBase 的读写流程HBase 在写的过程中的region的split的时机HBase 和 HDFS 各自的使用场景HBase 的存储结构HBase 中的热现象&#xff08;数据倾斜&#xff09;是怎么产生的&#xff0c;以及解决办法有哪些HBase rowkey的设计原则HBase 的列…

论文阅读:机器人跑酷学习

项目开源地址&#xff1a;https://github.com/ZiwenZhuang/parkour 摘要&#xff1a; 跑酷对腿部机动性是一项巨大的挑战&#xff0c;要求机器人在复杂环境中快速克服各种障碍。现有方法可以生成多样化但盲目的机动技能&#xff0c;或者是基于视觉但专门化的技能&#xff0c;…

Windows下MySQL服务启动常见的两种方式,完美适配Mysql5.7,MySql8.0

文章目录 一、图形界面下启动mysql服务二、在命令行重新启动mysql服务3 推荐阅读4 源码获取&#xff1a; Windows系统下&#xff0c;MySQL服务的启动&#xff0c;常见的两种启动方式如下&#xff1a; 一、图形界面下启动mysql服务 在图形界面下启动mysql服务的流程如下&#x…

Lvs+keepalived+nginx搭建高可用负载均衡集群

环境配置 master主机192.168.199.149&#xff0c;虚拟IP192.168.199.148 back备机192.168.199.150 真实服务器1 192.168.199.155 真实服务器2 192.168.199.156 关闭防火墙和selinux master配置&#xff08;149&#xff09; 添加虚拟IP ip addr add 192.168.199.148/24 …

vue axios 缓存 接口请求实现缓存加载

文章写的多了&#xff0c;开头就不知道怎么写了&#xff0c;硬挤一些句子总觉的卖弄。其实更多的想留下各位看官&#xff0c;多多的点赞&#xff0c;多多的关注&#xff0c;多的收藏。为将来的博客化动作做好前期数据粉丝基础。哦哦哦&#xff0c;我在想啥呢。。这大下午的。。…

【PyTorch][chapter 22][李宏毅深度学习][ WGAN]【实战三】

前言&#xff1a; 本篇主要讲两个WGAN的两个例子&#xff1a; 1 高斯混合模型 WGAN实现 2 MNIST 手写数字识别 -WGAN 实现 WGAN 训练起来蛮麻烦的,如果要获得好的效果很多超参数需要手动设置 1&#xff1a; 噪声的维度 2: 学习率 3&#xff1a; 生成器&#xff0c;鉴别器…

探索 TorchRe-ID--基于 Python 的人员再识别库

导言 人员再识别&#xff08;re-ID&#xff09;是计算机视觉中的一项重要任务&#xff0c;在监控系统、零售分析和人机交互中有着广泛的应用。TorchRe-ID 是一个功能强大、用户友好的 Python 库&#xff0c;它为人员再识别任务提供了一套全面的工具和模型。在本文中&#xff0…

Web前端-HTML

HTML 负责页面的结构&#xff08;页面的元素和内容&#xff09; HTML由标签组成&#xff0c;标签都是预定义好的。例如<a>展示超链接&#xff0c;使用<img>展示图片&#xff0c;<vedio>展示视频。 HTML代码直接在浏览器中运行&#xff0c;HTML标签由浏览器…

GitHub Copilot+ESP开发实战-串口

上篇文章讲了GitHub Copilot在应用中可能遇到的问题&#xff0c;接下来小启就简单介绍下GitHub Copilot在ESP32开发中C语言实现串口功能&#xff0c;感兴趣的可以看看。 一、向Copilot提问&#xff1a; 1. ESP32用C语言实现串口初始化&#xff1b; 2.配置uart为1&#xff0c…

web前端之旋转木马的图片效果、鼠标进入停止动画、keyframes、hover、child、nth

MENU 前言效果图htmlstyle 前言 1、旋转时有卡顿&#xff0c;暂时未找到解决办法&#xff1b; 2、-webkit-box-reflect样式属性一起用&#xff0c;未找到替换属性。 3、灵活性不够&#xff0c;不能自定义图片张数&#xff0c;后期打算使用scss来实现。 效果图 html <div cl…

WiFi是可以连接网络,但是在Pixel 手机上就连接提示受阻,无法上网-解决方法

1&#xff0c;通过USB连接手机&#xff0c;然后通过adb命令执行 adb shell settings delete global captive_portal_mode adb shell settings put global captive_portal_mode 0 adb shell settings get global captive_portal_mode adb shell settings delete global capti…

计算机网络:数据交换方式

计算机网络&#xff1a;数据交换方式 电路交换分组交换报文交换传输对比 本博客介绍计算机之间数据交换的三种方式&#xff0c;分别是电路交换、分组交换以及报文交换。 电路交换 我们首先来看电路交换&#xff0c;在电话问世后不久&#xff0c;人们就发现要让所有的电话机都…

如何在gitee上fork github上面的项目,并保持同步更新

前言 当看到github上面比较好的项目&#xff0c;想用到自己的项目&#xff0c;又不想仓库别人看&#xff0c;同时网络不好&#xff0c;囊中又羞涩的情况下&#xff0c;怎么办&#xff1f; 可以考虑用gitee来同步更新github上面的项目。 一、在gitee创建私有仓库 新建的是选择…
最新文章