当前位置: 首页 > news >正文

libVLC 视频窗口上叠加透明窗口

很多时候,我们需要在界面上画一些三角形、文字等之类的东西,我们之需要重写paintEvent方法,比如像这样

void Widget::paintEvent(QPaintEvent *event)

以下就是重写的代码。 

void Widget::paintEvent(QPaintEvent *event)
{//创建QPainter对象,指明父对象,否则不能看见QPainter painter(this);//先画一条线QPen pen;//设置线宽pen.setWidth(2);//设置颜色pen.setColor(Qt::red);//设置线的样式 实线、虚线pen.setStyle(Qt::DashDotLine);//设置线端点样式pen.setCapStyle(Qt::RoundCap);//设置画笔painter.setPen(pen);//画线painter.drawLine(10,10,100,100);//设置画刷QBrush brush;//画刷设置颜色brush.setColor(Qt::yellow);//设置填充样式brush.setStyle(Qt::SolidPattern);//设置画刷painter.setBrush(brush);//画四边形painter.drawRect(QRect(300,300,50,50));//画多边形,三角形QPoint points[] = {QPoint(200,200),QPoint(200,260),QPoint(260,260),};painter.drawPolygon(points,3);//设置字体QFont font;//字体大小font.setPointSize(30);//粗体font.setBold(true);//设置字体painter.setFont(font);//画字painter.drawText(400,400,QString("Qt"));
}

运行如下图所示:

更多QPainter相关的东西,请看:

Qt QPainter绘图_qt painter-CSDN博客 

但是现在我们需要在播放视频的界面上绘制窗体,像下面这样。

这里我叠加了一个Widget在上面,widget上放了两个控件,一个label和一个comboBox。

ui原型如下所示:

首先我们需要定义一个叠加窗体类TopWidget,

这个类很简单,设置了窗体无边框和透明。

	//窗口无边框setWindowFlags(Qt::FramelessWindowHint | Qt::Window);// 窗口透明this->setAttribute(Qt::WA_TranslucentBackground);

然后重写绘图事件。 

