Java -Swing-学习笔记
文章目录
Java -Swing-学习笔记1. 基本组件2. 特殊容器2.1 JSplitPane2.2 JTabbedPane2.3 JLayeredPane、JDesktopPane、JInternalFrame
3.拖放功能4.Java7新增的Swing功能4.1 用JLayer装饰组件4.2 透明、不规则形状窗口
5.用JProgressBar、ProgressMonitor、BoundedRangeModel创建进度条5.1 JProgressBar5.2 ProgressMonitor
6.JSlider、BoundedRangeModel创建滑动条7.JSpinner和SpinnerModel创建微调控制器8.JList、JComboBox创建列表框9.JTree和TreeModel创建树10.JTable、TableModel创建表格11.JFormattedTextField和JTextPane创建格式文本
1. 基本组件
(主要参考《疯狂Java》) (难受啊,写了一天的学习笔记结果第二天发现没保存,心态崩了,不重新写了)
2. 特殊容器
2.1 JSplitPane
2.2 JTabbedPane
2.3 JLayeredPane、JDesktopPane、JInternalFrame
JDesktopPane为JLayeredPane的子类,它更加常见,它可以启动多个内部窗口来显示信息(如Eclipse、EditPlus等)。Windows下这种用户界面称为多文档界面(Mulitple Doccument Interface)。
JDesktoppane需要和JInternalFrame结合使用,JDesktopPane代表一个虚拟桌面,JInternalFrame则用于创建内部窗口。如下:
import javax.swing.*;
import java.awt.*;
import java.beans.PropertyVetoException;
public class JInternalFrame_test {
public void init(){
var jf=new JFrame("test");
var jdp=new JDesktopPane();
var jp=new JPanel();
var jb=new JButton("click");
var jip=new JInternalFrame("new doc",true,true,true,true);
jip.reshape(20,20,400,400);
var jipp=new JPanel();
for(int x=0;x<5;x++)
jipp.add(new JButton("button "+x));
jipp.add(new JTextField(5));
jip.add(jipp);
jp.add(jb);jp.add(jdp);
jdp.add(jip);
jdp.setPreferredSize(new Dimension(400,400));//设置尺寸,必要的步骤
jb.addActionListener(e->{jip.show();System.out.println("click");
try {
jip.setMaximum(false);
jip.setIcon(false);
jip.reshape(20,20,200,200);//必要的
} catch (PropertyVetoException ex) {
ex.printStackTrace();
}
});
jf.add(jp);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);jf.pack();
}
public static void main(String[] args){new JInternalFrame_test().init();}
}
3.拖放功能
Swing中支持拖放操作的组件如下表
Swing 组件作为拖放源导出作为拖放目标接收JColorChooser导出颜色对象的本地应用可接受任何颜色JFileChooser导出文件列表无JList导出所选节点的HTML描述无JTable导出所选中的行无JTree导出所选择节点的HTM描述无JTextComponent导出所选文本接受文本,子类JTextArea还可接受文件列表,负责将文件打开
Swing默认不启动拖放,需要手动设置。
import javax.swing.*;
import java.awt.*;
public class drag_test {
public void init(){
var jf=new JFrame("test");
var jta=new JTextArea(5,30);jta.setDragEnabled(true);
var jp=new JPanel();
var jtf=new JTextField(40);jtf.setDragEnabled(true);
String[] strs={"1","2","3","4"};
var jl=new JList(strs);jl.setDragEnabled(true);
var jt=new JTable();jt.setDragEnabled(true);
jp.add(jta);jp.add(jtf);jp.add(jl);jp.add(jt);
jf.add(jp);
jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args){new drag_test().init();}//
}
4.Java7新增的Swing功能
4.1 用JLayer装饰组件
JLayer可以在指定组件上额外添加一个装饰层。JLayer一般和LayerUI一起使用,LayerUI用于扩展(需要重写他的paint方法),
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*;
public class JLayout_test {
public void init(){
var jf=new JFrame("test");
var p=new JPanel();
var bg=new ButtonGroup();
JRadioButton[] jrs=new JRadioButton[4];
int y=0;
for (var jr:jrs){
p.add(jr=new JRadioButton("item"+y++,y==1));
bg.add(jr);
}
p.add(new Button("b1"));
LayerUI layerUI=new layui();
var layer=new JLayer(p,layerUI);
jf.add(layer);
//jf.add(p);
jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class layui extends LayerUI{
public void paint(Graphics g,JComponent c){
super.paint(g,c);
var g2=(Graphics2D) g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.5f));
g2.setPaint(new GradientPaint(0,0,Color.RED,0,c.getHeight(),Color.BLUE));
g2.fillRect(0,0,c.getWidth(),c.getHeight());
g2.dispose();
}
}
public static void main(String[] args){
new JLayout_test().init();
}
}
由于重写paint,我们可以自由的绘制图形界面,怎么来都行,如可以添加模糊效果、探照灯效果、可以响应鼠标动作绘制动画(用定时器控制LayerUI上绘制的图行动态地改变)。
如下面代码实现的探照灯效果:
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
public class JLayout_test {
public void init(){
var jf=new JFrame("test");
var p=new JPanel();
var bg=new ButtonGroup();
JRadioButton[] jrs=new JRadioButton[4];
int y=0;
for (var jr:jrs){
p.add(jr=new JRadioButton("item"+y++,y==1));
bg.add(jr);
}
p.add(new Button("b1"));
LayerUI layerUI=new layui();
var layer=new JLayer(p,layerUI);
jf.add(layer);
//jf.add(p);
jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class layui extends LayerUI{
private boolean active;
private int cx,cy;
public void installUI(JComponent c){
super.installUI(c);
var layer=(JLayer) c;
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
public void uninstallUI(JComponent c){
var layer=(JLayer) c;
layer.setLayerEventMask(0);
super.uninstallUI(c);
}
public void paint(Graphics g,JComponent c){
var g2=(Graphics2D) g.create();
super.paint(g,c);
if(active){
Point2D center=new Point2D.Float(cx,cy);
float radius=72;
float[] dist={0.0f,1.0f};
Color[] colors={Color.YELLOW,Color.BLACK};
var p=new RadialGradientPaint(center,radius,dist,colors);
g2.setPaint(p);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.6f));
g2.fillRect(0,0,c.getWidth(),c.getHeight());
}
//g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.5f));
//g2.setPaint(new GradientPaint(0,0,Color.RED,0,c.getHeight(),Color.BLUE));
//g2.fillRect(0,0,c.getWidth(),c.getHeight());
g2.dispose();
}
public void processMouseEvent(MouseEvent e,JLayer layer){
if (e.getID()==MouseEvent.MOUSE_ENTERED)
active=true;
if(e.getID()==MouseEvent.MOUSE_EXITED)
active=false;
layer.repaint();
}
public void processMouseMotionEvent(MouseEvent e,JLayer layer){
Point p=SwingUtilities.convertPoint(e.getComponent(),e.getPoint(),layer);
cx=p.x;cy=p.y;
layer.repaint();
}
}
public static void main(String[] args){
new JLayout_test().init();
}
}
如下代码实现动态效果:
import javax.swing.*;
import javax.swing.plaf.LayerUI;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
public class JLayout_test {
public void init(){
var jf=new JFrame("test");
var p=new JPanel();
var bg=new ButtonGroup();
JRadioButton[] jrs=new JRadioButton[4];
int y=0;
for (var jr:jrs){
p.add(jr=new JRadioButton("item"+y++,y==1));
bg.add(jr);
}
var b1=new JButton("start");
var b2=new JButton("stop");
p.add(b1);p.add(b2);
var layerUIs=new layui();
var layer=new JLayer(p,layerUIs);
jf.add(layer);
b1.addActionListener(ae->{
layerUIs.start();
});
b2.addActionListener(ae-> layerUIs.stop());
//jf.add(p);
jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class layui extends LayerUI{
private Boolean isRunning=false;
private Timer timer;
private int angle;
public void paint(Graphics g,JComponent c){
super.paint(g,c);
int w=c.getWidth(),h=c.getHeight();
if(!isRunning)
return;
var g2=(Graphics2D) g.create();
Composite urComposite =g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.5f));
g2.fillRect(0,0,w,h);
g2.setComposite(urComposite);
var s=Math.min(w,h)/5;
var cx=w/2;var cy=h/2;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(s/2,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
g2.setPaint(Color.BLUE);
g2.rotate(Math.PI*angle/180,cx,cy);
for (var i=0;i<12;i++){
float scale=(11.0f-(float) i)/11.0f;
g2.drawLine(cx+s,cy,cx+s*2,cy);
g2.rotate(-Math.PI/6,cx,cy);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,scale));
}
g2.dispose();
}
public void start(){
if(isRunning)
return;
isRunning=true;
timer=new Timer(100,e->{
firePropertyChange("crazyitFlag",0,1);
angle+=6;
if(angle>=360)
angle=0;
});
timer.start();
}
public void stop(){
isRunning=false;
firePropertyChange("crazyitFlag",0,1);
timer.stop();
}
public void applyPropertyChange(PropertyChangeEvent pce,JLayer layer){
if(pce.getPropertyName().equals("crazyitFlag"))
layer.repaint();
}
}
public static void main(String[] args){
new JLayout_test().init();
}
}
4.2 透明、不规则形状窗口
setShape(Shape shape):设置窗口的形状setOpacity(float opacity):设置窗口的透明度
import javax.swing.*;
import java.awt.geom.Ellipse2D;
public class drag_test {
public void init(){
var jf=new JFrame("test");
var jta=new JTextArea(5,30);jta.setDragEnabled(true);
var jp=new JPanel();
var jtf=new JTextField(40);jtf.setDragEnabled(true);
String[] strs={"1","2","3","4"};
var jl=new JList(strs);jl.setDragEnabled(true);
var jt=new JTable();jt.setDragEnabled(true);
jp.add(jta);jp.add(jtf);jp.add(jl);jp.add(jt);
jf.add(jp);
jf.setUndecorated(true);//必要的
jf.setOpacity(0.8f);
jf.setShape(new Ellipse2D.Double(0,0,jf.getWidth(),jf.getHeight()) );
jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args){new drag_test().init();}//
}
5.用JProgressBar、ProgressMonitor、BoundedRangeModel创建进度条
5.1 JProgressBar
很简单,直接看下面的实例吧:
import javax.swing.*;
import java.awt.*;
public class progressbar_test {
public void init(){
var jf=new JFrame("test");
var jp=new JPanel();
var bar=new JProgressBar(JProgressBar.VERTICAL,0,100);
var jb_start=new JButton("start");
var jb_stop=new JButton("stop");
var jbshow=new JButton(" ");
jp.add(jb_start);jp.add(bar);jf.add(jp);jp.add(jb_stop);jp.add(jbshow);
bar.addChangeListener(e->{jbshow.setText(bar.getValue()+"%");
if(bar.getValue()==bar.getMaximum())
jbshow.setText("ok");
});
var timer=new Timer(100,e->{
if(bar.getValue()!=bar.getMaximum())
bar.setValue(bar.getValue()+1);
});
jb_start.addActionListener(e->{
if(timer.isRunning())
return;
timer.start();
});
jb_stop.addActionListener(e->timer.stop());
jf.pack();jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);
}
public static void main(String[] args){new progressbar_test().init();}
}
5.2 ProgressMonitor
ProgressMonitor可以直接创建一个进度对话框:
final ProgressMonitor dialog=new ProgressMonitor(f,"wait","note",0,max);
如下:
import javax.swing.*;
import java.awt.*;
public class progressbar_test {
int y=0;Timer timer;
public void init(){
var jf=new JFrame("test");
var jp=new JPanel();
var bar=new JProgressBar(JProgressBar.VERTICAL,0,100);
ProgressMonitor dialog=new ProgressMonitor(jf,"wait","progress:",0,100);
var jb_start=new JButton("start");
var jb_stop=new JButton("stop");
var jbshow=new JButton(" ");
jp.add(jb_start);jp.add(bar);jf.add(jp);jp.add(jb_stop);jp.add(jbshow);
timer=new Timer(100,e->{
if(!dialog.isCanceled()){
dialog.setProgress(y++);
dialog.setNote("已完成:"+y+"%");
}
else
timer.stop();
});
jb_start.addActionListener(e->{
if(timer.isRunning())
return;
timer.start();
});
jb_stop.addActionListener(e->timer.stop());
jf.pack();jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);
}
public static void main(String[] args){new progressbar_test().init();}
}
6.JSlider、BoundedRangeModel创建滑动条
JSlider:
import javax.swing.*;
import java.awt.*;
public class progressbar_test {
int y=0;Timer timer;
public void init(){
var jf=new JFrame("test");
var jp=new JPanel();
var bar=new JSlider(JSlider.VERTICAL,0,100,50);
bar.setPaintLabels(true);
bar.setSnapToTicks(true);
var jb_start=new JButton("1");
var jb_stop=new JButton("2");
var jbshow=new JButton("0%");
bar.addChangeListener(e->{
jbshow.setText(bar.getValue()+"%");
} );
jp.add(jb_start);jp.add(bar);jf.add(jp);jp.add(jb_stop);jp.add(jbshow);
jf.pack();jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);
}
public static void main(String[] args){new progressbar_test().init();}
}
7.JSpinner和SpinnerModel创建微调控制器
JSpinner一共有三种SpinnerModel:
SpinnerNumberModelSpinnerDateModelSpinnerListModel
如下:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Calendar;
public class progressbar_test {
int y=0;Timer timer;
public void init(){
var jf=new JFrame("test");
var jp=new Box(BoxLayout.Y_AXIS);
var spn=new SpinnerNumberModel(50,0,100,1);
var cal=Calendar.getInstance();
var init=cal.getTime();
cal.add(Calendar.DAY_OF_MONTH,-3);
var start=cal.getTime();
cal.add(Calendar.DAY_OF_MONTH,8);
var end=cal.getTime();
var spd=new SpinnerDateModel(init,start,end,Calendar.HOUR_OF_DAY);
ArrayList strs=new ArrayList<>();
strs.add("1");strs.add("2");
var spl=new SpinnerListModel(strs);
var sp1=new JSpinner(spn);
var sp2=new JSpinner(spd);
var sp3=new JSpinner(spl);
jp.add(new JPanel().add(sp1));jp.add(new JPanel().add(sp2));jp.add(new JPanel().add(sp3));
//jp.add(jb_start);jp.add(bar);jf.add(jp);jp.add(jb_stop);jp.add(jbshow);
jf.add(jp);
jf.pack();jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.setVisible(true);
}
public static void main(String[] args){new progressbar_test().init();}
}
8.JList、JComboBox创建列表框
如下:
import javax.swing.*;
public class jlist_test {
public void init(){
var jf=new JFrame("test");
String[] strs={"1","2","3","4","5","7"};
JList lists=new JList<>(strs);
lists.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JComboBox comboBox=new JComboBox<>(strs);
var jp=new JPanel();
jp.add(lists);jp.add(comboBox);
jf.add(jp);jf.pack();jp.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
public static void main(String[] args){new jlist_test().init();}
}
9.JTree和TreeModel创建树
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.ArrayList;
public class jtree_test {
public void init(){
var jf= new JFrame("test");
JTree jt;
int l=5;//2^4
var root=new DefaultMutableTreeNode("1-"+(int)Math.pow(2,l-1));
ArrayList treespro=new ArrayList<>();//上一个
treespro.add(root);
ArrayList treesnext=new ArrayList<>();//下一个
ArrayList trees=new ArrayList<>();//
jt=new JTree(root);
jf.add(new JScrollPane(jt));
jf.pack();jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
for (int x=1;x
for(var y=0;y
treesnext.add(new DefaultMutableTreeNode(x+1+"-"+(int)Math.pow(2,l-x-1)));
}
int ind=0;
for(var tree:treespro){
tree.add(treesnext.get(ind++));
tree.add(treesnext.get(ind++));
}
trees.addAll(treespro);
treespro.clear();
treespro.addAll(treesnext);
treesnext.clear();
}
jt.addTreeSelectionListener(e -> System.out.println(e.getPath()));
}
public static void main(String[] args){new jtree_test().init();}
}
10.JTable、TableModel创建表格
简单的创建表格如下:
import javax.swing.*;
public class table_test {
public void init(){
var jf=new JFrame("test");
String[][] tabs={{"1","2","3"},{"4","5","6"},{"7","8","9"}};
String[] name={"a","b","c"};
var tab=new JTable(tabs,name);
jf.add(new JScrollPane(tab));
jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.pack();
}
public static void main(String[] args){new table_test().init();}
}
JTable提供了很多的方法,深入了解的话会很繁琐,为了省事我直接跳过了,需要用到的时候再去了解不迟。
11.JFormattedTextField和JTextPane创建格式文本
JTextComponent为所有文本输入组件的父类,Swing提供了三个子类:JTextArea、JTextField和JEditorPane,为JEditorPane提供了子类JTextPane。JTextField派生了两个子类:JPasswordField和JFormattedTextField,他们分别代表密码输入框和格式化文本输入框。
如下代码实现了组件中文本变化事件的监听:
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
public class monitortext {public void init(){
var jf=new JFrame("test");
var jta1=new JTextArea(4,50);
var jta2=new JTextArea(4,50);
var box=new Box(BoxLayout.Y_AXIS);
box.add(new JScrollPane(jta1) );box.add(new JScrollPane(jta2));
Document doc=jta1.getDocument();
doc.addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
jta2.append("inserting\n");
}
public void removeUpdate(DocumentEvent e) {
jta2.append("removing\n");
}
public void changedUpdate(DocumentEvent e) {
jta2.append("changing\n");
}
});
doc.addUndoableEditListener(e -> jta2.append("--->undoable\n"));
jf.add(box);
jf.setVisible(true);jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jf.pack();
}
public static void main(String[] args){new monitortext().init();}
}