Java GUI——网页浏览器开发

news2024/11/15 15:25:53

Java GUI——网页浏览器开发

前言:为了做java课设,学了一手Java GUI。感觉蛮有意思的,写写文章,做个视频记录一下。欢迎大家友善指出我的不足

网页浏览器开发录制视频,从头敲到尾

任务需求

界面需求

  • 菜单栏

    • 文件 【热键F】
      • 另存为 【热键A,快捷键CTRL+S】
      • 退出 【热键I,快捷键CTRL+E】
    • 编辑 【热键E】
      • 前进 【快捷键CTRL+Z】
      • 后退 【快捷键CTRL+D】
    • 视图 【热键V】
      • 全屏 【快捷键CTRL+U】
      • 查看源码 【热键C,快捷键CTRL+C】
      • 刷新 【快捷键CTRL+R】
  • 工具栏

    • 另存为
    • 后退
    • 前进
    • 查看源代码
    • 退出
  • 工具栏

    • label(地址)
    • 文本框
    • 转向按钮

功能需求

另存为:保存正在访问的界面

前进:访问现有的上一个界面

后退:访问现有页面的下一个页面

查看源文件:查看访问页面的HTML源文件、并提供保存、退出功能

参考样式
在这里插入图片描述

在这里插入图片描述

功能解析

界面搭建

  • 界面解析【主界面】
    在这里插入图片描述

tip:

  • WebView的使用注意事项

    • 需要在FX线程中使用

      /**
       * <p>{@code WebView} objects must be created and accessed solely from the
       * FX thread.
       */
      
  • Platform.runLater说明

    • 能够启动JavaFX线程

      /**
       * Run the specified Runnable on the JavaFX Application Thread at some
       * unspecified
       */
      
    • 启动前,不能启动FX runtime. 对于Swing,只要初始化第一个JFXPanel,就算启动FX runtime

      /**
        * <p>
        * This method must not be called before the FX runtime has been
        * initialized.
        * For Swing applications that use JFXPanel to display FX content, the FX
        * runtime is initialized when the first JFXPanel instance is constructed.
        * For SWT application that use FXCanvas to display FX content, the FX
        * <p>
        */
      

WebView无法直接添加到JPanel中,需要借助JFXPanel,同时WebView的创建需要在独立的FX线程,因此WebView添加JPanel的代码稍微有些麻烦

Platform.runLater(() -> {
    // 不能再Platform.runLater之前运行, 否则就启动了FX runtime, Platform运行会报错
	webView = new WebView();
    // webPanel 是JFXPanel
    webPanel.setScene(new Scene(webView));
    // 加载网页
    webView.getEngine().load(url);
});
// TODO 将webPanel添加到JPanel中
  • 界面解析【查看源代码界面】
    • 在这里插入图片描述

模块划分

在这里插入图片描述

URL存储数组,用单独的类(URLList)来维护

URLList,建立起主界面html代码界面, 监听器界面 沟通的桥梁。同时URLList维护的数组,能够存储URL访问历史记录,实现网页前进, 后退功能

代码编写

maven坐标

    <dependencies>
        <!--Servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- Lombok 依赖 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>
        <!--MyBatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>
        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.2.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.0</version>
            </plugin>
        </plugins>
    </build>

utils

Constant

全局常量

package com.xhf.keshe.utils;

import java.awt.*;

public interface Constant {

    int MAIN_WIDTH = 1920;
    int MAIN_HEIGHT = 1080;

    String[] menuList1 = {"另存为(A)", "退出(I)"};

    String[] menuList2 = {"前进", "后退"};

    String[] menuList3 = {"全屏", "查看源码(C)", "刷新"};

    Font baseFont = new Font("仿宋", Font.BOLD, 20);

    Font smallFont = new Font("仿宋", Font.BOLD, 15);

    String[] toolBarButtonNameList = {"另存为", "后退", "前进", "查看源码", "退出"};

    int SOURCE_WIDTH = 800;
    int SOURCE_HEIGHT = 600;
}

WebsiteHTMLGetter

通过URL解析出html代码

package com.xhf.keshe.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class WebsiteHTMLGetter {
    public static String getHTMLCode(String url) throws IOException {
        URL website = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) website.openConnection();
        connection.setRequestMethod("GET");

        // 获取网页内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        StringBuilder htmlCode = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            htmlCode.append(line).append("\n");
        }
        reader.close();

        return htmlCode.toString();
    }
}

