展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > Java如何实现登录窗口?

Java如何实现登录窗口?

登录窗口主类packageccnu.paint;importjava.awt.Color;importjava.awt.Font;importjava.awt.GridLayout;importjava.awt.Point;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.MouseAdapter;importjava.awt.event.MouseEvent;importja

登录窗口主类

package ccnu.paint;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import ccnu.util.Answer;
import ccnu.util.Verification;

public class Login extends JFrame
{
    private static final long serialVersionUID = 1L;

    private Properties pro = new Properties();

    private boolean ver_code = false; // 默认输入验证码错误

    private Answer answer = null;

    private JPanel p1 = new JPanel(); // 添加到JPanel中的组件默认为流式布局
    private JLabel luser = new JLabel("username: ");
    private JTextField username = new JTextField(20);

    private JPanel p2 = new JPanel();
    private JLabel lpwd = new JLabel("password: ");
    private JPasswordField pwd = new JPasswordField(20);

    private JPanel p4 = new JPanel();
    private JLabel lVer = new JLabel("verification: ");
    private JTextField ver = new JTextField(10);
    private JLabel img = new JLabel();
    private JLabel result = new JLabel();

    private JPanel p3 = new JPanel();
    private JButton ok = new JButton("ok");
    private JButton cancel = new JButton("cancel");
    private JButton signUp = new JButton("Sign up"); // 用于账户注册

    // 设置组件的监听
    public void initListener()
    {
        username.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {// JTextField的action是回车键
                String name = username.getText();
                // Login.this.setTitle(name);
                // System.out.println(name.hashCode() + "***" +"".hashCode());
                if (name.equals(""))
                {
                    JOptionPane.showMessageDialog(Login.this, "Please input a userName!");
                } else
                {
                    pwd.grabFocus();
                }
            }
        });

        pwd.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e)
            {
                String password = new String(pwd.getPassword());
                if(password.equalsIgnoreCase(""))
                {
                    JOptionPane.showMessageDialog(Login.this, "please input a password!");
                }else{
                    ver.grabFocus();
                }
            }

        });

        ok.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e)
            {
                // 重新加载最新的账户文件
                try
                {
                    pro.load(new FileInputStream(new File("src/res/accouts.properties")));
                } catch (IOException e1)
                {
                    e1.printStackTrace();
                }
                check();
            }

        });

        // 判断验证码是否正确
        ver.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e)
            {
                String verCode = ver.getText();
                if(verCode.equals(""))
                {
                    JOptionPane.showMessageDialog(Login.this, "Please input a verification!");
                }else{
                    if(verCode.equals(answer.getResult()))
                    {
                        result.setIcon(new ImageIcon(Login.this.getClass().getResource("/res/right.jpg"))); // 显示提示的图片信息(如√图片)
                        ver_code = true;
                        // 检查之前,重新加载最新的账户文件
                        try
                        {
                            pro.load(new FileInputStream(new File("src/res/accouts.properties"))); // 将账户文件加载进来
                        } catch (IOException e1)
                        {
                            e1.printStackTrace();
                        }
                        check();
                    }else{
                        result.setIcon(new ImageIcon(Login.this.getClass().getResource("/res/error.jpg"))); // 显示提示的图片信息(如×图片) 
                        ver_code = false;
                    }
                }
            }
        });

        // 点击图片会更改验证码
        img.addMouseListener(new MouseAdapter(){

            @Override
            public void mouseClicked(MouseEvent e)
            {
                answer = Verification.verification();
                img.setIcon(new ImageIcon(answer.getBufferedImage())); // 设置验证码图案
            }
        });

        cancel.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                int option = JOptionPane.showConfirmDialog(Login.this, "Are you sure to exit?");
