Python pyside6 设置的一个《广告图片生成器》

一、图:

二、说明书:

 

广告图片生成器使用说明

软件功能

这是一个用于生成广告图片的工具,可以快速制作包含产品图片和文字的广告图片。

主要特点

  1. 自定义广告尺寸(默认620×420像素)

  2. 智能去除产品图片背景

  3. 自动排版(左文右图布局)

  4. 自动文字换行

  5. 可自定义颜色和文字

使用步骤

1. 基本设置
  • 广告尺寸: 可设置宽度(300-1920px)和高度(200-1080px)

  • 广告文本: 在文本框中输入需要显示的广告文字

  • 输出路径: 默认为"D:\PIC",可通过"选择路径"按钮更改

2. 图片处理
  • 选择图片: 点击"选择产品图片"按钮选择要使用的图片

  • 去背景功能:

    • 可通过复选框开启/关闭去背景功能

    • 使用滑动条调整去背景阈值(180-250)

    • 点击"预览去背景"查看效果

3. 样式设置
  • 背景颜色: 点击"选择背景颜色"按钮自定义背景色

  • 文字颜色: 点击"选择文字颜色"按钮自定义文字颜色

4. 生成和保存
  • 生成预览: 所有设置完成后会自动预览效果

  • 生成图片: 点击"生成广告图片"按钮生成最终图片

  • 保存图片: 点击"保存图片"按钮将图片保存到指定位置

布局说明

  • 文字区域占图片宽度的1/3,位于左侧

  • 产品图片占图片宽度的2/3,位于右侧

  • 文字和图片都会自动居中对齐

注意事项

  1. 去背景功能最适合处理白色或浅色背景的图片

  2. 文字会根据区域大小自动换行

  3. 图片会自动等比例缩放以适应区域

  4. 每次生成的图片会自动以时间戳命名

系统要求

  • 操作系统:Windows

  • Python环境

  • 需要安装的库:

    • PySide6

    • Pillow (PIL)

快捷操作

  • 可以直接拖拽图片到软件窗口

  • 使用滑动条快速调整去背景效果

  • 实时预览所有修改效果

代码: 

from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                                 QHBoxLayout, QPushButton, QLabel, QLineEdit, QFileDialog,
                                 QSpinBox, QColorDialog, QTextEdit, QSlider, QDialog, QCheckBox,
                                 QScrollArea)
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap, QImage
from PIL import Image, ImageDraw, ImageFont
import sys
import os
import time

class PreviewDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("去背景预览")
        self.setModal(False)  # 非模态对话框
        layout = QVBoxLayout(self)
        
        # 预览标签
        self.preview_label = QLabel()
        self.preview_label.setFixedSize(300, 300)
        self.preview_label.setStyleSheet("QLabel { background-color: #808080; }")  # 灰色背景
        self.preview_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.preview_label)
        
        # 关闭按钮
        close_btn = QPushButton("关闭预览")
        close_btn.clicked.connect(self.close)
        layout.addWidget(close_btn)

class HelpDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("使用说明")
        self.setGeometry(150, 150, 600, 400)
        
        layout = QVBoxLayout(self)
        
        # 创建滚动区域
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        layout.addWidget(scroll)
        
        # 创建内容容器
        content = QWidget()
        scroll.setWidget(content)
        content_layout = QVBoxLayout(content)
        
        # 读取说明文件
        try:
            with open("readme.md", "r", encoding="utf-8") as f:
                help_text = f.read()
        except:
            help_text = "找不到说明文件"
        
        # 创建文本显示
        text_display = QTextEdit()
        text_display.setReadOnly(True)
        text_display.setMarkdown(help_text)
        content_layout.addWidget(text_display)
        
        # 关闭按钮
        close_btn = QPushButton("关闭")
        close_btn.clicked.connect(self.close)
        layout.addWidget(close_btn)

