Java Swing图形化编程期末试题(附有注释)

/*Explorer*/
import javax.swing.SwingUtilities;

public class Explorer {//资源管理器
		public static void main(String args[]){
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					new MainFrame();//创建主机
				}
			});//等SwingUtilities.invokeLater()图形用户接口全部实现后,才能调用匿名内部类的线程,从而实现异步执行
		}
}

/*MainFrame*/
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;

public class MainFrame extends JFrame {//MainFrame继承JFrame窗体
		private MainPanel panel;//创建框架中的组件对象
		
		public MainFrame() {
			super("Explorer");//调用父类JFrame中的JFrame(String title)构造器,设置窗体框架的标题
			create();//创建窗体的布局和结构内容
		}
		
		private void create() {
			this.addWindowListener(new WindowAdapter() {
				@Override
				public void windowClosing(WindowEvent e){//窗口的关闭按钮被点击时调用的方法
					panel.onFinished();//调用MainPanel的onFinished()方法
					
					System.exit(0);//退出系统s
				}
			});//在窗口添加一个Windows事件消息,目的是我们关闭窗口的时候可以正常的退出,即当你的框架关闭时窗口能关闭。
			this.panel = new MainPanel();//创建一个面板对象,无参构造中create()方法实现面板的组件创造
			this.getContentPane().add(this.panel,BorderLayout.CENTER);//把刚刚创建的面板添加到主窗体的内容窗格中央
			//getContentPane():返回此框架的 contentPane对象。用getContentPane()方法获得JFrame的内容面板,再对其加入组件
			
			this.setLocationRelativeTo(null);//可写在this.pack()的下一行
			//设置窗口相对于指定组件的位置。如果组件当前未显示或者 c 为 null,则此窗口将置于屏幕的中央。

			this.setPreferredSize(new Dimension(800,600));//设置参照的窗体首选大小,自动调节比例大小*会考*
			this.pack();//告诉布局管理器,按照窗体首选大小进行内部布局调整
			
			this.setVisible(true);//让窗体显示			
		}
}


/*MainPanel*/
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MainPanel extends JPanel{
		private final FileQueue queue;
		
		private Thread scanner;//扫描线程
		
		private Thread render;//处理线程
		
		private JButton start;//启动按钮
		
		private JButton stop;//停止按钮(未完善)
		
		private JTextField where;//文本字段,单行
		
		private JTextArea logger;//文本区域。多行
		
		public MainPanel() {
			super();//一定要调用这个super()方法
			create();
			
			queue = new FileQueue();
		}
		
		public void create() {
			//框体网格布局设置
			this.setLayout(new GridBagLayout());//设置网格包布局管理器

			//设置单行文本字段
			where = new JTextField();
			GridBagConstraints gbc = new GridBagConstraints();//如何放置,是否扩展,即定制某些组件的相关约束对象,可重复使用
			gbc.gridx = 0;//网格第一行
			gbc.gridy = 0;//网格第一列
			gbc.weightx = 1;//权重是1,可随意设置,十分灵活
			gbc.fill = GridBagConstraints.HORIZONTAL;//将第一行第一列水平拉伸,往右挤。组件横向充满显示区域,但是不改变组件高度
			this.add(where,gbc);//按照指定布局限制添加组件。
			
			//设置文件目录浏览按钮
			JButton browse = new JButton("...");
			browse.addActionListener(new ActionListener() {//实现addActionListener里的参数接口ActionListener,重写ActionListener接口的actionPerformed方法
				//如果发生了点击事件,系统将会回调actionPerformed方法
				@Override
				public void actionPerformed(ActionEvent e) {
					JFileChooser fc = new JFileChooser();//创建文件选择器
					fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//设置选择模式,只能选择文件夹
					if(fc.showOpenDialog(browse) == JFileChooser.APPROVE_OPTION) {//弹出的文件选择框尽量靠近按钮,且当点击了确定或保存时
						File file = fc.getSelectedFile();//得到选择的目标文件信息
						where.setText(file.getAbsolutePath());//让文本目录的绝对路径显示在单行文本字段
					} 
					
				}
			});
			gbc.gridx = 1;
			gbc.weightx = 0;//不再拉伸
			gbc.fill = GridBagConstraints.NONE;//默认值
			this.add(browse,gbc);//把按钮添加到面板中
			
			//设置Start按钮
			start = new JButton("Start");
			start.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					logger.selectAll();//选择文本区域的所有行
					logger.replaceSelection("");//清空文本区域
					
					render = new Thread(new Render(queue,MainPanel.this));
					render.start();
					
					scanner = new Thread(new Scanner(queue,new File(where.getText())));
					scanner.start();
				}
			});
					gbc.gridx = 0;
					gbc.gridy = 1;
					gbc.anchor = GridBagConstraints.WEST;锚点,放置在最左边
					this.add(start,gbc);
					//设置Stop按钮
					stop = new JButton("Stop");
					gbc.gridx = 1;
					this.add(stop,gbc);
					
					//设置logger文本框
					logger = new JTextArea(10,20);
					logger.setEditable(false);//禁止编辑文本区域
					gbc.gridx = 0;
					gbc.gridy = 2;
					gbc.gridwidth = 2;//横跨2列
					gbc.weightx = 1;//水平拉伸
					gbc.weighty = 1;//垂直拉伸
					gbc.fill = GridBagConstraints.BOTH;//充满当前窗体剩下的所有区域
					this.add(new JScrollPane(logger),gbc);//使文本框可滚动浏览
				}
				
		public void onFilePair(FilePair pair) {//记录文本框要输出的父子对文件目录信息
					logger.append(pair.getParent().getAbsolutePath() + " : " + pair.getChild().getAbsolutePath() + "\n");
				}
				
		public void onFinished() {//结束线程
					this.render = null;
					this.scanner = null;
				}
			
}