URLList

维护URL记录

package com.xhf.keshe.utils;

import java.util.ArrayList;
import java.util.List;

public class URLList {
    private static List<String> queue = new ArrayList<String>();

    private static int pointer = -1;

    // 获取当前元素
    public static String getCur() {
        if (queue.size() == 0) return null;
        return queue.get(pointer);
    }

    // 指针右移
    public static boolean right() {
        if (pointer == queue.size() - 1) {
            return false;
        }
        pointer++;
        return true;
    }

    // 指针左移
    public static boolean left() {
        if (pointer == 0) {
            return false;
        }
        pointer--;
        return true;
    }

    // 添加元素
    public static boolean add(String url) {
        if (pointer + 1 > queue.size() - 1) {
            queue.add(url);
            ++pointer;
        }else {
            queue.set(++pointer, url);
        }
        return true;
    }
}

界面

主界面

package com.xhf.keshe;

import com.xhf.keshe.listener.*;
import com.xhf.keshe.utils.Constant;
import com.xhf.keshe.utils.URLList;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebView;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

/**
 * 主界面
 */
public class Main extends JFrame {
    public static JPanel toolBarPanel;

    /**
     * http地址接收栏
     */
    private static JTextField http = new JTextField();
    /**
     * 转向
     */
    private JButton redirect = new JButton("转向");
    /**
     * 显示web界面的panel
     */
    public static JFXPanel webPanel;
    /**
     * 显示website
     */
    public static WebView webView;

    /**
     * 刷新界面
     */
    public static void refreshWebSite(String url) {
        Platform.runLater(() -> {
            webView = new WebView();
            webPanel.setScene(new Scene(webView));
            // 加载网页
            webView.getEngine().load(url);
            // 重新加载http
            http.setText(url);
        });
    }

    public Main() {
        this.setSize(Constant.MAIN_WIDTH, Constant.MAIN_HEIGHT);
        // 居中
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 初始化界面
        initUI();

        refreshWebSite(http.getText());
    }

    /**
     * 初始化界面
     */
    private void initUI() {
        // 初始化所有的panel界面
        initPanel();
        // 初始化菜单栏
        initMenu();
        // 初始化工具栏1
        initToolBar1();
        // 初始化工具栏2
        initToolBar2();
    }

    /**
     * 初始化panel界面
     */
    private void initPanel() {
        toolBarPanel = new JPanel();
        toolBarPanel.setLayout(new GridLayout(2, 1));

        webPanel = new JFXPanel();
        webPanel.setLayout(new BorderLayout());

        webPanel.add(toolBarPanel, BorderLayout.NORTH);

        add(webPanel);
    }