//              System.out.println("option = " + option);
                if (option == 0)
                {// Yes
                    Login.this.dispose();
                }
            }
        });

        signUp.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e)
            {
                new SignUp();
            }
        });
    }

    // 初始化登录窗口及其组件的设置监听
    public Login()
    {
        super("Login");

        // 加载账户文件
        try
        {
            pro.load(new FileInputStream(new File("src/res/accouts.properties"))); // 从指定位置将账户文件加载进来
        } catch (IOException e)
        {
            e.printStackTrace();
        }

        initListener();
        answer = Verification.verification(); // 生成验证码
        img.setIcon(new ImageIcon(answer.getBufferedImage())); // 设置初始验证码

        this.setLocation(new Point(200, 200));
        this.setSize(500, 300);
        this.setLayout(new GridLayout(4, 1, 0, 20)); // 垂直间隙为20px
        p1.add(luser);
        p1.add(username);
        p2.add(lpwd);
        p2.add(pwd);
        p4.add(this.lVer);
        p4.add(this.ver);
        p4.add(this.img);
        result.setForeground(Color.red);
        result.setFont(new Font("楷体", Font.BOLD, 20));
        p4.add(result);
        p3.add(ok);
        p3.add(cancel);
        p3.add(signUp);
        this.add(p1);
        this.add(p2);
            this.add(p4);
        this.add(p3);

//      this.setBackground(Color.blue); // JFrame的上层还有一个ContentPane
        this.getContentPane().setBackground(Color.gray);
        this.setResizable(false);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 等价于Frame中的windowClosing事件
    }

    // 检查用户名或密码
    public void check()
    {

        String verCode = ver.getText();
        if(verCode.equals(""))
        {
            JOptionPane.showMessageDialog(Login.this, "Please input a verification!");
            return;
        }else{
            if(verCode.equals(answer.getResult()))
            {
                result.setIcon(new ImageIcon(Login.this.getClass().getResource("/res/right.jpg")));
                ver_code = true;
            }else{
                result.setIcon(new ImageIcon(Login.this.getClass().getResource("/res/error.jpg")));
                ver_code = false;
            }
        }

        if(ver_code == false)
        {
            JOptionPane.showMessageDialog(this, "verification is error!");
            return;
        }
        String name = username.getText();
        String password = new String(pwd.getPassword()); // return char[]
//      if (name.equalsIgnoreCase("admin") && password.equals("123456"))
        if (isPass(name, password))
        {
//          new PaintApp(name);
            JOptionPane.showMessageDialog(this, "-^_^-   OK..."); // 此处可以加上其他的登陆成功后进一步处理的窗口
            this.dispose();
        } else
        {
            JOptionPane.showMessageDialog(this, "userName or password is incorrect!");
            username.setText("");
            pwd.setText("");
            ver.setText("");
            answer = Verification.verification();
            img.setIcon(new ImageIcon(answer.getBufferedImage()));
            result.setIcon(null);
        }
    }

    // 验证用户输入的账户名和密码是否正确(通过与加载进来的账户 pro 比对)
    public boolean isPass(String name, String password)
    {
        Enumeration en = pro.propertyNames();
        while(en.hasMoreElements())
        {
            String curName = (String)en.nextElement();
//          System.out.println(curName + "---" + pro.getProperty(curName));
            if(curName.equalsIgnoreCase(name))
            {
                if(password.equalsIgnoreCase(pro.getProperty(curName)))
                {
                    return true;
                }
            }
        }
        return false;
    }

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

账户注册类

package ccnu.paint;

