Swing入门之简单文本编辑器

本文探讨了Java的Swing库在构建窗口应用程序中的应用,包括Swing的继承框架、基本组件如JFrame,以及事件监听器的概念。通过讲解AWT的基础,特别是Container类和Component的子类,阐述了如何利用Swing创建具有一致观感的跨平台窗口组件,例如用于文本编辑的组件。文章还介绍了事件处理机制,并给出了简单的文本编辑器代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用Java开发窗口应用程序有两种选择:
1.AWT: Abstract Window Toolkit
2.JFC: Java Foundation Classes / Swing

本文主要介绍Swing设计基本要素:
容器,组件,版面管理员,事件与监听器等基本概念
要了解Swing必须了解Swing继承架构,Swing是基于AWT而创建,因此要了解Swing继承架构必须先了解AWT继承架构

一.AWT继承架构

AWT提供基本的GUI组件,用在所有的Java applets及应用程序中。

具有可扩展的超类,它们的属性是继承的。
确保显示在屏幕上的每个GUI组件都是抽象类组件的子类。
GUI组件根据作用可以分为两种:基本组件和容器组件
基本组件又称构件,诸如按钮、文本框之类的图形界面元素。
容器是一种比较特殊的组件,可以容纳其他组件,容器如窗口、对话框等。
所有的容器类都是java.awt.Container的直接或间接子类
Container,它是Component的一个子类,而且包括两个主要子类:Panel,Window。

  注:容器不但能容纳组件,还能容纳其他容器,这一事实对于建立复杂的布局是关键的,也是基本的。
这里写图片描述

各种组件的父类:
java.awt.Component 或
java.awt.MenuComponent

Component: 英 [kəmˈpəʊnənt] 美 [kəmˈpoʊnənt]
n. 成分; 组分; 零件; [数] 要素;
adj. 成分的; 组成的; 合成的; 构成的;

Component的子类:

Button, Label, TextComponent

MenuBar, MenuItem

容器: Container

是Component的重要子类
其实例可以容纳其他Component,因而可递归组合为复杂的窗口画面.

Container主要有两个子类:

Window:
Window包括两个重要子类:
(1)Frame: 有标题栏,工具栏且可改变大小的窗口组件
(2)Dialog: 可显示简单的对话框,没有工具栏,不能改变大小

Panel:
(1)容纳于Container
(2)嵌入浏览器&在其中可以放入组件或其他Container

在AWT中,主要就是使用Window+Dialog+Panel来进行窗口组件组合

二.Swing继承框架

Swing以AWT为基础,功能繁多,且开发出来的窗口组件在不同平台会有一致观感

重要概念:

Swing所有了组件都是Container的子类实例

这里写图片描述

基本元素(1) JFrame

可独立显示,不用加入其他容器

例子:

import javax.swing.*;

/**
 * Created by butter on 16-11-21.
 */
public class JNotePad extends JFrame {
    public JNotePad(){
        initComponents();//初始组件外观
        //initEventListeners();//初始化组件事件倾听器
    }

    private void initEventListeners() {//事件处理
        //设置按左(右)上角X按钮默认行为:关闭窗口,其实这个是默认的,不需要手动设置
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void initComponents() {//窗口组件设置
        setTitle("新增纯文本文档");//设置窗口标题
        setSize(1000, 700);//设置窗口宽高
    }

    public static void main(String[] args) {
        //将建立的JNotePad实例与SetVisible()的动作排入事件队列

        //这玩意应该是一个Runnable接口的实现
        SwingUtilities.invokeLater( ()->{
            new JNotePad().setVisible(true);
        });
    }
}

窗口上发生任何事件 : 键盘操作,鼠标点击/选中, 大小改变等
都会产生事件:Event
若对某些事件感兴趣(事件发生后想要实现相应该功能),可以对组件注册监听器(Listener),每个窗口程序都有一个事件队列,若有事件发生,都会被安排到这个队列,窗口程序会使用一条线程来处理队列中的事件,调用已注册监听器中的方法.

编辑器代码:

import jdk.nashorn.internal.scripts.JO;

import javax.swing.*;
import javax.xml.soap.Text;
import java.awt.*;
import java.awt.event.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * Created by butter on 16-11-21.
 */


/**
 *
 * swing开发基本步骤:
 * (1)继承JFrame
 * (2)定义需要的组件
 * (3)创建组件
 * (4)添加组件
 * (5)对(顶层)窗体设置
 * (6)设置显示
 */

public class JNotePad_demo2 extends JFrame{


    private JMenuBar        menuBar;

    private JMenu fileMenu;
        private JMenuItem       menuOpen;
        private JMenuItem       menuSave;
        private JMenuItem       menuSaveAs;
        private JMenuItem       menuClose;

    private JMenu editMenu;
        private JMenuItem       menuCut;
        private JMenuItem       menuCopy;
        private JMenuItem       menuPast;

    private JMenu aboutMenu;
        private JMenuItem       menuAbout;