    /**
     * 初始化二号工具栏
     */
    private void initToolBar2() {
        JToolBar jToolBar2 = new JToolBar();
        JLabel jLabel = new JLabel("地址");
        jLabel.setFont(Constant.smallFont);
        jToolBar2.add(jLabel);

        http.setFont(Constant.smallFont);
        http.setText("https://www.baidu.com/");
        URLList.add("https://www.baidu.com/");

        jToolBar2.add(http);

        redirect.setFont(Constant.smallFont);
        // 执行网页跳转逻辑
        redirect.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                URLList.add(http.getText());

                refreshWebSite(http.getText());
            }
        });
        jToolBar2.add(redirect);

        toolBarPanel.add(jToolBar2);
    }

    /**
     * 初始化一号工具栏
     */
    private void initToolBar1() {
        JToolBar jToolBar1 = new JToolBar();
        for (int i = 0; i < Constant.toolBarButtonNameList.length; i++) {
            JButton jButton = new JButton(Constant.toolBarButtonNameList[i]);
            jButton.setFont(Constant.smallFont);
            jToolBar1.add(jButton);
            try {
                if (Constant.toolBarButtonNameList[i].equals("另存为")) {
                    jButton.addActionListener(new SaveCodeListener());
                } else if (Constant.toolBarButtonNameList[i].equals("后退")) {
                    jButton.addActionListener(new URLmoveListener(URLmoveListener.BACKEND));
                } else if (Constant.toolBarButtonNameList[i].equals("前进")) {
                    jButton.addActionListener(new URLmoveListener(URLmoveListener.FORWARD));
                } else if (Constant.toolBarButtonNameList[i].equals("查看源码")) {
                    jButton.addActionListener(new GetSourceCodeListener());
                } else {
                    jButton.addActionListener(new QuitListener(this));
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
        toolBarPanel.add(jToolBar1);
    }

    /**
     * 初始化菜单栏
     */
    private void initMenu() {
        JMenuBar jMenuBar = new JMenuBar();
        // 初始化 '文件' 菜单
        JMenu jMenu1 = new JMenu("文件(ALT+F)");
        jMenu1.setMnemonic(KeyEvent.VK_F);

        jMenu1.setFont(Constant.baseFont);
        for (int i = 0; i < Constant.menuList1.length; i++) {
            JMenuItem item = new JMenuItem(Constant.menuList1[i]);
            item.setFont(Constant.baseFont);

            // 添加热键, 快捷键
            if (Constant.menuList1[i].equals("另存为(A)")) {
                // A
                item.setMnemonic(KeyEvent.VK_A);
                // ctrl + s
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK));
                item.addActionListener(new SaveCodeListener());
            }else if (Constant.menuList1[i].equals("退出(I)")) {
                // I
                item.setMnemonic(KeyEvent.VK_I);
                // ctrl + e
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.CTRL_MASK));
                item.addActionListener(new QuitListener(this));
            }
            jMenu1.add(item);
        }

        // 初始化 '编辑' 菜单
        JMenu jMenu2 = new JMenu("编辑(ALT+E)");
        jMenu2.setMnemonic(KeyEvent.VK_E);

        jMenu2.setFont(Constant.baseFont);
        for (int i = 0; i < Constant.menuList2.length; i++) {
            JMenuItem item = new JMenuItem(Constant.menuList2[i]);
            item.setFont(Constant.baseFont);

            // 添加快捷键
            if (Constant.menuList2[i].equals("前进")) {
                // ctrl + z
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
                item.addActionListener(new URLmoveListener(URLmoveListener.FORWARD));
            }else if (Constant.menuList2[i].equals("后退")){
                // ctrl + d
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.CTRL_MASK));
                item.addActionListener(new URLmoveListener(URLmoveListener.BACKEND));
            }
            jMenu2.add(item);
        }

        // 初始化 '视图' 菜单
        JMenu jMenu3 = new JMenu("视图(ALT+V)");
        jMenu3.setMnemonic(KeyEvent.VK_V);

        jMenu3.setFont(Constant.baseFont);
        for (int i = 0; i < Constant.menuList3.length; i++) {
            JMenuItem item = new JMenuItem(Constant.menuList3[i]);
            item.setFont(Constant.baseFont);

            // 添加热键, 快捷键
            if (Constant.menuList3[i].equals("全屏")) {
                // ctrl + u
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, ActionEvent.CTRL_MASK));
                item.addActionListener(new FullScreenListener(this));
            }else if (Constant.menuList3[i].equals("查看源码(C)")) {
                // c
                item.setMnemonic(KeyEvent.VK_C);
                // ctrl + c
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
                item.addActionListener(new GetSourceCodeListener());
            }else if (Constant.menuList3[i].equals("刷新")) {
                // ctrl + r
                item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.CTRL_MASK));
                item.addActionListener(new RefreshWebSite());
            }
            jMenu3.add(item);
        }

        jMenuBar.add(jMenu1);
        jMenuBar.add(jMenu2);
        jMenuBar.add(jMenu3);

        this.setJMenuBar(jMenuBar);
    }

    public static void main(String[] args) {
        Main main = new Main();
    }
}

查看源代码界面

package com.xhf.keshe.source;

import com.xhf.keshe.listener.QuitListener;
import com.xhf.keshe.listener.SaveCodeListener;
import com.xhf.keshe.utils.Constant;
import com.xhf.keshe.utils.URLList;
import com.xhf.keshe.utils.WebsiteHTMLGetter;

import javax.swing.*;
import java.awt.*;
import java.io.*;

public class SourcePage extends JFrame{
    /**
     * 工作界面
     */
    private JPanel workspace = new JPanel();

    public SourcePage() {
        this.setSize(Constant.SOURCE_WIDTH, Constant.SOURCE_HEIGHT);
        // 居中
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        // 初始化界面
        initUI();
    }