import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class SignUp extends JFrame
{
    private static final long serialVersionUID = 3054293481122038909L;

    private Properties pro = new Properties(); // 最好时静态的,因为账户是共享的

    private JPanel panel = new JPanel();
    private JLabel label = new JLabel("username: ");
    private JTextField field = new JTextField(15);

    private JPanel panel2 = new JPanel();
    private JLabel label2 = new JLabel("password: ");
    private JPasswordField field2 = new JPasswordField(15);

    private JPanel panel3 = new JPanel();
    private JLabel label3 = new JLabel("confirmation: ");
    private JPasswordField field3 = new JPasswordField(15);

    private JPanel panel4 = new JPanel();
    private JButton button = new JButton("OK");
    private JButton button2 = new JButton("Cancel");

    public void initListener()
    {
        field.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                field2.grabFocus();
            }

        });

        field2.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                field3.grabFocus();
            }
        });
        field3.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                ok_actionPerformed(e);
            }

        });

        // OK
        button.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                ok_actionPerformed(e);
            }
        });

        // Cancel
        button2.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                cancel_actionPerformed(e);
            }
        });
    }

    public void ok_actionPerformed(ActionEvent e)
    {
        String userName = field.getText();
        String password = new String(field2.getPassword());
        String password2 = new String(field3.getPassword());
        if (userName.equals(""))
        {
            JOptionPane.showMessageDialog(SignUp.this, "username cannot be empty!");
        } else
        {
            if (password.equalsIgnoreCase(""))
            {
                JOptionPane.showMessageDialog(SignUp.this, "password cannot be empty!");
            } else
            {
                if (password2.equalsIgnoreCase(password))
                {
                    if (isExist(userName))
                    {
                        JOptionPane.showMessageDialog(SignUp.this, "username has been existed!");
                        field.setText("");
                        field2.setText("");
                        field3.setText("");
                    } else
                    {
                        pro.setProperty(userName, password);
                        JOptionPane.showMessageDialog(SignUp.this, "SignUp success!");
                        writeToPro(userName, password); // 将其写入到账户文件中
                        SignUp.this.dispose();
                    }
                } else
                {
                    JOptionPane.showMessageDialog(SignUp.this, "password is not consistent!");
                    field2.setText("");
                    field3.setText("");
                }
            }
        }
    }

    public void cancel_actionPerformed(ActionEvent e)
    {
        System.exit(0);
    }

    public SignUp()
    {
        super("Sign up");

        // 加载账户文件
        try
        {
            pro.load(new FileInputStream(new File("src/res/accouts.properties")));
        } catch (IOException e)
        {
            e.printStackTrace();
        }

        // 初始化窗口组件的监听
        initListener();

        this.setLocation(new Point(300, 230));
        this.setSize(280, 210);

        this.setLayout(new GridLayout(4, 1, 0, 20)); // 垂直间隙为20px
        panel.add(label);
        panel.add(field);
        panel2.add(label2);
        panel2.add(field2);
        panel3.add(label3);
        panel3.add(field3);
        panel4.add(button);
        panel4.add(button2);
        this.add(panel);
        this.add(panel2);
        this.add(panel3);
        this.add(panel4);

        this.setAlwaysOnTop(true);
        this.setResizable(false);
        this.setVisible(true);
    }

    // 如果注册始终可用,就要保存起来,否则不需要写入文件中,注册账户本次使用
    // 将账户名与其对应密码保存到指定的账户文件中
    public void writeToPro(String userName, String password)
    {
        pro.setProperty(userName, password);
        try
        {
            pro.store(new FileOutputStream(new File("src/res/accouts.properties")), "allAccouts");
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }


    // 判断此用户名是否已经存在
    public boolean isExist(String userName)
    {
        Enumeration enumer = pro.propertyNames();
        while (enumer.hasMoreElements())
        {
            String temp = (String) enumer.nextElement();
            if (temp.equals(userName))
            {
                return true;
            }
        }
        return false;
    }
}

生成验证码类

package ccnu.util;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Random;

// 用于生成验证码
public class Verification
{
    private static Answer answer = new Answer();
    private static BufferedImage bufferedImage = null;
    private static String result = null;
    private static String words = null;
    private static String words2 = null;