class AdGenerator(QMainWindow):
    def __init__(self):
        super().__init__()
        # 设置默认输出路径
        self.output_dir = "D:\\PIC"
        # 确保输出目录存在
        if not os.path.exists(self.output_dir):
            try:
                os.makedirs(self.output_dir)
            except Exception as e:
                print(f"创建输出目录失败: {str(e)}")
                self.output_dir = os.getcwd()  # 如果创建失败,使用当前目录
        
        self.initUI()
        self.product_image_path = None
        self.bg_color = (30, 30, 30)
        self.text_color = (255, 255, 255)
        self.threshold = 220  # 默认阈值
        self.preview_dialog = None
        self.current_image = None
        self.remove_bg_enabled = True  # 默认启用去背景
        self.ad_width = 620   # 默认宽度
        self.ad_height = 420  # 默认高度
        self.help_dialog = None
        
    def initUI(self):
        self.setWindowTitle('广告图片生成器')
        self.setGeometry(100, 100, 800, 600)
        
        # 创建中心部件和布局
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        # 创建预览标签
        self.preview_label = QLabel()
        self.preview_label.setFixedSize(620, 420)
        self.preview_label.setStyleSheet("QLabel { background-color: #1e1e1e; }")
        self.preview_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.preview_label)
        
        # 创建控制面板
        controls_layout = QHBoxLayout()
        
        # 左侧控制面板
        left_panel = QVBoxLayout()
        
        # 添加尺寸设置
        size_layout = QHBoxLayout()
        size_label = QLabel("广告尺寸:")
        self.width_input = QSpinBox()
        self.width_input.setRange(300, 1920)  # 设置合理的范围
        self.width_input.setValue(620)
        self.width_input.setSuffix(" px")
        self.width_input.valueChanged.connect(self.size_changed)
        
        size_x_label = QLabel("×")
        
        self.height_input = QSpinBox()
        self.height_input.setRange(200, 1080)
        self.height_input.setValue(420)
        self.height_input.setSuffix(" px")
        self.height_input.valueChanged.connect(self.size_changed)
        
        size_layout.addWidget(size_label)
        size_layout.addWidget(self.width_input)
        size_layout.addWidget(size_x_label)
        size_layout.addWidget(self.height_input)
        left_panel.addLayout(size_layout)
        
        # 文本输入
        text_layout = QVBoxLayout()
        text_label = QLabel("广告文本:")
        self.text_input = QTextEdit()
        self.text_input.setPlaceholderText("输入广告文本")
        self.text_input.setMaximumHeight(100)
        text_layout.addWidget(text_label)
        text_layout.addWidget(self.text_input)
        left_panel.addLayout(text_layout)
        
        # 图片选择按钮
        self.select_image_btn = QPushButton("选择产品图片")
        self.select_image_btn.clicked.connect(self.select_image)
        left_panel.addWidget(self.select_image_btn)
        
        # 背景颜色选择
        self.bg_color_btn = QPushButton("选择背景颜色")
        self.bg_color_btn.clicked.connect(self.select_bg_color)
        left_panel.addWidget(self.bg_color_btn)
        
        # 文字颜色选择
        self.text_color_btn = QPushButton("选择文字颜色")
        self.text_color_btn.clicked.connect(self.select_text_color)
        left_panel.addWidget(self.text_color_btn)
        
        # 阈值选择
        threshold_layout = QHBoxLayout()
        
        # 添加去背景开关
        self.remove_bg_checkbox = QCheckBox("启用去背景")
        self.remove_bg_checkbox.setChecked(True)
        self.remove_bg_checkbox.stateChanged.connect(self.toggle_remove_bg)
        left_panel.addWidget(self.remove_bg_checkbox)
        
        threshold_label = QLabel("去背景阈值:")
        self.threshold_value_label = QLabel("220")
        self.threshold_slider = QSlider(Qt.Horizontal)
        self.threshold_slider.setMinimum(180)
        self.threshold_slider.setMaximum(250)
        self.threshold_slider.setValue(220)
        self.threshold_slider.valueChanged.connect(self.threshold_changed)
        
        # 添加预览按钮
        self.preview_btn = QPushButton("预览去背景")
        self.preview_btn.clicked.connect(self.show_preview)
        
        threshold_layout.addWidget(threshold_label)
        threshold_layout.addWidget(self.threshold_slider)
        threshold_layout.addWidget(self.threshold_value_label)
        threshold_layout.addWidget(self.preview_btn)
        left_panel.addLayout(threshold_layout)
        
        controls_layout.addLayout(left_panel)
        
        # 右侧控制面板
        right_panel = QVBoxLayout()
        
        # 添加输出路径设置
        output_layout = QHBoxLayout()
        output_label = QLabel("输出路径:")
        self.output_path_label = QLabel(self.output_dir)
        self.output_path_label.setStyleSheet("padding: 5px; background-color: #f0f0f0; border: 1px solid #ccc;")
        self.output_path_btn = QPushButton("选择路径")
        self.output_path_btn.clicked.connect(self.select_output_path)
        
        output_layout.addWidget(output_label)
        output_layout.addWidget(self.output_path_label, stretch=1)
        output_layout.addWidget(self.output_path_btn)
        right_panel.addLayout(output_layout)
        
        # 生成按钮
        self.generate_btn = QPushButton("生成广告图片")
        self.generate_btn.clicked.connect(self.generate_ad)
        right_panel.addWidget(self.generate_btn)
        
        # 保存按钮
        self.save_btn = QPushButton("保存图片")
        self.save_btn.clicked.connect(self.save_image)
        right_panel.addWidget(self.save_btn)
        
        # 添加帮助按钮
        self.help_btn = QPushButton("使用说明")
        self.help_btn.clicked.connect(self.show_help)
        right_panel.addWidget(self.help_btn)
        
        controls_layout.addLayout(right_panel)
        layout.addLayout(controls_layout)
    
    def select_image(self):
        file_name, _ = QFileDialog.getOpenFileName(
            self,
            "选择产品图片",
            "",
            "图片文件 (*.png *.jpg *.jpeg *.bmp)"
        )
        if file_name:
            self.product_image_path = file_name
            self.preview_image()
    
    def select_bg_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.bg_color = (color.red(), color.green(), color.blue())
            self.preview_image()
    
    def select_text_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.text_color = (color.red(), color.green(), color.blue())
            self.preview_image()
    
    def threshold_changed(self):
        self.threshold = self.threshold_slider.value()
        self.threshold_value_label.setText(str(self.threshold))
        if self.preview_dialog and self.preview_dialog.isVisible():
            self.show_preview()
        if self.product_image_path:
            self.preview_image()
    
    def toggle_remove_bg(self, state):
        self.remove_bg_enabled = bool(state)
        # 更新阈值控件的启用状态
        self.threshold_slider.setEnabled(self.remove_bg_enabled)
        self.threshold_value_label.setEnabled(self.remove_bg_enabled)
        self.preview_btn.setEnabled(self.remove_bg_enabled)
        # 如果有图片,立即更新预览
        if self.product_image_path:
            self.preview_image()
    
    def remove_background(self, image):
        if not self.remove_bg_enabled:
            return image.convert('RGBA')
            
        # 转换图片为RGBA模式
        image = image.convert('RGBA')
        data = image.getdata()
        new_data = []
        
        for item in data:
            # 如果像素接近白色,则设置为透明
            if item[0] >= self.threshold and item[1] >= self.threshold and item[2] >= self.threshold:
                new_data.append((255, 255, 255, 0))
            else:
                new_data.append(item)
        
        image.putdata(new_data)
        return image
    
    def show_preview(self):
        if not self.product_image_path:
            return
            
        if not self.preview_dialog:
            self.preview_dialog = PreviewDialog(self)
        
        try:
            # 加载原图并去背景
            img = Image.open(self.product_image_path)
            img = self.remove_background(img)
            
            # 调整图片大小以适应预览窗口
            preview_size = 300
            img.thumbnail((preview_size, preview_size), Image.Resampling.LANCZOS)
            
            # 转换为QImage
            img_data = img.convert("RGBA").tobytes("raw", "RGBA")
            qimg = QImage(img_data, img.size[0], img.size[1], QImage.Format_RGBA8888)
            
            # 显示在预览窗口中
            pixmap = QPixmap.fromImage(qimg)
            self.preview_dialog.preview_label.setPixmap(pixmap)
            
            # 显示预览窗口
            self.preview_dialog.show()
            
        except Exception as e:
            print(f"预览出错: {str(e)}")
    
    def preview_image(self):
        self.current_image = self.generate_ad(preview=True)
        if self.current_image:
            pixmap = QPixmap.fromImage(self.current_image)
            self.preview_label.setPixmap(pixmap.scaled(
                self.preview_label.size(),
                Qt.KeepAspectRatio,
                Qt.SmoothTransformation
            ))
    
    def generate_ad(self, preview=False):
        width, height = self.ad_width, self.ad_height  # 使用设置的尺寸
        image = Image.new('RGB', (width, height), self.bg_color)
        draw = ImageDraw.Draw(image)
        
        if self.product_image_path and os.path.exists(self.product_image_path):
            try:
                product_img = Image.open(self.product_image_path)
                product_img = self.remove_background(product_img)
                
                # 严格计算2/3宽度
                right_width = int(width * (2/3))  # 确保宽度正好是2/3
                product_height = int((right_width * product_img.height) / product_img.width)
                
                # 如果高度超出,按高度缩放,但保持宽度不超过2/3
                if product_height > height:
                    product_height = height
                    calc_width = int((product_height * product_img.width) / product_img.height)
                    right_width = min(calc_width, right_width)  # 取较小值确保不超过2/3
                
                product_img = product_img.resize((right_width, product_height))
                
                # 计算粘贴位置(右侧居中)
                paste_x = width - right_width
                paste_y = (height - product_height) // 2
                
                # 粘贴产品图片
                image.paste(product_img, (paste_x, paste_y), product_img)
            except Exception as e:
                print(f"处理图片时出错: {str(e)}")
        
        try:
            # 根据广告尺寸调整字体大小
            font_size = min(32, int(height / 13))  # 动态计算合适的字体大小
            font = ImageFont.truetype("msyh.ttc", font_size)
        except:
            font = ImageFont.load_default()
        
        # 文本区域(使用左侧1/3的空间)
        text_area_width = int(width * (1/3))  # 确保文本区域是1/3
        text = self.text_input.toPlainText()
        
        # 改进的文本换行处理
        lines = []
        current_line = ""
        
        # 按字符分割文本(考虑中文字符)
        for char in text:
            test_line = current_line + char
            text_bbox = draw.textbbox((0, 0), test_line, font=font)
            if text_bbox[2] - text_bbox[0] > text_area_width - 40:  # 留出左右边距
                if current_line:
                    lines.append(current_line)
                    current_line = char
                else:
                    lines.append(char)
                    current_line = ""
            else:
                current_line += char
        
        if current_line:
            lines.append(current_line)
        
        # 计算文本总高度
        line_height = font.size + 8
        total_text_height = len(lines) * line_height
        
        # 绘制文本(左侧居中)
        start_y = (height - total_text_height) // 2
        for i, line in enumerate(lines):
            text_bbox = draw.textbbox((0, 0), line, font=font)
            text_width = text_bbox[2] - text_bbox[0]
            x = 30  # 增加左边距
            y = start_y + i * line_height
            draw.text((x, y), line, font=font, fill=self.text_color)
        
        if preview:
            # 转换为QImage用于预览
            data = image.tobytes("raw", "RGB")
            qimage = QImage(data, image.size[0], image.size[1], QImage.Format_RGB888)
            return qimage
        else:
            # 生成文件名(使用时间戳)
            timestamp = time.strftime("%Y%m%d_%H%M%S")
            output_path = os.path.join(self.output_dir, f"ad_{timestamp}.png")
            
            # 创建图片
            width, height = self.ad_width, self.ad_height
            image = Image.new('RGB', (width, height), self.bg_color)
            draw = ImageDraw.Draw(image)
            
            if self.product_image_path and os.path.exists(self.product_image_path):
                try:
                    product_img = Image.open(self.product_image_path)
                    product_img = self.remove_background(product_img)
                    
                    # 严格计算2/3宽度
                    right_width = int(width * (2/3))  # 确保宽度正好是2/3
                    product_height = int((right_width * product_img.height) / product_img.width)
                    
                    # 如果高度超出,按高度缩放,但保持宽度不超过2/3
                    if product_height > height:
                        product_height = height
                        calc_width = int((product_height * product_img.width) / product_img.height)
                        right_width = min(calc_width, right_width)  # 取较小值确保不超过2/3
                    
                    product_img = product_img.resize((right_width, product_height))
                    
                    # 计算粘贴位置(右侧居中)
                    paste_x = width - right_width
                    paste_y = (height - product_height) // 2
                    
                    # 粘贴产品图片
                    image.paste(product_img, (paste_x, paste_y), product_img)
                except Exception as e:
                    print(f"处理图片时出错: {str(e)}")
            
            try:
                # 根据广告尺寸调整字体大小
                font_size = min(32, int(height / 13))  # 动态计算合适的字体大小
                font = ImageFont.truetype("msyh.ttc", font_size)
            except:
                font = ImageFont.load_default()
            
            # 文本区域(使用左侧1/3的空间)
            text_area_width = int(width * (1/3))  # 确保文本区域是1/3
            text = self.text_input.toPlainText()
            
            # 改进的文本换行处理
            lines = []
            current_line = ""
            
            # 按字符分割文本(考虑中文字符)
            for char in text:
                test_line = current_line + char
                text_bbox = draw.textbbox((0, 0), test_line, font=font)
                if text_bbox[2] - text_bbox[0] > text_area_width - 40:  # 留出左右边距
                    if current_line:
                        lines.append(current_line)
                        current_line = char
                    else:
                        lines.append(char)
                        current_line = ""
                else:
                    current_line += char
            
            if current_line:
                lines.append(current_line)
            
            # 计算文本总高度
            line_height = font.size + 8
            total_text_height = len(lines) * line_height
            
            # 绘制文本(左侧居中)
            start_y = (height - total_text_height) // 2
            for i, line in enumerate(lines):
                text_bbox = draw.textbbox((0, 0), line, font=font)
                text_width = text_bbox[2] - text_bbox[0]
                x = 30  # 增加左边距
                y = start_y + i * line_height
                draw.text((x, y), line, font=font, fill=self.text_color)
            
            # 保存图片
            try:
                image.save(output_path)
                print(f"图片已保存到: {output_path}")
                return output_path
            except Exception as e:
                print(f"保存图片失败: {str(e)}")
                return None
    
    def save_image(self):
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        default_name = f"ad_{timestamp}.png"
        file_name, _ = QFileDialog.getSaveFileName(
            self,
            "保存广告图片",
            os.path.join(self.output_dir, default_name),
            "PNG图片 (*.png)"
        )
        if file_name:
            if self.generate_ad():
                # 复制生成的图片到选择的位置
                latest_file = os.path.join(self.output_dir, default_name)
                if os.path.exists(latest_file):
                    Image.open(latest_file).save(file_name)
                    print(f"图片已保存到: {file_name}")
                else:
                    print("找不到生成的图片文件")
    
    def size_changed(self):
        # 更新尺寸
        self.ad_width = self.width_input.value()
        self.ad_height = self.height_input.value()
        
        # 更新预览标签大小
        self.preview_label.setFixedSize(self.ad_width, self.ad_height)
        
        # 如果有图片,重新生成预览
        if self.product_image_path:
            self.preview_image()
    
    def select_output_path(self):
        dir_path = QFileDialog.getExistingDirectory(
            self,
            "选择输出目录",
            self.output_dir,
            QFileDialog.ShowDirsOnly
        )
        if dir_path:
            self.output_dir = dir_path
            self.output_path_label.setText(self.output_dir)
    
    def show_help(self):
        if not self.help_dialog:
            self.help_dialog = HelpDialog(self)
        self.help_dialog.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = AdGenerator()
    window.show()
    sys.exit(app.exec())

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

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