    /**
     * 初始化UI
     */
    private void initUI() {
        workspace.setLayout(new BorderLayout());
        // 初始化标题
        JLabel title = new JLabel("源代码");
        title.setFont(Constant.baseFont);
        title.setHorizontalAlignment(SwingConstants.CENTER);

        // 初始化文本域
        initTextArea();

        // 初始化按钮
        initButton();

        add(workspace);
    }

    /**
     * 初始化按钮
     */
    private void initButton() {
        // 添加按钮显示区域
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new FlowLayout());
        // 创建按钮
        JButton save = new JButton("保存");
        save.setFont(Constant.baseFont);
        save.addActionListener(new SaveCodeListener());

        JButton quit = new JButton("退出");
        quit.addActionListener(new QuitListener(this));
        quit.setFont(Constant.baseFont);

        buttonPanel.add(save);
        buttonPanel.add(quit);

        // 添加到panel中
        workspace.add(buttonPanel, BorderLayout.SOUTH);
    }


    /**
     * 初始化文本域
     */
    private void initTextArea() {
        JTextArea sourceCode = new JTextArea();

        // 设置自动换行
        sourceCode.setLineWrap(true);
        // 设置自动换行时,以单词为单位换行
        sourceCode.setWrapStyleWord(true);

        try {
            String URL = URLList.getCur();
            String htmlCode = WebsiteHTMLGetter.getHTMLCode(URL);
            // 获取源代码
            sourceCode.setText(htmlCode);
        } catch (IOException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "Could not read website source code, please try again or check the http is correct");
        }
        JScrollPane jScrollPane = new JScrollPane(sourceCode);
        // 添加源代码显示区域
        workspace.add(jScrollPane, BorderLayout.CENTER);
    }
}

listener

FullScreenListener

监听器:实现窗体全屏功能