/*FileQueue*/
import java.util.LinkedList;
import java.util.List;

public class FileQueue {//文件缓冲队列
	public static final Object RENDER = new Object();//作为Render类中的锁
	
	public static final Object SCANNER = new Object();//作为Scanner类中的锁
	
	private static final int LIMIT = 3;//共享队列queue的最大容量限制
	
	private final List<FilePair> queue;//共享数据列表queue,存放FilePair父子对
	
	private final Object locker;//队列对应的锁,控制读写
	
	public FileQueue() {
		this.queue = new LinkedList<>();//创建队列
		this.locker = new Object();//new一个锁对象
	}
	
	public boolean addPair(FilePair pair) {//写的操作
		//同步
		/*
		 * 对这个对象上锁,控制单一进程,执行代码块,如果共享队列queue存放FilePair对象个数大于2个就返回false,反之就将FilePair对象添加到队列中
		 * */
		synchronized (this.locker) {
			if(this.queue.size() >= LIMIT) {
				return false;
			}
			this.queue.add(pair);
			return true;
		}
	}
	/*
	 * 对这个对象上锁,控制单一进程,执行代码块,如果共享队列queue空就返回null,反之就可以读取队列中的FilePair数据对象并出队
	 * */
	public FilePair getPair() {//读的操作
		synchronized (this.locker) {
			if(this.queue.isEmpty()) {
				return null;
			}
			
			return this.queue.remove(0);//实现队列的队首数据的读取并出队
		}
	}
}


/*FilePair*/
import java.io.File;

public class FilePair {
		private final File parent;//文本字段选择器界面中选择到的初始目录
		private final File child;//根据初始目录扫描到的子目录
		
		public FilePair(File parent, File child) {//构造方法
			this.parent = parent;
			this.child = child;
		}
		//访问方法只设置读取
		public File getParent() {
			return this.parent;
		}
		
		public File getChild() {
			return this.child;
		}
}

/*Scanner*/
import java.io.File;

public class Scanner implements Runnable{//写者
		private final FileQueue queue;//队列的引用
		
		private final File where;//扫描的起始目录的引用
		
		public Scanner(FileQueue queue, File where) {
			this.queue = queue;
			this.where = where;
		}
		
		@Override
		public void run() {//线程的入口点
			boolean running = true;
			
			File[] files = where.listFiles();//返回子目录的文件数组
			for(File file : files){
				FilePair pair = new FilePair(where,file);//每个子目录与父目录创建父子对
						
				running = queue(pair);//将父子对放入输出队列中,若队列满了则返回true,break退出for循环,否则继续for循环
				if(!running) {
					break;
				}
			}
			
			FilePair pair = new FilePair(where,where);
			queue(pair);//为Reander类中run()方法的if条件语句判断做准备,使Scanner线程结束
		}
		
		private boolean queue(FilePair pair) {//读/写转换判断
			while(true) {
				if(this.queue.addPair(pair)) {//将FileQueue类中的addPair方法,将父子对放入输出队列中,如果队列满了
					synchronized (FileQueue.RENDER) {//加锁
						FileQueue.RENDER.notify();//若之前为阻塞状态,则通知转为等待状态
					}
					return true;
				}
				
				synchronized (FileQueue.SCANNER) {//加锁
					try {
							FileQueue.SCANNER.wait();//调用object类中的等待方法,转为等待状态
					}catch(InterruptedException e) {//若发生中断异常,则返回false
							return false;
					}
				}
			}
		}
		
}


/*Render*/
import javax.swing.SwingUtilities;

public class Render implements Runnable{//读者
		private final FileQueue queue;//创建文件队列
		
		private final MainPanel panel;//创建面板
		
		public Render(FileQueue queue, MainPanel panel) {
			this.panel = panel;
			this.queue = queue; 
		}
		
		@Override
		public void run() {//重写线程里的run()方法
			while(!Thread.interrupted()) {//如果没有被终断
				FilePair pair = this.queue.getPair();//获取文本字段选择器界面中选择到的初始目录
				if(pair != null) {//若文件对不为空
					if(pair.getParent() == pair.getChild()) {//若父子对相同,则扫描完毕
						SwingUtilities.invokeLater(new Runnable() {//更新图形用户接口
							@Override
							public void run() {
								panel.onFinished();//线程结束
							}
						});
						break;
					}else {//继续扫描
						SwingUtilities.invokeLater(new Runnable() {
							@Override
							public void run() {
								panel.onFilePair(pair);//得到输出内容
							}
						});
					}
					
					synchronized (FileQueue.SCANNER) {
						FileQueue.SCANNER.notify();//扫描线程由阻塞状态转化为等待状态
					}
					continue;
				}
				
				synchronized (FileQueue.RENDER) {
					try {
							FileQueue.RENDER.wait();//处理线程转化为等待状态
					}catch(InterruptedException e) {
						break;
					}
				}
			}
		}
}

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值