相关文章

Spark基本介绍

一,Spark是什么 1.定义:Aache Spark是用于大规模数据处理的统一分析引擎。 二,Spark的发展 三,Spark的特点 高效性 计算速度快 提供了一个全新的数据结构RDD(弹性分布式数据集)。整个计算操作,…

Elasticsearch操作笔记版

文章目录 1.ES索引库操作(CRUD)1.mapping常见属性(前提)2.创建索引库3.查询,删除索引库4.修改索引库 2.ES文档操作(CRUD)1.新增文档2.查询、删除文档查询返回的数据解读: 3.修改文档 3.RestClient操作(索引库/文档)(CRUD)1.什么是RestClient2.需要考虑前…

EFEVD: Enhanced Feature Extraction for Smart Contract Vulnerability Detection

假设,攻击者在合约 Dao 内存放有 1 Ether 攻击者调用 withdraw 函数,提取 1 Ether; 函数执行到 require 之后, balances 之前时,6789-6789-6789- contract Dao {function withdraw() public {require(balances[msg.…

我的线代观-秩(向量,矩阵)

都说秩是线代中不可避免的一环,当然,它其中最重要的一环。 我在学习线代之后,也有这种感受,它有着一种很绕的感受。 1.矩阵中 在矩阵中,它的秩是怎么定义的呢。它常常与行列式扯上关系,我们拿三阶矩阵为例…

ES IK分词字典热更新

前言 在使用IK分词器的时候,发现官方默认的分词不满足我们的需求,那么有没有方法可以自定义字典呢? 官方提供了三种方式 一、ik本地文件读取方式 k插件本来已为用户提供自定义词典扩展功能,只要修改配给文件即可: …

基于Spring Boot的电影网站系统

一、技术架构 后端框架:Spring Boot,它提供了自动配置、简化依赖管理、内嵌式容器等特性,使得开发者可以快速搭建起一个功能完备的Web应用。 前端技术:可能采用Vue.js、JS、jQuery、Ajax等技术,结合Element UI等组件库…

C#运动控制系统:雷赛控制卡实用完整例子 C#雷赛开发快速入门 C#雷赛运动控制系统实战例子 C#快速开发雷赛控制卡

雷赛控制技术 DMC系列运动控制卡是一款新型的 PCI/PCIe 总线运动控制卡。可以控制多个步进电机或数字式伺服电机;适合于多轴点位运动、插补运动、轨迹规划、手轮控制、编码器位置检测、IO 控制、位置比较、位置锁存等功能的应用。 DMC3000 系列卡的运动控制函数库功…

android studio 写一个小计时器(版本二)

as版本&#xff1a;23.3.1patch2 例程&#xff1a;timer 在前一个版本的基本上改的&#xff0c;增加了继续的功能&#xff0c;实现方法稍微不同。 动画演示&#xff1a; activity_main.xml <?xml version"1.0" encoding"utf-8"?> <androidx…

python-leetcode-轮转数组

189. 轮转数组 - 力扣&#xff08;LeetCode&#xff09; class Solution:def rotate(self, nums: List[int], k: int) -> None:"""Do not return anything, modify nums in-place instead."""n len(nums)k % n # 如果 k 大于 n&#xff0c;…

亚马逊云科技 | Amazon Nova:智能技术新势力

在2024年亚马逊云科技re:invent大会上&#xff0c;Amazon Nova 系列自研生成式 AI 多模态模型重磅登场&#xff0c;新一代的AI产品-Amazon Nova&#xff0c;隶属于 Amazon Bedrock&#xff0c;一共发布6款大模型&#xff0c;精准切入不同领域&#xff0c;解锁多元业务可能&…

记录第一次跑YOLOV8做目标检测

今天是24年的最后一天&#xff0c;终于要向新世界开始破门了&#xff0c;开始深度学习&#xff0c;YOLO来敲门~ 最近做了一些皮肤检测的功能&#xff0c;在传统的处理中经历了反复挣扎&#xff0c;终于要上YOLO了。听过、看过&#xff0c;不如上手体会过~ 1、YOLO是什么&#x…

从授权校验看SpringBoot自动装配

背景 最近需要实现一个对于系统的授权检测功能&#xff0c;即当SpringBoot应用被启动时&#xff0c;需要当前设备是否具有有效的的授权许可信息&#xff0c;若无则直接退出应用。具体的实现方案请继续看下文。 环境 Ruoyi-Vue SpringBoot3 RuoYi-Vue: &#x1f389; 基于Spr…

【Unity】 HTFramework框架(五十七)通过Tag、Layer批量搜索物体

更新日期&#xff1a;2024年12月30日。 Github源码&#xff1a;[点我获取源码] Gitee源码&#xff1a;[点我获取源码] 索引 问题再现通过Tag搜索物体&#xff08;SearchByTag&#xff09;打开SearchByTag窗口搜索标记指定Tag的所有物体批量修改Tag搜索Undefined状态的所有物体 …

Unity2D无限地图的实现(简单好抄)

说明&#xff1a;本教程实现的是在2D游戏中玩家在游戏中上下左右移动的时候自动进行地图拼接的功能&#xff0c;如果你只想实现左右移动的无限地图&#xff0c;那么这篇博客也能起到一定参考作用。 思路 第一步&#xff1a; 创建一个10*10的2D游戏对象当做地图 第二步创建一个…

艾体宝方案丨全面提升API安全:AccuKnox 接口漏洞预防与修复

一、API 安全&#xff1a;现代企业的必修课 在现代技术生态中&#xff0c;应用程序编程接口&#xff08;API&#xff09;扮演着不可或缺的角色。从数据共享到跨平台集成&#xff0c;API 成为连接企业系统与外部服务的桥梁。然而&#xff0c;伴随云计算的普及与微服务架构的流行…

日期时间选择(设置禁用状态)

目录 1.element文档需要 2.禁用所有过去的时间 3.设置指定日期的禁用时间 <template><div class"block"><span class"demonstration">起始日期时刻为 12:00:00</span><el-date-pickerv-model"value1"type"dat…

SAP学习笔记 - 豆知识14 - Msg 番号 M7562 - 取引Type WL 对应的番号範囲中不存在2025年度 OMBT

这种类似的以前也写过&#xff0c;原因就是自动採番的番号没弄。 比如跨年了&#xff0c;那该新年度的番号范围没弄啊&#xff0c;就会出这种错误。 把番号范围给加一下就可以了。 1&#xff0c;现象 比如点 VL02N 出荷传票变更 画面&#xff0c;点 出库确认 就会出如下错误…

SpringBoot 集成 Activiti 7 工作流引擎

一. 版本信息 IntelliJ IDEA 2023.3.6JDK 17Activiti 7 二. IDEA依赖插件安装 安装BPM流程图插件&#xff0c;如果IDEA的版本超过2020,则不支持actiBPM插件。我的IDEA是2023版本我装的是 Activiti BPMN visualizer 插件。 在Plugins 搜索 Activiti BPMN visualizer 安装 创…

分布式版本管理工具——Git关联远程仓库(github+gitee)

Git远程仓库&#xff08;Github&#xff09;的基本使用 一、前言二、Git远程仓库介绍三、演示1. 关联github远程仓库2. 关联gitee&#xff08;码云&#xff09;远程仓库3. 重命名远程仓库名4. 移除远程仓库 四、结束语 一、前言 古之立大事者&#xff0c;不惟有超世之才&#x…

python-leetcode-删除有序数组中的重复项 II

80. 删除有序数组中的重复项 II - 力扣&#xff08;LeetCode&#xff09; class Solution:def removeDuplicates(self, nums: List[int]) -> int:n len(nums)if n < 2:return n # 如果长度小于等于 2&#xff0c;直接返回长度k 2 # 指针 k 指向下一个有效位置&#x…