package com.xhf.keshe.listener;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FullScreenListener implements ActionListener {

    private final JFrame fullScreenFrame;

    private boolean isFullScreen = false;

    public FullScreenListener(JFrame fullScreenFrame) {
        this.fullScreenFrame = fullScreenFrame;
    }
    /**
     * Invoked when an action occurs.
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        isFullScreen = !isFullScreen;
        if (isFullScreen) {
            fullScreenFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        } else {
            fullScreenFrame.setExtendedState(JFrame.NORMAL);
        }
    }
}

GetSourceCodeListener

监听器:获取查看源代码窗体

package com.xhf.keshe.listener;

import com.xhf.keshe.source.SourcePage;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class GetSourceCodeListener implements ActionListener {
    /**
     * Invoked when an action occurs.
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        // 创建JFrame
        SourcePage sourcePage = new SourcePage();
    }
}

QuitListener

package com.xhf.keshe.listener;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * 执行退出逻辑
 */
public class QuitListener implements ActionListener {
    private JFrame jFrame;

    public QuitListener(JFrame frame) {
        this.jFrame = frame;
    }
    /**
     * Invoked when an action occurs.
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        // 点击退出按钮时,关闭当前JFrame
        jFrame.dispose();
    }
}

RefreshWebSite

监听器:刷新网页

package com.xhf.keshe.listener;

import com.xhf.keshe.Main;
import com.xhf.keshe.utils.URLList;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class RefreshWebSite implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        Main.refreshWebSite(URLList.getCur());
    }
}

SaveCodeListener

监听器:保存源代码

package com.xhf.keshe.listener;

import com.xhf.keshe.utils.URLList;
import com.xhf.keshe.utils.WebsiteHTMLGetter;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class SaveCodeListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        String URL = URLList.getCur();
        String htmlCode = null;
        try {
            htmlCode = WebsiteHTMLGetter.getHTMLCode(URL);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }

        String fileName = removeUrlPrefix(URL);
        System.out.println(fileName);
        try {
            String path = "E:\\B站视频创作\\Java课设\\网页浏览器开发\\代码\\src\\main\\resources\\sourceCode\\";
            // 写文件
            writeFile(path + fileName, htmlCode);
        } catch (IOException exp) {
            exp.printStackTrace();
        }
    }
    /**
     * 写文件
     * @param filePath
     * @param content
     * @throws IOException
     */
    private static void writeFile(String filePath, String content) throws IOException {
        File file = new File(filePath);
        System.out.println(filePath);

        // 创建文件输出流
        try (PrintWriter writer = new PrintWriter(new FileWriter(file))) {
            // 写入文件内容
            writer.print(content);
        }
    }

    /**
     * 去除网址前缀
     * @param url
     * @return
     */
    private static String removeUrlPrefix(String url) {
        // 去除"http://"前缀
        if (url.startsWith("http://")) {
            url = url.substring(7);
        }
        // 去除"https://"前缀
        else if (url.startsWith("https://")) {
            url = url.substring(8);
        }

        return url;
    }
}

URLmoveListener

监听器:控制网页界面前进、后退

package com.xhf.keshe.listener;

import com.xhf.keshe.Main;
import com.xhf.keshe.utils.URLList;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class URLmoveListener implements ActionListener {
    public static int FORWARD = 0;
    public static int BACKEND = 1;

    private int direction;

    public URLmoveListener(int direction) {
        this.direction = direction;
    }

    public void actionPerformed(ActionEvent e) {
        boolean flag = false;
        // 向前移动
        if (direction == FORWARD) {
            flag = URLList.right();
            if (!flag) {
                JOptionPane.showMessageDialog(null, "已经是最新的网页了");
            }
        }else if (direction == BACKEND) {
            flag = URLList.left();
            if (!flag) {
                JOptionPane.showMessageDialog(null, "已经是最旧的网页了");
            }
        }
        if (flag) {
            Main.refreshWebSite(URLList.getCur());
        }
    }
}

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

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

相关文章

构建IT项目价值管理体系︱陆金所控股有限公司项目管理专家朱磊

陆金所控股有限公司项目管理专家朱磊先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;陆控-构建IT项目价值管理体系。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; IT资源有限&#xff0c;…

常见的几大排序问题

前言&#xff1a;排序问题&#xff0c;是数据结构中的一大重要的组成板块&#xff0c;很多的面试机试中都会多多少少的涉及到排序问题&#xff0c;之前在上数据结构的那个学期整理过排序问题&#xff0c;不过大都是囫囵吞枣&#xff0c;不求甚解&#xff0c;今天&#xff0c;我…

Altium Designer (AD) 绘制原理图及双层PCB简易教程

目录 前言 工程建立 创建工程 创建原理图文件 创建PCB文件 绘制原理图 导入元件库 ​编辑绘制原理图 设置原理图标注 ​编辑​编辑 结果图​编辑 制作PCB板 生成PCB​编辑 绘制PCB边缘 设置PCB网格间距大小 走线规则设置 修改安全间距 什么是安全间距 怎样修…

在飞机设计中的仿真技术

仿真技术在飞机设计中发挥着越来越重要的作用&#xff0c;本文阐述了国内外在飞机设计中广泛使用的结构强度计算&#xff0c;多体动力学仿真、多学科多目标结构优化、内外流场分析、非线性有限元分析、疲劳强度分析、电磁仿真分析&#xff0c;机电液联合仿真分析等&#xff0c;…

数据结构基础5:栈和队列的实现。

一.栈的基本概念。 一.基本概念 1.基本概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&…

java静默打印PDF(可实现生产环境下服务器写入PDF模板,然后调用客户端打印机打印)

java静默打印PDF可实现生产环境下服务器写入PDF模板&#xff0c;然后调用客户端打印机打印 一、简需求实现步骤 二、代码实现0、打印模板1、服务器部分 &#xff08;端口&#xff1a;8090&#xff09;1.1、maven依赖1.2、实体1.2.1、接口返回类1.2.2、标签纸页面参数类1.2.3、P…

【EI/SCOPUS检索】第四届应用力学与机械工程国际学术会议(ICAMME 2023)

第四届应用力学与机械工程国际学术会议&#xff08;ICAMME 2023&#xff09; 2023 4th International Conference on Applied Mechanics and Mechanical Engineering (ICAMME 2023) 第四届应用力学与机械工程国际学术会议&#xff08;ICAMME 2023&#xff09;将于2023年11月10…

期刊和会议缩写查询网站

1.https://pubmed.ncbi.nlm.nih.gov/?termMedicalImageComputingandComputer-AssistedIntervention 2. http://www.letpub.com.cn/index.php?pagejournalapp&viewsearch 3. https://blog.csdn.net/weixin_44557349/article/details/120825927 https://blog.csdn.net/ret…

Kafka:安装和配置

producer&#xff1a;发布消息的对象&#xff0c;称为消息产生者 &#xff08;Kafka topic producer&#xff09; topic&#xff1a;Kafka将消息分门别类&#xff0c;每一个消息称为一个主题&#xff08;topic&#xff09; consumer&#xff1a;订阅消息并处理发布消息的对象…

【solon生态】- solon.cloud.micrometer插件使用指南及micrometer详解

solon.cloud.micrometer插件使用指南 solon是什么solon的cloud生态图快速入门 micrometer指南micrometer是什么监控系统 Supported Monitoring Systems注册表 Registry度量 Meters度量名 Naming Meters度量标签 Tag Naming通用标签 Common Tags 指标过滤器 MeterFilter聚合速率…

LeetCode_01 精度丢失

1281. 整数的各位积和之差 给你一个整数 n&#xff0c;请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。 示例 输入&#xff1a;n 234 输出&#xff1a;15 解释&#xff1a; 各位数之积 2 * 3 * 4 24 各位数之和 2 3 4 9 结果 24 - 9 15示例 …

vue中使用this.$refs获取不到子组件的方法,属性方法都为undefined的解决方法

问题描述 vue2中refs获取不到子组件中的方法&#xff1f;&#xff0c;而获取到的是undefined 原因及解决方案&#xff1a; 第一种、在循环中注册了很多个ref 因为注册了多个ref&#xff0c;获取是不能单单知识refs.xxx&#xff0c;需要使用数组和索引来获取具体一个组件refs[…

限流式保护器在高校宿舍电气防火的应用

安科瑞 华楠 引言 14日早晨6时10分左右&#xff0c;上海商学院徐汇校区学生宿舍楼发生火灾&#xff0c;4名女生从六楼宿合阳台跳下逃生当场死亡&#xff0c;酿成近年来惨烈的校园事故。宿舍火灾初步判断缘起于寝室里使用热得快导致电器故障并将周围可燃物引燃。 任何条生命都是…

【方法】7Z压缩包如何解压?

你知道7Z压缩包如何解压吗&#xff1f; 7Z是一种主流高效的压缩格式&#xff0c;它可以用多种压缩解压软件来解压&#xff0c;像7-Zip、WinRAR等常用的解压缩软件都可以解压7Z压缩包。 首先我们可以从官网或者软件商店里免费下载7-Zip或者WinRAR解压缩软件&#xff0c;再安装…

PXE-kickstart无人值守安装操作系统

PXE的概念&#xff1a; PXE&#xff08;Pre-boot Execution Environment&#xff0c;预启动执行环境&#xff09;是由Intel公司开发的最新技术&#xff0c;工作于C/S的网络模式&#xff0c;支持工作站通过网络从远端服务器下载映像&#xff0c;并由此支持通过网络启动操作系统…

leetcode 2616. 最小化数对的最大差值

在数组nums中找到p个数对&#xff0c;使差值绝对值的和最小。 思路&#xff1a; 最小差值应该是数值相近的一对数之间产生&#xff0c;让数值相近的数字尽量靠在一起方便计算&#xff0c;所以需要排序。 这里不去直接考虑一对对的数字&#xff0c;而是直接考虑差值的取值。 …

msvcp120.dll丢失的解决方法,哪种解决方法更实用

msvcp120.dll是Microsoft Visual C 2013库中的一个动态链接库文件。它包含了在使用Visual C 2013编译的应用程序中所需的函数和资源。这个文件通常用于在Windows操作系统上运行使用Visual C 2013编写的软件。如果缺少或损坏了msvcp120.dll文件&#xff0c;可能会导致相关软件无…

Wav2Lip实践

1. 安装 1.1 安装 conda以指定python版本运行环境 下载&#xff1a;Index of /https://repo.anaconda.com/archive/index.html 1.2 如按旧项目基于python3.6版本对话&#xff0c;会有很多包找不到的情况&#xff0c;经摸索后以python3.9构建成功&#xff0c; conda instal…

js代码加密,也能在vs code中进行?

在vs code中对js代码混淆加密 Vs code是常用的js代码编辑工具。本文演示如何在vs code中调用jshaman扩展&#xff0c;实现非常方便的js代码加密。 打开vs code&#xff1a; 点击左侧的“扩展”&#xff0c;打开后搜索“jshaman”。 &#xff08;JShaman是业界很有名的JS代码…

Stable Diffusion - 底部视角 (From Below) 拍摄的图像 LoRA 与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132192139 图像来源自 哥特风格 与 底部视角 的结合&#xff0c;更具有视觉冲击力。 从下面或底部 (From Below) 拍摄人物&#xff0c;可以创造出…