//Explorer.java import javax.swing.SwingUtilities; public class Explorer { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable(){ @Override public void run() { new Mainframe();//创建了一个Mainframe的实例,告诉线程后期再执行这一部分的代码。 } }); } } //Mainframe.java 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{ private MainPanel panel; public Mainframe() { super("Explorer");//调用了Jframe里的setTitle("");设置窗体标题,在swing要确保调用所有版本的窗类的构造方法 create(); } private void create() { this.addWindowListener(new WindowAdapter() {//设置一个窗口侦听器。 @Override public void windowClosing(WindowEvent e) { panel.onFinished();//关闭程序了就要清理数据 System.exit(0);//关闭程序并且退出 } }); this.panel=new MainPanel();//第一个视频22:46 this.getContentPane().add(this.panel,BorderLayout.CENTER); //getContentPane()获取内容窗格,this.getContentPane()获取的是一个Container的对象,也就是窗体容器(可以往里面添加组件) this.setPreferredSize(new Dimension(800,600));//调整首选窗口的大小!填空 this.pack();//与setPreferredSize()同时使用,如果没有pack().则setPreferredSize()不起作用 this.setLocationRelativeTo(null);//让窗体在屏幕上居中显示 //this.setLocationRelativeTo(null);应该放在this.pack();之后,因为应该设置好窗体的大小,才能居中显示 this.setVisible(true); } } //MainPanel.java import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; 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;//按钮start private JButton stop;//按钮stop这里没做什么事情 private JTextField where;//文本框 private Jtextarea logger;//文本区,多行文本空间 public MainPanel() { super();//在swing要确保调用所有版本的窗类的构造方法,否则不会正常显示!!! create(); queue=new FileQueue(); } private void create() { this.setLayout(new GridBagLayout());//JPanel的布局管理器默认为FlowLayout流式布局管理器,这里设置为网格组布局管理器 where=new JTextField();//文本框 GridBagConstraints gbc=new GridBagConstraints();//组件的设置 gbc.gridx=0;//起始位置为第0咧 gbc.gridy=0;//起始位置为第0杭 gbc.weightx=1;//权重设置为1不理解?? gbc.fill=GridBagConstraints.HORIZONTAL;//HORIZONTAL为只调整组件水平方向的大小(即组件宽度)至填满显示区域,水平拉伸 this.add(where,gbc); JButton browse =new JButton("...");//按钮上的文本标签 browse.addActionListener(new ActionListener() {//添加一个动作侦听器,当按钮被调用的时候会调用侦听器里的方法,只有点击才会执行 //@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=new JButton("Start");//设置“start”按钮 start.addActionListener(new ActionListener() { //@override public void actionPerformed(ActionEvent e) { logger.selectAll();//选择文本区全部空间 logger.replaceSelection("");//用传递的参数空文本来替换文本区内容 //相当于删除文本区全部内容 //启动之前删除内容 render=new Thread(new Render(queue,MainPanel.this));//创建线程 //render实现了Runnable接口 render.start();//启动线程 scanner=new Thread(new Scanner(queue,new File(where.getText())));//创建线程 //scanner实现了Runnable接口 scanner.start(); } }); gbc.gridx=0;//设置成第0行 gbc.gridy=1;//设置成第一列 gbc.anchor=GridBagConstraints.WEST;//默认为center,将start按钮放在最左边 //anchor锚点设置一个基准点 this.add(start,gbc);//将设置好的start按钮添加到面板 stop=new JButton("Stop");//对stop不做处理,应该判断线程是否正在运行, gbc.gridx=1; this.add(stop,gbc); logger=new Jtextarea(10,20);//指定10行20列,初始值 logger.setEditable(false);//禁止编辑,文本区域不可以编辑,默认是可以编辑的。 gbc.gridx=0;//第0列 gbc.gridy=2;//第2行 gbc.gridwidth=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.java import java.util.linkedList; import java.util.List; public class FileQueue { public static final Object RENDER=new Object();// public static final Object SCANNER=new Object(); private static final int LIMIT=100;//模拟队列是3,超过3就需要等待 private final Listqueue;//列表,FilePair private final Object locker;//表示队列对应的锁。一个往里面写,一个从里面读,需要互斥的访问 public FileQueue() { this.queue=new linkedList<>(); this.locker=new Object(); } public boolean addPair(FilePair pair) {//供扫描线程使用 synchronized(this.locker) {//同步synchronized对应的锁。当一个线程访问locker的时候其他任何的线程都将被阻塞 if(this.queue.size()>=LIMIT) {//如果其他线程拿到这个锁,就会被OS踢到阻塞队列里,直到被唤醒 return false; } this.queue.add(pair);//如果没有被加锁就可以进来。 return true; } } public FilePair getPair() {//供读者 synchronized(this.locker) {//供render使用 if(this.queue.isEmpty()) { return null; } } return this.queue.remove(0);//删除第一个元素,并将引用返回。 } } //FilePair.java 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; } } //Render.java import javax.swing.SwingUtilities; public class Render implements Runnable{ private final FileQueue queue; private final MainPanel panel; public Render(FileQueue queue,MainPanel panel) { this.queue=queue; this.panel=panel; } //@override public void run() { while(!Thread.interrupted()) {//没有被中断 currentThread().isInterrupted()中的isInterrupted()是静态方法,需要currentThread()去调用 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; } } } } } //Scanner.java 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;//假设没有扫描完毕running初始为true File[] files =where.listFiles();//返回的是一个File的数组,是当前目录子目录的文件数组 for(File file:files) {//对于数组中的元素进行处理,如果遇到子目录就往下扫描 FilePair pair=new FilePair(where,file); running =queue(pair); if(!running) { break; } } FilePair pair=new FilePair(where,where);//为Render类中的判断父目录是否与子目录相同,这个时候传入的参数都是where queue(pair); //running=queue(pair); } private boolean queue(FilePair pair) { while(true) { if(this.queue.addPair(pair)) { synchronized(FileQueue.RENDER) {//等待SCANNER向RENDER通知,没有加锁调用通知会抛出异常 FileQueue.RENDER.notify();//这里只有一个RENDER,只需要使用notify(),将阻塞队列里的线程提到就绪队列里 } return true; } synchronized(FileQueue.SCANNER) { try { FileQueue.SCANNER.wait(); }catch(InterruptedException e) { return false;//如果被中断,break } } } } }
代码相关的补充知识点:
1.RunnableJava多线程:
一个Java就是一个进程,一条线程就是进程中一个单一顺序控制流,一个进程可以并发对个线程,每条线程并行执行不同的任务。
创建一个线程,最简单的方法就是创建一个实现Runnable接口的类。
实现多线程的方法:extends Thread、implements Runnable
还有一种就是由第二种变形而来的new Runnable(){}
为了实现Runnable,一个类只需要执行以一个方法调用run()
但是Runnable是一个接口,接口和抽象类不能被实例化,但是new Runnable(){}其实不是实例化Runnable接口来的,实际上是一种内部类的简写
1.首先构造了一个implements Runnable的无名local内部类(方法内的内部类)
2.构造这个无名local内部类的一个实例
3.然后用Runnable来表示这个无名local内部类type
创建一个实现Runnable接口的类之后,可以在类中实例化一个线程对象,利用Thread定义
最常用的:
Thread thread=Thread(Runnable threadOb,String threadName);
这里的threadOb是实现Runnable接口的类的一个实例,并且threadName指定新线程的名字。
新线程创建之后需要调用start()方法它才会运行。
Thread构造方法解释?
2.swing是什么相关学习内容CSDN已收藏
早期GUI的基础类库AWT(Abstract Window Toolkit)抽象窗口工具包。
swing是一种轻量级组件,底层以AWT为基础。
swing类结构:
3.Object类
object类是所有类的父类,当一个类没有明确指定一个父类的话,这个类的就是Object的子类
4.synchronizedsynchronized是Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。
当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍可以访问该object中的非加锁代码块。
对synchronized的内容保持互斥访问,只能允许一个线程的访问。synchronized锁定的是对象。不同对象访问被synchronized的部分不会产生互斥的现象。
5.SwingUtilities.invokeLater ·事件分发线程Swing中事件处理和绘画代码都在一个单独的线程中执行,这个线程就是事件分发线程。
为了避免线程问题,建议你使用invokeLater在事件分发线程中为所有新应用程序创建GUI。
在任何的线程中调用invokeLater来请求事件分发线程来运行某段代码。必须将这段代码放入一个Runnable对象的run方法中,并将该指定Runnable对象作为参数传递给invokeLater。invokeLater函数会立即返回,不会等到事件分发线程执行完这段代码。
6.java.swing.JframeSwing 的三个基本构造块:标签、按钮和文本字段;但是需要个地方安放它们,并希望用户知道如何处理它们。Jframe 类就是解决这个问题的——它是一个容器,允许程序员把其他组件添加到它里面,把它们组织起来,并把它们呈现给用户。 Jframe 实际上不仅仅让程序员把组件放入其中并呈现给用户。比起它表面上的简单性,它实际上是 Swing 包中最复杂的组件。为了最大程度地简化组件,在独立于 *** 作系统的 Swing 组件与实际运行这些组件的 *** 作系统之间,Jframe 起着桥梁的作用。Jframe 在本机 *** 作系统中是以窗口的形式注册的,这么做之后,就可以得到许多熟悉的 *** 作系统窗口的特性:最小化/最大化、改变大小、移动。
Jframe就是建立一个窗体。(相当于一个容器。对就是一个容器,然后将其他的component组件添加到这里面。)
Jframe窗体的常用方法
1、Jframe frame=new Jframe();//创建frame窗体,参数可以定义窗体的名字 2、setTitle("");//设置窗体标题 ,直接输入标题字符串即可 3、setVisible();//设置窗体是否可见,true:可见,false:不可见 4、setDefaultCloseOperation();//设置窗体关闭方式,关闭方式如下(点击窗体上的关闭按钮x):
1. EXIT_ON_CLOSE:关闭窗体,并停止程序 2. HIDE_ON_CLOSE:隐藏窗体,不停止程序 3. DISPOSE_ON_CLOSE:释放窗体资源 4. DO_NOTHING_ON_CLOSE:什么都不做
5、setSize();//设置窗体大小,单位:像素 6、setLocation();//设置窗体左上角的坐标,单位:像素 7、setBounds();//设置窗体的坐标和大小(前两个参数设置坐标,后两个参数设置大小),单位:像素 8、Container container=getContentPane();//获取窗体容器!!! 9、container.add();//往容器中添加组件
this.getContentPane().add(frame,BorderLayout.CENTER);
10、container.setBackground();//设置窗体背景颜色 11、container.remove();//从容器中删除组件 12、container.validate();//验证容器中的组件,即刷新容器 13、setContentPane(container);//重新载入容器,也起到了刷新的作用 14、setResizable();//设置窗体是否可以更改其大小,true:可以更改,false:不可以更改 15、JPanel p=new JPanel();//创建面板组件,参数可以设置布局管理器 16、JScrollPane js=new JScrollPane();//创建滚动面板,参数可填入需要添加进滚动面板的组件,如文本框 17、JLabel jl=new JLabel();//创建标签组件,参数可填入标签的内容,图片属于标签组件 18、JTextField jt=new JTextField();//创建文本框组件,参数可填入文本框的初始内容 19、Jtextarea area=new Jtextarea();//创建文本域组件,参数可填入文本域的初始内容以及文本域大小(几行几列) 20、JButton btn=new JButton();//创建按钮组件,参数可填入按钮的名称(即按钮上面显示的内容) 21、JRadioButton rbtn=new JRadioButton();//创建单选按钮组件,参数可填入按钮的名称(也可理解为选项的名称或选项内容) 22、JCheckBox cb=new JCheckBox();//创建复选框组件,参数可填入复选框名称 23、JComboBox comboBox=new JComboBox();//创建下拉列表组件,创建格式为:
JComboBoxcomboBox=new JComboBox<>();
其中String为下拉框中的数据格式,如果你的列表中有多种数据格式,那么你也可填为Object 24、JList jl=new JList();//创建列表框组件,参数可以为一个字符串数组,如
String contents[]={"列表1","列表2","列表3"}; JList jl=new JList(contents);7.事件模型相关概念
事件:描述发生了什么的对象。存在各种不同类型的事件类用来描述各种类型的用户交互。
事件源:事件的产生器。
事件处理器:接收事件、解释事件并处理用户交互的方法。
比如Button组件上点击鼠标产生????
如果用户在用户界面层执行了一个动作(鼠标点击和按键),这将导致一个事件的发生。
8.this.addWindowListener(new WindowAdapter() {});以下代码:
frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0);//退出系统 } });
这个是表示在窗口添加一个Windows事件消息,目的是我们关闭窗口的时候可以正常的退出,其实这段语句等价于
frame.setDefaultCloseOptration(Jframe.EXIT_ON_CLOSE);
在这段语句中new WindowAdapter表示新的创建WindowAdapter的对象
中间是对一个函数也就是windows窗口关闭函数进行重写。
9.WindowListener是一个接口,主要作用就是接收窗口事件的侦听器接口。
主要方法:
1.public void windowClosed(WindowEvent e){} 窗口被完全关闭时调用的方法 2. public void windowDeactivated(WindowEvent e){} 窗口失去活性时调用的方法 3.public void windowActivated(WindowEvent e){} 窗口被完全激活时调用的方法 4. public void windowIconified(WindowEvent e){} 窗口被最小化时调用的方法 5. public void windowDeiconified(WindowEvent e){} 窗口被从最小化还原时调用的方法 6. public void windowOpened(WindowEvent e){} 窗口被完全激活时调用的方法 7.public void windowClosing(WindowEvent e){} 窗口的关闭按钮被点击时调用的方法 10.java.awt.BorderLayout(边界布局)
BorderLayout布局管理器为在一个Panel或Window中放置组件提供一
个更复杂的方案。BorderLayout布局管理器包括五个明显的区域:东、南、
西、北、中。
import java.awt.*; public class ExGui2 { private frame f; private Button bn, bs, bw, be, bc; public static void main(String args[]) { ExGui2 guiWindow2 = new ExGui2(); guiWindow2.go(); } public void go() { f = new frame("Border Layout"); bn = new Button("B1"); bs = new Button("B2"); be = new Button("B3"); bw = new Button("B4"); bc = new Button("B5"); f.add(bn, BorderLayout.NORTH); f.add(bs, BorderLayout.SOUTH); f.add(be, BorderLayout.EAST); f.add(bw, BorderLayout.WEST); f.add(bc, BorderLayout.CENTER); f.setSize(200, 200); f.setVisible(true); } }
11.Jframe.pack()
pack() 调整此窗口的大小,以适合其子组件的首选大小和布局 单独使用setSize()时,不能使用pack(),否则按照pack()自动适配
单独使用pack()时,是按照组件的大小自动适配的
单独使用setPreferredSize()时,设置的大小无效,必须在后面添加pack()配合显示,否则设置效果不生效
12.java.awt.Dimension如果一容器使用了布局管理器,则该容器内的组件或容器(即该容器的下一级)应该使用setPreferredSize(new Dimension(w,h));来设置尺寸;
w,h为像素。
13.Container容器类分为两种类型Window和Panel
Window:不依赖其他容器而独立存在的容器,有两个子类:
frame:用于创建一个具有标题栏的框架窗口,作为程序的主界面
Dialog:用于创建一个对话框,实现与用户的信息交互
Panel:也是一个容器,不能单独存在,只能存在于其他容器(Window或其子类)。一个Panel对象代表了一个长方形的区域,在这个区域里可以容纳其他组件。在程序中通常会使用Panel来实现一些特殊的布局。
14.JPanel一个界面只能有一个Jframe窗体组件,但是可以有多个JPanel面板组件。
整体的构造:
JPanel相当于将整个窗体划分成几个面板,然后在面板里使用布局管理器。
注意:
1.Jpanel是Jcomponent的子类
2.属于容器类组件,可以加入别的组件
3.默认布局管理器:流式布局(FlowLayOut)
15.布局管理器 绝对布局步骤:
使用Container.setLayout(null);//方法取消布局管理器 使用Component.setBounds()//方法设置每个组件的大小与位置 setLayout(GridbagLayout);//设置网格组布局管理器流布局管理器
像“流”一样从左到右摆放组件,直到占据了这一行的所有空间,然后再向下移动一行。默认情况下,组件在每一行上都是居中排列的,但是通过设置也可以更改组件在每一行上的排列位置。
**FlowLayout**类中具有以下常用的构造方法:
public FlowLayout() public FlowLayout(int alignment) public FlowLayout(int alignment, int horizGap, int vertGap)
构造方法中的alignment参数表示使用流布局管理器后组件在每一行的具体摆放位置。alignment为0时,每一行的组件将被指定按照左对齐排列;alignment为2时,每一行的组件将被指定按照右对齐排列;alignment为1时,每一行的组件将被指定按照居中对齐排列; horizGap与vertGap参数分别以像素为单位指定组件之间的水平间距与垂直间距。
边界布局管理器在默认不指定窗体布局的情况下,Swing组件的布局模式是BorderLayout布局管理器。边界布局管理器可以将容器划分为东、南、西、北、中5个区域,可以将组件加入到这5个区域中。容器调用Container类的add()方法添加组件时可以设置此组件在边界布局管理器中的区域,区域的控制可以由BorderLayout类中的成员变量来决定。
网格布局管理器将容器划分为网格,所以组件可以按行和列进行排列。在网格布局管理器中,每一个组件的大小都相同,并且网格中的空格的个数由网格的行数和列数决定。组件从网格的左上角开始,按照从左到右、从上到下的顺序加入到网格中,而且每一个组件都会填满整个网格,改变窗体的大小,组件也会随之而改变大小。
Public GridLayout(int rows, int columns) Public GridLayout(int rows, int columns, int horizGap, int vertGap)
Rows与columns参数代表网格的行数与列数,只能一个参数可以为0,代表一行或一列可以排列人一多个组件。horizGap与vertGap指定网格之间的间距。
箱式布局管理器由BoxLayout类实现的布局管理器称为箱式布局管理器,用来管理一组水平或垂直排列的组件,如果是用来管理一组水平排列的组件,则称为水平箱,如果是用来管理一组垂直排列的组件,则称为垂直箱。
构造方法BoxLayout(Container target,int axis)(frame对象调用getContentPane()就可以得到Container对象,Container对象可以调用add()向容器里添加组件。)参数target为要采用该布局方式的容器对象,参数axis为要采用的布局方式,如设置为静态常量X_AXIS表示创建一个水平箱,组件从做到右排列,若为Y_AXIS则表示创建一个垂直箱,组件从上到下排列。无论是水平箱还是垂直箱,当窗体调小至不能显示所有组件时,组件仍会排列在一行或一列,组件按添加到容器中的先后顺序进行排列。
(待补充)
网格组布局管理器由GridBagLayout类实现的布局管理器称为网格组布局管理器,它实现了一个动态的矩形网格,这个矩形网格由无数个矩形单元格组成,每个组件可以占用一个或多个这样的单元格。所谓动态的矩形网格,就是可以根据实际需要随意增减矩形网格的行数和列数。
在向由GridBagLayout类管理的容器中添加组件时,需要为每个组件创建一个与之关联的GridBagConstraints类的对象,通过该类中的属性可以设置组件的布局信息,例如组件在网格组中位于第几行、第几列,以及需要占用几行几列等。
通过GridBagLayout类实现的矩形网格的绘制方向由容器决定,如果容器的方向是从左到右,则位于矩形网格左上角的单元格的列索引为0,此时组件左上角的点为起始点;如果容器的方向是从右到左,则位于矩形网格右上角的单元格的列索引为0,此时组件右上角的点为起始点。
GridBagLayout类中各个属性的功能和使用方法gridx和gridy属性
这两个属性用来设置组件起始点所在单元格的索引值。需要注意的是,属性gridx设置的是X轴(即网格水平方向)的索引值,所以它表示的是组件起始点所在列的索引;属性gridy设置的是Y轴(即网格垂直方向)的索引值,所以它表示的是组件起始点所在行的索引。
gridwidth和gridheight属性
这两个属性用来设置组件占用网格组的行数和列数。属性gridwidth为组件占用网格组的列数,也可以理解为以单元格为单位组件的宽度;属性gridheight为组件占用网格组的行数,也可以理解为以单元格为单位组件的高度。
anchor属性
属性anchor用来设置组件在其所在显示区域的显示位置。通常将显示区域从方向上划分为9个方位,分别为北方(NORTH)、东北(NORTHEAST)、东方(EAST)、东南(SOUTHEAST)、南方(SOUTH)、西南(SOUTHWEST)、西方(WEST)、西北(NORTHWEST)和中心(CENTER)。 九个方位的单词是该类的静态常量,静态常量CENTER为默认值。
fill属性
属性fill用来设置组件的填充方式。当单元格显示区域的面积大于组件面积时,或者一个组件占用多个单元格时,显示组件可能不必占用所有显示区域,在这种情况下可以通过fill属性设置组件的填充方式。默认情况下是将该属性设置为静态常量NONE,即不调整组件大小至填满显示区域;HORIZONTAL为只调整组件水平方向的大小(即组件宽度)至填满显示区域;VERTICAL为只调整组件垂直方向的大小(即组件高度)至填满显示区域;BOTH为同时调整组件的宽度和高度至填满显示区域。
insets属性
属性insets用来设置组件四周与单元格边缘之间的最小距离。该属性的类型为Insets,Insets类仅有一个构造方法Insets(int top, int left, int bottom, int right),它的4个入口参数依次为组件上方、左侧、下方和右侧的最小距离,单位为像素,默认为没有距离。
ipadx和ipady属性
这两个属性用来修改组件的首选大小。属性ipadx用来修改组件的宽度,属性ipady用来修改组件的高度。如果为正数,则在首选大小的基础上增加指定的宽度和高度。如果为负数,则在首选大小的基础上减小指定的宽度和高度。
weightx和weighty属性
这两个属性用来设置网格组的每一行和每一列对额外空间的分布方式。在不设置属性weightx和weighty(即采用默认方式)的情况下,当窗体调整到足够大时,组件全部聚集在窗体的中央,在组件四周出现了大片的额外空间。通过这两个属性设置网格组的每一行和每一列对额外空间的分布方式可避免此现象。 这两个属性的默认值均为0,表示不分布容器的额外空间。属性weightx用来设置器所在列对额外空间的分布方式,如果该列中设置多个weightx属性,则取他们的最大值为该列的分布方式;weighty属性与之类似。
在设置网格组的每一行和每一列对额外空间的分布方式时,只设置第一行的weightx属性和第一列的weighty属性,这样会方便前期调试和后期维护。 在设置网格组的每一行和每一列对额外空间的分布方式时,为各个属性按百分比取值。
d簧布局管理器待补充
16.java.awt.eventjava.awt.event.ActionEvent对应按钮点击、菜单选择、选择列表项或者在文本域中输入enter
监听接口:ActionListener
17.public void actionPerformed(ActionEvent e)这是接口ActionListener里面定义的一个抽象方法,所有实现这个接口的类都要重写这个方法。 一般情况下,这是在编写GUI程序时,组件发生“有意义”的事件时会调用这个方法,比如按钮被按下,文本框内输入回车时都会触发这个事件,然后调用你编写的事件处理程序。 实现过程大体如下:编写一个ActionListener类的侦听器,组件注册该侦听器,侦听器内部要编写这个actionPerformed方法。
18.javax.swing.JFileChooser(文件选择器)JFileChooser,文件选取器。JFileChooser为用户选择文件提供了一种简单的机制,包括 打开文件 和 保存文件。
JFileChooser() JFileChooser(File currentDirectory) JFileChooser(String currentDirectoryPath)
常用的方法:
// 设置默认显示的文件夹 void setCurrentDirectory(File dir) // 设置文件选择模式, 可选值如下: // JFileChooser.FILES_ONLY: 只能选文件 // JFileChooser.DIRECTORIES_ONLY: 只能选文件夹 // JFileChooser.FILES_AND_DIRECTORIES: 文件和文件夹都可以选 void setFileSelectionMode(int mode) // 设置是否允许同时选择多个(默认为不允许) void setMultiSelectionEnabled(boolean b) // 添加可供用户选择的文件过滤器 void addChoosableFileFilter(FileFilter filter) // 设置默认使用的文件过滤器 void setFileFilter(FileFilter filter) // 设置默认被选中的文件 void setSelectedFile(File file) void setSelectedFiles(File[] selectedFiles) int showOpenDialog(Component parent) int showSaveDialog(Component parent) // 获取选择的文件(一般在用户选择完文件点击了确认或保存后通过该方法获取选中的文件) File getSelectedFile() File[] getSelectedFiles() 19.JScollPane
1,简介 JScrollPane是一个滚动面板,只能添加一个组件(例如在Swing中,像Jtextarea、JList、JTable等组件),但是我们可以添加一个面板JPanel, 然后再把很多组件添加到JPanel上。
2,布局 a,边界布局BorderLayout中,发现添加JPanel时,发现不能使用add()方法 例如:
//添加Jscrollpane滚动,只能用 JScrollPane scrollPane = new JScrollPane(panel); //不能使用 //scrollPane.add(panel);20.notify()
notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。区别:
-
notifyAll使所有原来在该对象上等待被notify的所有线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
-
notify则文明得多,它只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁此时如果该对象没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。
string [] list()//返回一个字符串数组,这些字符串数组指定此抽象路径名表示的目录中的文件和目录 File [] listFiles()//返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)