    private JTextArea textArea;//输入区域
    private JLabel    stateBar;//状态条

    private TextDAO textDAO;//保存
    private JFileChooser fileChooser;//文件选择器
    private JPopupMenu popUpMeue; //鼠标点击Menu事件



    public JNotePad_demo2(){
        initComponents();//初始组件外观
        initEventListeners();//初始化组件事件倾听器
    }

    private void initComponents(){
        setTitle("新增纯文本文档");
        setSize(400, 300);
        initMenu();
        initTextArea();
        initStateBar();
        popUpMeue = editMenu.getPopupMenu();
        fileChooser = new JFileChooser();
    }


/*----------------初始化Menu---------------------*/
    private void initMenu() {
    initFileMenu();
    initEditMenu();
    initAboutMenu();
    initMenuBar();
}
    private void initMenuBar() {
        //构造菜单列
        menuBar = new JMenuBar();
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(aboutMenu);

        //设置菜单列
        setJMenuBar(menuBar);
    }
    private void initAboutMenu() {
        aboutMenu = new JMenu("关于");
        menuAbout = new JMenuItem("关于JNotePad");

        aboutMenu.add(menuAbout);
    }
    private void initEditMenu() {
        editMenu = new JMenu("编辑");
        menuCut  = new JMenuItem("剪切");
        menuCopy = new JMenuItem("复制");
        menuPast = new JMenuItem("粘贴");

        editMenu.add(menuCut);
        editMenu.add(menuCopy);
        editMenu.add(menuPast);
    }
    private void initFileMenu() {
        fileMenu = new JMenu("文件");

        menuOpen   = new JMenuItem("打开");
        menuSave   = new JMenuItem("保存");
        menuSaveAs = new JMenuItem("另存为");
        menuClose  = new JMenuItem("关闭");

        fileMenu.add(menuOpen);
        fileMenu.addSeparator(); //分割线;
        fileMenu.add(menuSave);
        fileMenu.add(menuSaveAs);
        fileMenu.addSeparator(); //分割线;
        fileMenu.add(menuClose);
    }
/*-----------------------------------------------*/