#pragma once#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include "ui_TopWidget.h"class TopWidget : public QWidget
{Q_OBJECTpublic:TopWidget(QWidget *parent = nullptr);~TopWidget();protected:void paintEvent(QPaintEvent *pEvent);private:Ui::TopWidgetClass ui;
};#include "TopWidget.h"TopWidget::TopWidget(QWidget *parent): QWidget(parent)
{ui.setupUi(this);//窗口无边框setWindowFlags(Qt::FramelessWindowHint | Qt::Window);// 窗口透明this->setAttribute(Qt::WA_TranslucentBackground);
}TopWidget::~TopWidget()
{}void TopWidget::paintEvent(QPaintEvent *pEvent)
{QStyleOption opt;opt.initFrom(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式
}

 在主界面中,创建叠加窗体对象:

    TopWidget *m_widget = nullptr;	m_widget = new TopWidget(this);m_widget->setStyleSheet(QString("background-color: rgba(255, 0, 0, 0%);"));m_widget->show();

重写绘图和窗体移动事件:我们需要在主窗体移动的时候,叠加窗体跟随着主窗体移动。

void showWidget::paintEvent(QPaintEvent *event)
{QStyleOption opt;opt.initFrom(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式QPoint pos_form = ui.widgetShow->mapToGlobal(ui.widgetShow->pos());m_widget->move(pos_form);m_widget->setGeometry(pos_form.x(), pos_form.y(), ui.widgetShow->width(), ui.widgetShow->height());
}void showWidget::moveEvent(QMoveEvent *event)
{QPoint pos_form = ui.widgetShow->mapToGlobal(ui.widgetShow->pos());m_widget->move(pos_form);m_widget->setGeometry(pos_form.x(), pos_form.y(), ui.widgetShow->width(), ui.widgetShow->height());
}

完整源码:

#pragma once
#define LIBVLC_USE_PTHREAD_CANCEL 1
#include <QtWidgets/QWidget>
#include "ui_showWidget.h"
#include <QMenu>
#include <QActionGroup>
#include <vlc/vlc.h>#include <QDebug>
#include <QFileDialog>
#include <QThread>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QPainter>
#include "TopWidget.h"enum Rate
{Rate2X,Rate1_5X,Rate1_25X,Rate1_0X,Rate0_75X,Rate0_5X
};class showWidget : public QWidget
{Q_OBJECTpublic:showWidget(QWidget *parent = nullptr);~showWidget();protected:virtual void mouseDoubleClickEvent(QMouseEvent *event);virtual void keyPressEvent(QKeyEvent *event);virtual bool eventFilter(QObject *watched, QEvent *event);virtual void paintEvent(QPaintEvent *event);virtual void moveEvent(QMoveEvent *event);private slots:void slotOpenFile();void slotPlay();void slotPause();void slotStop();void slotValueChanged(int value);void slotCurrentIndexChanged(int index);void slotSnap();private://事件处理回调static void vlcEvents(const libvlc_event_t *ev, void *param);private:Ui::showWidgetClass ui;private:libvlc_instance_t *vlc_base = nullptr;libvlc_media_t *vlc_media = nullptr;libvlc_media_player_t *vlc_mediaPlayer = nullptr;QList<float> m_lstRate;TopWidget *m_widget = nullptr;
};#include "showWidget.h"
#include <QTimer>
#include <QTime>
#include <QFileDialog>#pragma execution_character_set("utf-8")showWidget::showWidget(QWidget *parent): QWidget(parent)
{ui.setupUi(this);m_widget = new TopWidget(this);m_widget->setStyleSheet(QString("background-color: rgba(255, 0, 0, 0%);"));m_widget->show();this->setWindowTitle("视频播放器");ui.cbxRate->setCurrentIndex(Rate1_0X);m_lstRate << 2.0 << 1.5 << 1.25 << 1.0 << 0.75 << 0.5;vlc_base = libvlc_new(0, NULL);ui.btnOpen->setFocusPolicy(Qt::NoFocus);ui.btnPlay->setFocusPolicy(Qt::NoFocus);ui.btnPause->setFocusPolicy(Qt::NoFocus);ui.btnStop->setFocusPolicy(Qt::NoFocus);ui.hSliderVolumn->setFocusPolicy(Qt::NoFocus);ui.cbxRate->setFocusPolicy(Qt::NoFocus);ui.horizontalSlider->installEventFilter(this);connect(ui.btnOpen, &QPushButton::clicked, this, &showWidget::slotOpenFile);connect(ui.btnPlay, &QPushButton::clicked, this, &showWidget::slotPlay);connect(ui.btnPause, &QPushButton::clicked, this, &showWidget::slotPause);connect(ui.btnStop, &QPushButton::clicked, this, &showWidget::slotStop);connect(ui.btnSnap, &QPushButton::clicked, this, &showWidget::slotSnap);connect(ui.hSliderVolumn, &QSlider::valueChanged, this, &showWidget::slotValueChanged);connect(ui.cbxRate,SIGNAL(currentIndexChanged(int)), this, SLOT(slotCurrentIndexChanged(int)));
}showWidget::~showWidget()
{libvlc_release(vlc_base); //减少libvlc实例的引用计数,并销毁
}void showWidget::mouseDoubleClickEvent(QMouseEvent *event)
{if (this->isFullScreen()){this->showNormal();}else{this->showFullScreen();}
}void showWidget::keyPressEvent(QKeyEvent *event)
{if (!vlc_mediaPlayer)return;int value = ui.hSliderVolumn->value();if (event->key() == Qt::Key_W)	//添加音量{qDebug() << "up";slotValueChanged(value+10);}else if (event->key() == Qt::Key_S)	//减小音量{slotValueChanged(value - 10);}else if (event->key() == Qt::Key_Space){if (vlc_mediaPlayer && libvlc_media_player_get_state(vlc_mediaPlayer) == libvlc_Playing){libvlc_media_player_pause(vlc_mediaPlayer);}else if (vlc_mediaPlayer && libvlc_media_player_get_state(vlc_mediaPlayer) == libvlc_Paused){libvlc_media_player_play(vlc_mediaPlayer);}}
}bool showWidget::eventFilter(QObject *watched, QEvent *event)
{if (watched == ui.horizontalSlider) {if (event->type() == QEvent::MouseButtonPress) {if (!vlc_mediaPlayer)return false;QMouseEvent *mouse = static_cast<QMouseEvent*>(event);libvlc_time_t totalLen = libvlc_media_player_get_length(vlc_mediaPlayer);QPoint pos = mouse->pos();libvlc_time_t time = 0;time = (double)pos.x() / ui.horizontalSlider->width() * totalLen;libvlc_media_player_set_time(vlc_mediaPlayer, time);return true;}else {return false;}}else {// pass the event on to the parent classreturn QWidget::eventFilter(watched, event);}
}void showWidget::paintEvent(QPaintEvent *event)
{QStyleOption opt;opt.initFrom(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式QPoint pos_form = ui.widgetShow->mapToGlobal(ui.widgetShow->pos());m_widget->move(pos_form);m_widget->setGeometry(pos_form.x(), pos_form.y(), ui.widgetShow->width(), ui.widgetShow->height());
}void showWidget::moveEvent(QMoveEvent *event)
{QPoint pos_form = ui.widgetShow->mapToGlobal(ui.widgetShow->pos());m_widget->move(pos_form);m_widget->setGeometry(pos_form.x(), pos_form.y(), ui.widgetShow->width(), ui.widgetShow->height());
}void showWidget::slotOpenFile()
{/*选择文件*/QString filename = QFileDialog::getOpenFileName(this, "选择打开的文件", "D:/", tr("*.*"));std::replace(filename.begin(), filename.end(), QChar('/'), QChar('\\'));vlc_media = libvlc_media_new_path(vlc_base, filename.toUtf8().data());if (!vlc_media) {return;}// 创建libvlc实例和媒体播放器vlc_mediaPlayer = libvlc_media_player_new_from_media(vlc_media);if (!vlc_mediaPlayer) {return;}// 等待元数据加载完成libvlc_media_parse(vlc_media);libvlc_video_set_mouse_input(vlc_mediaPlayer, 0);libvlc_video_set_key_input(vlc_mediaPlayer, 0);// 获取各种元数据const char *title = libvlc_media_get_meta(vlc_media, libvlc_meta_Title);const char *artist = libvlc_media_get_meta(vlc_media, libvlc_meta_Artist);const char *album = libvlc_media_get_meta(vlc_media, libvlc_meta_Album);const char *url = libvlc_media_get_meta(vlc_media, libvlc_meta_URL);const char *date = libvlc_media_get_meta(vlc_media, libvlc_meta_Date);const char *lang = libvlc_media_get_meta(vlc_media, libvlc_meta_Language);int duration = libvlc_media_get_duration(vlc_media);  // 获取时长(单位:毫秒)qDebug("Title: %s", title ? title : "N/A");qDebug("Artist: %s", artist ? artist : "N/A");qDebug("Album: %s", album ? album : "N/A");qDebug("Duration: %d ms", duration);qDebug("url: %s", url ? url : "N/A");qDebug("date: %s", date ? date : "N/A");qDebug("lang: %s", lang ? lang : "N/A");libvlc_media_track_t **tracks;int track_count = libvlc_media_tracks_get(vlc_media,&tracks);for (unsigned i = 0; i < track_count; i++) {libvlc_media_track_t* track = tracks[i];// 显示轨道信息printf("Track #%u: %s\n", i, track->psz_description);// 这里可以获取到每一个轨道的信息,比如轨道类型 track->i_type// 可能是 libvlc_track_video, libvlc_track_audio 或者 libvlc_track_text (字幕)if (track->i_type == libvlc_track_video) {// 处理视频轨道信息qDebug("width = %d",track->video->i_width);qDebug("height = %d", track->video->i_height);qDebug("rate_num = %d", track->video->i_frame_rate_num);qDebug("rate_den = %d", track->video->i_frame_rate_den);}else if (track->i_type == libvlc_track_audio) {// 处理音频轨道信息qDebug("channels = %d", track->audio->i_channels);qDebug("rate = %d", track->audio->i_rate);}else if (track->i_type == libvlc_track_text) {// 处理字幕轨道信息qDebug("psz_encoding = %s", track->subtitle->psz_encoding);}}//获取事件管理器libvlc_event_manager_t *em = libvlc_media_player_event_manager(vlc_mediaPlayer);// 注册事件监听器libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerEndReached, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerStopped, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerPlaying, vlcEvents, this);libvlc_event_attach(em, libvlc_MediaPlayerPaused, vlcEvents, this);libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId());QTimer::singleShot(1000, this, &showWidget::slotPlay);}void showWidget::slotPlay()
{if (vlc_mediaPlayer)libvlc_media_player_play(vlc_mediaPlayer);
}void showWidget::slotPause()
{if (vlc_mediaPlayer)libvlc_media_player_pause(vlc_mediaPlayer);
}void showWidget::slotStop()
{if (vlc_mediaPlayer)libvlc_media_player_stop(vlc_mediaPlayer);
}void showWidget::slotValueChanged(int value)
{if (vlc_mediaPlayer)libvlc_audio_set_volume(vlc_mediaPlayer, value);
}void showWidget::slotCurrentIndexChanged(int index)
{if (vlc_mediaPlayer)libvlc_media_player_set_rate(vlc_mediaPlayer, m_lstRate[index]);
}void showWidget::slotSnap()
{if (vlc_mediaPlayer){QString path = "./snap.png";libvlc_video_take_snapshot(vlc_mediaPlayer, 0, path.toUtf8().data(), 0, 0);}
}//事件回调
void showWidget::vlcEvents(const libvlc_event_t *ev, void *param)
{showWidget *w = (showWidget*)param;//处理不同的事件switch (ev->type) {case libvlc_MediaPlayerTimeChanged:{//qDebug() << "VLC媒体播放器时间已更改";qint64 len = libvlc_media_player_get_time(w->vlc_mediaPlayer);libvlc_time_t lenSec = len / 1000;libvlc_time_t totalLen = libvlc_media_player_get_length(w->vlc_mediaPlayer);libvlc_time_t totalLenSec = totalLen / 1000;int thh, tmm, tss;thh = lenSec / 3600;tmm = (lenSec % 3600) / 60;tss = (lenSec % 60);QTime time(thh, tmm, tss);w->ui.lbCurTime->setText(time.toString("hh:mm:ss"));thh = totalLenSec / 3600;tmm = (totalLenSec % 3600) / 60;tss = (totalLenSec % 60);QTime TotalTime(thh, tmm, tss);w->ui.lbTotalTime->setText(TotalTime.toString("hh:mm:ss"));double pos = (double)lenSec / totalLenSec * 100;w->ui.horizontalSlider->setValue(pos);}break;case libvlc_MediaPlayerEndReached:qDebug() << "VLC播放完毕.";break;case libvlc_MediaPlayerStopped:qDebug() << "VLC停止播放";break;case libvlc_MediaPlayerPlaying:qDebug() << "VLC开始播放";break;case libvlc_MediaPlayerPaused:qDebug() << "VLC暂停播放";break;}
}

更多参考:

Qt+FFmpeg+opengl从零制作视频播放器-1.项目介绍_qt opengl视频播放器-CSDN博客

libVLC 提取视频帧使用OpenGL渲染-CSDN博客

QT UDP通信(单播、广播、组播)-CSDN博客

QCharts -1.概述-CSDN博客

相关文章:

libVLC 视频窗口上叠加透明窗口

很多时候&#xff0c;我们需要在界面上画一些三角形、文字等之类的东西&#xff0c;我们之需要重写paintEvent方法&#xff0c;比如像这样 void Widget::paintEvent(QPaintEvent *event) 以下就是重写的代码。 void Widget::paintEvent(QPaintEvent *event) {//创建QPainte…...

MySQL基础入门上篇

MySQL基础 介绍 mysql -uroot -p -h127.0.0.1 -P3306项目设计 具备数据库一定的设计能力和操作数据的能力。 数据库设计DDL 定义 操作 显示所有数据库 show databases;创建数据库 create database db02;数据库名唯一&#xff0c;不能重复。 查询是否创建成功 加入一些…...

Docker搭建FFmpeg

FFmpeg 是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的完整解决方案。FFmpeg 包含了领先的音视频编解码库libavcodec&#xff0c;可以用于各种视频格式的转换。 应用场景包括&#xff1a; 视频转换&#xff1a;把视频从一种格式转换成另一种格式。视…...

Hudi-ubuntu环境搭建

hudi-ubuntu环境搭建 运行 1.编译Hudi #1.把maven安装包上传到服务器 # 官网下载安装包 https://archive.apache.org/dist/maven/maven-3/ scp -r D:\Users\zh\Desktop\Hudi\compressedPackage\apache-maven-3.6.3-bin.tar.gz zhangheng10.8.4.212:/home/zhangheng/hudi/com…...

Hive进阶Day05

一、HDFS分布式文件存储系统 1-1 HDFS的存储机制 按块&#xff08;block&#xff09;存储 hdfs在对文件数据进行存储时&#xff0c;默认是按照128M(包含)大小进行文件数据拆分&#xff0c;将不同拆分的块数据存储在不同datanode服务器上 拆分后的块数据会被分别存储在不同的服…...

ssh爆破服务器的ip-疑似肉鸡

最近发现自己的ssh一直有一些人企图使用ssh暴力破解的方式进行密码破解.就查看了一下,真是网络安全太可怕了. 大家自己的服务器密码还是要设置好,管好,做好最基本的安全措施,不然最后只能沦为肉鸡. ssh登陆日志可以在/var/log下看到,ubuntu的话为auth.log,centos为secure文件 查…...

4.JVM八股

JVM空间划分 线程共享和线程私有 1.7&#xff1a; 线程共享&#xff1a; 堆、方法区 线程私有&#xff1a; 虚拟机栈、本地方法栈、程序计数器 本地内存 1.8&#xff1a; 线程共享&#xff1a; 堆 线程私有&#xff1a; 老三样 本地内存&#xff0c;元空间 程序计数器 …...

内网渗透系列-mimikatz的使用以及后门植入

内网渗透系列-mimikatz的使用以及后门植入 文章目录 内网渗透系列-mimikatz的使用以及后门植入前言mimikatz的使用后门植入 msf永久后门植入 &#xff08;1&#xff09;Meterpreter后门&#xff1a;Metsvc&#xff08;2&#xff09;Meterpreter后门&#xff1a;Persistence NC后…...

5G网络开通与调测ipv4

要求如下&#xff1a; 1. 勘站规划 1. 【重】首先观察NR频点&#xff0c;完成设备选型 2645--选择N41 3455--选择N78 4725--选择N79 设备选型如下&#xff1a;观察AAU的通道数&#xff0c;最大发射功率&#xff1b;选择N41的选型频段也要选41 2. …...

Spark开窗函数之ROW

Spark 1.5.x版本以后,在Spark SQL和DataFrame中引入了开窗函数,其中比较常用的开窗函数就是row_number 该函数的作用是根据表中字段进行分组,然后根据表中的字段排序;其实就是根据其排序顺序,给组中的每条记录添 加一个序号;且每组的序号都是从1开始,可利用它的这个特性进行分组…...

双向链表的实现(详解)

目录 前言初始化双向链表的结构为双向链表的节点开辟空间头插尾插打印链表尾删头删查找指定位置之后的插入删除pos节点销毁双向链表 前言 链表的分类&#xff1a; 带头 不带头 单向 双向 循环 不循环 一共有 (2 * 2 * 2) 种链表 带头指的是&#xff1a;带有哨兵位节点 哨兵位&a…...

SpringBoot项目中如何使用校验工具

用到hutool提供的校验方法与java提供的校验方法 1. 声明数据 String str "123" String regex "^123456$" Boolean is1_6 mismatch(str, regex);2. 定义校验方法 // 校验是否不符合正则格式 private static boolean mismatch(String str, String rege…...

AI预测小分子与蛋白的相关特征: MegaMolBART, MoFlow,ESM-1, ESM-2

1、小分子:MegaMolBART, MoFlow 1)MegaMolBART https://github.com/NVIDIA/MegaMolBART 基于 SMILES 的小分子药物发现与化学信息学深度学习模型。 2)MoFlow https://github.com/calvin-zcx/moflow 用flow流方式分子生成 2、蛋白质:ESM-1, ESM-2 https://github.com/fa…...

基于深度学习的花卉检测系统(含PyQt界面)

基于深度学习的花卉检测系统&#xff08;含PyQt界面&#xff09; 前言一、数据集1.1 数据集介绍1.2 数据预处理 二、模型搭建三、训练与测试3.1 模型训练3.2 模型测试 四、PyQt界面实现参考资料 前言 本项目是基于swin_transformer深度学习网络模型的花卉检测系统&#xff0c;…...

深度学习图像处理基础工具——opencv 实战信用卡数字识别

任务 信用卡数字识别 穿插之前学的知识点 形态学操作 模板匹配 等 总体流程与方法 1.有一个模板 2 用轮廓检测把模板中数字拿出来 外接矩形&#xff08;模板和输入图像的大小要一致 &#xff09;3 一系列预处理操作 问题的解决思路 1.分析准备&#xff1a;准备模板&#…...

【HBase】HBase高性能架构:如何保证大规模数据的高可用性

HBase高性能原理 HBase 能够提供高性能的数据处理能力&#xff0c;主要得益于其设计和架构的几个关键方面。这些设计特点使得 HBase 特别适合于大规模、分布式的环境中进行高效的数据读写操作。以下是 HBase 高性能的主要原因&#xff1a; 1. 基于列的存储 HBase 是一个列式…...

JAVA基础两个项目案例代码

1.JAVA使用ArrayList上架菜品案例 视频参考链接 创建一个Food.java类 package org.example;// 菜品类 public class Food {private String name; // 菜品名private double price; // 价格private String desc; // 菜品描述public Food() {}public Food(String name, Double …...

asp.net core 网页接入微信扫码登录

创建微信开放平台账号&#xff0c;然后创建网页应用 获取appid和appsecret 前端使用的vue&#xff0c;安装插件vue-wxlogin 调用代码 <wxlogin :appid"appId" :scope"scope" :redirect_uri"redirect_uri"></wxlogin> <scri…...

【板栗糖GIS】如何给微软拼音输入法加上小鹤双拼

【板栗糖GIS】如何给微软拼音输入法加上小鹤双拼 用过在注册表里新建的方法&#xff0c;结果弄完没有出现小鹤双拼方案&#xff0c;想到了自己写reg表 目录 1. 新建一个txt文件 2. 把.txt的后缀名改成.reg&#xff0c;双击运行 3. 在设置中找到微软输入法-常规 1. 新建一个…...

如何解决微信小程序无法使用css3过度属性transition

由于微信小程序不支持CSS3过度属性transition,所以我们需要利用微信小程序api进行画面过度的展示 首先是官方示例: wxml: <view animation="{{animationData}}" style="background:red;height:100rpx;width:100rpx"></view> js: Page(…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...

GraphRAG优化新思路-开源的ROGRAG框架

目前的如微软开源的GraphRAG的工作流程都较为复杂&#xff0c;难以孤立地评估各个组件的贡献&#xff0c;传统的检索方法在处理复杂推理任务时可能不够有效&#xff0c;特别是在需要理解实体间关系或多跳知识的情况下。先说结论&#xff0c;看完后感觉这个框架性能上不会比Grap…...

Spring Boot 与 Kafka 的深度集成实践(二)

3. 生产者实现 3.1 生产者配置 在 Spring Boot 项目中&#xff0c;配置 Kafka 生产者主要是配置生产者工厂&#xff08;ProducerFactory&#xff09;和 KafkaTemplate 。生产者工厂负责创建 Kafka 生产者实例&#xff0c;而 KafkaTemplate 则是用于发送消息的核心组件&#x…...

Gitlab + Jenkins 实现 CICD

CICD 是持续集成&#xff08;Continuous Integration, CI&#xff09;和持续交付/部署&#xff08;Continuous Delivery/Deployment, CD&#xff09;的缩写&#xff0c;是现代软件开发中的一种自动化流程实践。下面介绍 Web 项目如何在代码提交到 Gitlab 后&#xff0c;自动发布…...

NoSQL——Redis配置与优化

目录 关系型&非关系型数据库 一、核心原理对比‌ ‌二、核心特性对比‌ ‌三、关键区别剖析‌ ‌四、典型产品示例‌ ‌总结‌ Redis Redis核心原理 核心特性 技术意义 配置文件解析 1. 基础配置 2. 持久化配置 3. 内存管理 4. 高可用配置 5. 性能调优 6.…...

Digital IC Design Flow

Flow介绍 1.设计规格 架构师根据市场需求制作算法模型(Algorithm emulation)及芯片架构(Chip architecture),确定芯片设计规格书(Chip design specification) 原型验证 原型验证(Prototype Validation)通常位于产品开发流程的前期阶段,主要是在设计和开发的初步阶…...