    // 生成验证码
    public static Answer verification()
    {

        bufferedImage = new BufferedImage(200, 35, BufferedImage.TYPE_INT_RGB);
        Graphics g = bufferedImage.getGraphics();
        Random rand = new Random();
        for (int i = 0; i < 20; i++)
        {
            Point p1 = new Point(rand.nextInt(200), rand.nextInt(30));
            Point p2 = new Point(rand.nextInt(200), rand.nextInt(30));
            g.drawLine(p1.x, p1.y, p2.x, p2.y);
        }
        g.setColor(Color.RED);
        g.setFont(new Font("楷体", Font.BOLD, 22));
        int plan = 2;
        switch (rand.nextInt(plan))
        {
        case 0:
            plan(g);
            break;
        case 1:
            plan1(g);
            break;
        default:
            break;
        }
        answer.setBufferedImage(bufferedImage);
        answer.setResult(result);
        g.dispose();
        return answer;
    }

    // 方案一
    private static void plan(Graphics g)
    {
        words = ReadTxt.read("/res/words.txt"); // 指定生成验证码问题的资源文件的路径
        Random rand = new Random();
        String first = String.valueOf(words.charAt(rand.nextInt(words.length())));
        String second = String.valueOf(words.charAt(rand.nextInt(words.length())));
        String third = String.valueOf(words.charAt(rand.nextInt(words.length())));
        g.drawString(first, rand.nextInt(40) + 20, rand.nextInt(12) + 15);
        g.drawString(second, rand.nextInt(40) + 80, rand.nextInt(12) + 15);
        g.drawString(third, rand.nextInt(40) + 140, rand.nextInt(12) + 15);
        result = first + second + third;
    }

    // 方案二
    private static void plan1(Graphics g)
    {
        words2 = ReadTxt.read("/res/words2.txt"); // 指定生成验证码问题的资源文件的路径
        Random rand = new Random();
        String first = String.valueOf(words2.charAt(rand.nextInt(words2.length() - 2)));
        String second = String.valueOf(words2.charAt(rand.nextInt(2) + 9));
        String third = String.valueOf(words2.charAt(rand.nextInt(words2.length() - 2)));
        g.drawString(first, rand.nextInt(30) + 20, rand.nextInt(12) + 15);
        g.drawString(second, rand.nextInt(40) + 60, rand.nextInt(12) + 15);
        g.drawString(third, rand.nextInt(30) + 110, rand.nextInt(12) + 15);
        g.drawString("=", rand.nextInt(40) + 150, rand.nextInt(12) + 15);
        if(second.equals("+"))
        {
            result = String.valueOf(Integer.valueOf(first) + Integer.valueOf(third)); 
        }else{
            result = String.valueOf(Integer.valueOf(first) - Integer.valueOf(third)); 
        }
    }

}

读取生成验证码所需文件类

package ccnu.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

// 专门用于读取文件
public class ReadTxt
{
    public static String read(String path) // 根据指定路径path来读取它,并返回它所包含的内容
    {
        StringBuffer sb = new StringBuffer();
        try
        {
            BufferedReader br = new BufferedReader(new InputStreamReader(Verification.class.getResourceAsStream(path)));
            String temp = null;
            while(null != (temp = br.readLine()))
            {
                sb.append(temp);
            }
            br.close();
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        return sb.toString();
    }

}

得到生成的验证码所包含的信息类(图案、问题)

package ccnu.util;

import java.awt.image.BufferedImage;

// 用于将生成的验证码的图案信息以及问题结果封装
public class Answer
{
    private BufferedImage bufferedImage = null; // 验证码图像
    private String result = null; // 验证码图像问题的答案

    public BufferedImage getBufferedImage()
    {
        return bufferedImage;
    }
    public void setBufferedImage(BufferedImage bufferedImage)
    {
        this.bufferedImage = bufferedImage;
    }
    public String getResult()
    {
        return result;
    }
    public void setResult(String result)
    {
        this.result = result;
    }

}

验证码生成汉字识别的问题的文件words.txt
如: 中国湖北省武汉市汉东大学政法学院

验证码生成算术运算的问题的文件words2.txt
123456789+-

提示图片

Java如何实现登录窗口?

Java如何实现登录窗口?

登录效果

Java如何实现登录窗口?

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发 Java
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。