    //初始化事件监视器
    private void initEventListeners(){
        //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);设置点X关闭
        initAccelerator();
        //下面要设置,点X提示"文档已改变,是否保存"

        //按下窗口关闭按钮事件处理:
        addWindowListener(
                new WindowAdapter() {
                    public void windowClosing(WindowEvent event){
                        closeWindow(event);
                    }
                }
        );

        initMenuListener();//初始化菜单的点击事件

        //编辑区键盘事件:
        textArea.addKeyListener(
                new KeyAdapter() {
                    public void keyTyped(KeyEvent event){
                        jtexAreaActionPerformed(event);
                    }
                }
        );

        //编辑区鼠标事件:
        textArea.addMouseListener(
                new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent mouseEvent) {
                        if(mouseEvent.getButton() == MouseEvent.BUTTON3){//3:右键
                            popUpMeue.show(editMenu, mouseEvent.getX(), mouseEvent.getY());
                        }
                    }
                    public void mouseClicked(MouseEvent e){
                        if(e.getButton() == MouseEvent.BUTTON1){
                            popUpMeue.setVisible(false);
                        }
                    }
                }
        );
    }


    private void initMenuListener() {
        menuOpen.addActionListener(this::openFile);
        menuSave.addActionListener(this::saveFile);
        menuSaveAs.addActionListener(this::saveFileAs);
        menuClose.addActionListener(this::closeFile);
        menuCut.addActionListener(this::cut);
        menuPast.addActionListener(this::past);
        menuAbout.addActionListener(event -> {//关于  弹窗
            JOptionPane.showOptionDialog(null,
                    "JNotePad 0.1\n来自 http://www.dubutter.com",
                    "关于JNotePad",
                    JOptionPane.DEFAULT_OPTION,
                    JOptionPane.INFORMATION_MESSAGE,
                    null, null, null);
        });
    }

    private void past(ActionEvent event) {

    }

    private void cut(ActionEvent event) {

    }


    private void saveFileAs(ActionEvent event) {
        int option = fileChooser.showDialog(null, null);
        if(option == JFileChooser.APPROVE_OPTION){
            //在标题栏设定文件名
            setTitle(fileChooser.getSelectedFile().toString());
            textDAO.create(fileChooser.getSelectedFile().toString());
            saveFile(event);
        }
    }

    private void saveFile(ActionEvent event) {
        Path path = Paths.get(getTitle());
        if(Files.notExists(path)){
            saveFileAs(event);
        }else{
            try{
                textDAO.save(path.toString(), textArea.getText());
                stateBar.setText("未修改");
            }catch(Throwable e){
                JOptionPane.showMessageDialog(null, e.toString(),
                        "写入失败", JOptionPane.ERROR_MESSAGE);
            }
        }
    }
    private void closeFile(ActionEvent event) {
        if(stateBar.getText().equals("未修改")){
            dispose();//释放窗口资源,关闭程序
        }else{
            int option = JOptionPane.showConfirmDialog(null,
                    "文档已修改,是否保存:",
                    "保存?",JOptionPane.YES_NO_OPTION,
                    JOptionPane.WARNING_MESSAGE);
            switch (option){
                case JOptionPane.YES_OPTION:
                    saveFile(event);
                    break;
                case JOptionPane.NO_OPTION:
                    dispose();
            }
        }
    }


    private void openFile(ActionEvent event) {
        if(stateBar.getText().equals("未修改")){
            showFileDialog();
        } else{
            int option = JOptionPane.showConfirmDialog(
                    null, "已修改,是否保存?", "保存", JOptionPane.WARNING_MESSAGE, Integer.parseInt(null)
            );
            switch (option){
                case JOptionPane.YES_OPTION:
                    saveFile();
                    break;
                case JOptionPane.NO_OPTION:
                    showFileDialog();
                    break;
                default:
                    break;
            }
        }

    }

    private void jtexAreaActionPerformed(KeyEvent event) {
        stateBar.setText("已修改");
    }


    //关闭窗口,并提示是否表存
    private void closeWindow(WindowEvent event) {
        closeFile(new ActionEvent(
                event.getSource(), event.getID(), "windowClosing"));
    }

    //设置快捷键
    private void initAccelerator() {
        //设置快捷键,,略略略
        menuCopy.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK)
        );
        menuPast.setAccelerator(
                KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK)
        );
    }
    //设置文本区域
    private void initTextArea(){
        textArea = new JTextArea();
        textArea.setFont(new Font("细明体", Font.PLAIN, 16));
        textArea.setLineWrap(true);
        JScrollPane panel = new JScrollPane(textArea,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        getContentPane().add(panel, BorderLayout.CENTER);
    }

    //初始化状态栏(最下方)
    private void initStateBar() {
        stateBar = new JLabel("未修改");
        stateBar.setHorizontalAlignment(SwingConstants.LEFT);
        stateBar.setBorder(BorderFactory.createEtchedBorder());
        getContentPane().add(stateBar, BorderLayout.SOUTH);
    }

    public JNotePad_demo2(TextDAO textDAO){
        this();
        this.textDAO = textDAO;
    }

    //打开
    private void openFile(){
        if(stateBar.getText().equals("未修改")){
            showFileDialog();
        } else{
            int option = JOptionPane.showConfirmDialog(
                    null, "已修改,是否保存?", "保存", JOptionPane.WARNING_MESSAGE, Integer.parseInt(null)
            );
            switch (option){
                case JOptionPane.YES_OPTION:
                    saveFile();
                    break;
                case JOptionPane.NO_OPTION:
                    showFileDialog();
                    break;
                default:
                    break;
            }
        }
    }
    //保存
    private void saveFile() {
    }


    //输出问文件信息
    private void showFileDialog() {
        int option = fileChooser.showDialog(null, null);//文档选取对话框

        if(option == JFileChooser.APPROVE_OPTION){

            try {
                setTitle(fileChooser.getSelectedFile().toString());
                textArea.setText("");
                textArea.setText("未修改");
                String text = textDAO.read(fileChooser.getSelectedFile().toString());
                textArea.setText(text);
            } catch (Throwable e) {
                JOptionPane.showMessageDialog(null, e.toString(), "打开文档失败", JOptionPane.ERROR_MESSAGE);
            }
        }

    }
    //测试函数
    public static void main(String[] args) {
        //将建立的JNotePad实例与SetVisible()的动作排入事件队列
        //这玩意应该是一个Runnable接口的实现
        SwingUtilities.invokeLater( ()->{
            new JNotePad_demo2(new FileTextDAO()).setVisible(true);//true显示,false隐藏
        });
    }
}

TextDAO接口

/**
 * Created by butter on 16-11-21.
 */
public interface TextDAO {
    void    create(String file);
    void    save(String s, String file);
    String  read(String file);
}

FileTextDAO

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by butter on 16-11-21.
 */
public class FileTextDAO implements TextDAO {

    @Override
    public void create(String file) {
        try {
            Files.createFile(Paths.get(file));
        } catch (IOException e) {
            Logger.getLogger(
                    FileTextDAO.class.getName()).log(Level.SEVERE, null, e);
        }
    }

    @Override
    public void save(String file, String text) {
        try(BufferedWriter writer = Files.newBufferedWriter(
                Paths.get(file),
                Charset.forName(System.getProperty("file.encoding")))){

            writer.write(text);
        } catch (IOException e) {
            Logger.getLogger(FileTextDAO.class.getName()).log( Level.SEVERE,null,e);
        }
    }

    @Override
    public String read(String file) {
        byte[] datas = null;
        try {
            datas = Files.readAllBytes(Paths.get(file));
        } catch (IOException e) {
            Logger.getLogger(FileTextDAO.class.getName()).log(Level.SEVERE, null, e);
        }
        return new String(datas);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值