【11-Swing编程】
|
Swing 编程
Swing 2-1
Swing 2-2
Swing 容器组件 3-1
Swing 容器组件 3-2
JFrame(窗口) 1. 扩展 java.awt.Frame 类 2. 用于在 Swing 程序中创建窗口 3. 包含边框、标题和用于关闭和图标化窗口的按钮
JPanel(面板) 1. 中间容器 2. 用于将较小的轻量级组件组合在一起 3. 与内容窗格相似,面板在默认情况下不透明
JScrollPane(滚动面板) 1.管理视区、滚动条及可选的行和列的标题视区
Swing GUI 组件
事件体系结构
事件处理程序 3-1
事件处理程序 3-2
事件处理程序 3-3
布局管理器
•用户界面上的屏幕组件可以按照一定的格式布局 例如水平排列,或按网格方式排列 •布局管理器类是一组类,它 •实现 java.AWT.LayoutManager 接口 •帮助在容器中放置组件 •Java 中可用的各种布局如下: •BorderLayout •FlowLayout •GridLayout
BorderLayout 2-1
BorderLayout 2-2
FlowLayout 2-1
FlowLayout 2-2
GridLayout 2-1
GridLayout 2-2
使用布局管理器
•选择内容面板 •在属性窗口中将内容面板的 Layout 属性选择为 BorderLayout •从组件面板的 Swing 类别中选择 JButton •将 JButton 添加至 North •使用属性窗口更改属性 •将 JButton 添加至内容面板的左边、下边和右边 •从 Swing 容器类别中选择一个 JPanel,并将其添加至内容面板的中央 •将 JLabel 添加至 JPanel,并更改属性 •将 JTextField 添加至 JPanel,并更改属性
public void btnNorth_actionPerformed(ActionEvent e) { Code generated for the actionPerformed method 为 actionPerformed 方法生成的代码
public void btnNorth_actionPerformed(ActionEvent e) {
public void btnWest_actionPerformed(ActionEvent e) {
为 btnWest 的 actionPerformed 事件添加代码
public void btnSouth_actionPerformed(ActionEvent e) {
为 btnSouth 的 actionPerformed 事件添加代码
public void btnEast_actionPerformed(ActionEvent e) {
为 btnEast 的 actionPerformed 事件添加代码
•在设计视图上选择按钮“北” ,在检查器窗口中单击“Events”选项卡 •双击检查器窗口中的 actionPerformed 事件
菜单2-1 •显示一个项目列表,指明用户可以执行的各项操作 ![]()
菜单 2-2
•包含 javax.swing 包的菜单类的类层次结构
JMenuBar 类 2-1
•只要选中 JMenuItem,就会产生通过重写 actionPerformed()方法进行处理的 ActionEvent
JMenuBar 类 2-2
JMenu 类 2-1
•JMenu 组件有两个用途 –当它添加至 JMenuBar 时,将显示为文本字符串 –当用户单击此菜单项时,则显示一个弹出式菜单
JMenu 类 2-2
JMenuItem 类 2-2
/* mnuFormat.setText(“格式"); mnuNew.setText(“新建"); mnuOpen.setText(“打开..."); mnuSave.setText(“保存"); mnuSaveAs.setText(“另存为..."); mnuExit.setText(“退出"); mnuHelp.setText(“帮助"); mnuNotepad.add(mnuFile); mnuNotepad.add(mnuEdit); mnuNotepad.add(mnuFormat); mnuNotepad.add(mnuHelp); mnuFile.add(mnuNew); mnuFile.add(mnuOpen); mnuFile.add(mnuSave); mnuFile.add(mnuSaveAs); mnuFile.add(mnuExit); } } */
JPopupMenu 类 2-1
•用于显示展开形式的菜单 •可显示在屏幕的任何地方 •通常是由单击鼠标右键触发的 •激活弹出式菜单项之一所执行的操作总是依赖于上下文 •可供 JPopupMenu 类使用的方法 JPopupMenu 类 2-2
JCheckBoxMenuItem类
•这个类是 JMenuItem 类的子类 •使用这个类可实现复选框,默认情况下可为其分配选定标记或取消选定标记
JRadioButtonMenuItem类
•在同一时刻只能选择一个菜单项
对话框 6-1
•Java 中的对话框是一个容器,它充当父容器的子容器 •JOptionPane 这个类支持的功能有: –布局标准对话框 –指定对话框的标题和文本 –提供图标和自定义按钮文本 •JOptionPane 可用于显示各种图标,如用于警告消息、问题、错误和信息等的图标 对话框 6-2
•以下是一些可供 JOptionPane 类使用的构造方法: –JOptionPane() –JOptionPane(Object message) –JOptionPane(Object message, int messageType) –JOptionPane(Object message, int messageType, int optionType) –JOptionPane(Object message, int messageType, int optionType, Icon icon)
对话框 6-3
•showXxxDialog() 方法的一些重载版本 •JOptionPane 类的 showXxxDialog 方法是显示模式对话框最常用的方法
对话框 6-4
对话框 6-5
•用于验证用户身份和显示相应消息的代码 •验证用户身份的应用程序 –向工程中添加标题为“User_Login”的应用程序 –将 JOptionPane 拖放至该应用程序 –该应用程序将验证用户身份并显示相应消息
对话框 6-6
public void btnOk_actionPerformed(ActionEvent e) {
String user;
String password;
user = txtUserName.getText();
password = txtPassword.getText();
if (user.equals("admin") && password.equals("aptech"))
{
dlgMessage.showMessageDialog(this,"您是授权用户","经验证的用户",JOptionPane.INFORMATION_MESSAGE);
} else
{
dlgMessage.showMessageDialog(this,"非法用户名或密码 ","非法用户",JOptionPane.ERROR_MESSAGE);
txtUserName.setText("");
txtPassword.setText("");
txtUserName.setFocusable(true);
}
菜单的事件处理
JTable 9-1
•以表格方式维护大量数据比以列表方式更加方便 •使用 Swing 中的 JTable 类可以创建表
JTable 9-2
•创建一个 TableDemo 工程 •单击“File”---》“New” •选择“Application”,输入 TableDemo 作为应用程序的类名称 •单击“Next”,输入 TableFrame 作为框架的类名称,并输入“欢迎使用 JTable”作为其标题 •单击“Next”,确保已选定“Create Runtime Configuration”选项 •单击“Finish” •单击“Design”选项卡 •选择组件面板中的“JTable”,并将其拖入框架
JTable 9-4
JTable 9-5
JTable 9-6
JTable 9-7
•运行该工程 •此时创建的表无表头 •要显示表头,请单击“Design”选项卡 •选定该表,右击其中的表头属性 •单击关联菜单中的“Expose as Class level variable”选项 •此时将显示表头 •运行该工程 •为表头设置属性
JTable 9-9
•以下代码将在“Source”选项卡中自动生成 package tabledemo;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.JTableHeader;
public class TableFrame extends JFrame {
JPanel contentPane;
Object[ ][ ] cells =
{
{"Java",new Integer(01),new Integer(400)},
{"Oracle",new Integer(02),new Integer(500)},
{"C#",new Integer(03),new Integer(700)},
};
String[] colnames={"课程名称","课程编号","学费(元)"};
JTable jTable1 = new JTable(cells, colnames);
JTableHeader jTableHeader1 = jTable1.getTableHeader();
public TableFrame() {
try {
setDefaultCloseOperation(EXIT_ON_CLOSE);
jbInit();
} catch (Exception exception) {
exception.printStackTrace();
}
}
/**
*初始化组件.
*
* @throws java.lang.Exception
*/
contentPane = (JPanel) getContentPane();
contentPane.setLayout(null);
setSize(new Dimension(400, 300));
setTitle("欢迎使用 JTable");
jTable1.setBackground(Color.yellow);
jTable1.setBorder(null);
jTable1.setGridColor(Color.black);
jTable1.setSelectionBackground(Color.orange);
jTable1.setBounds(new Rectangle(11, 29, 251, 161));
jTableHeader1.setBackground(Color.pink);
jTableHeader1.setBounds(new Rectangle(10, 10, 252, 20));
contentPane.add(jTableHeader1);
contentPane.add(jTable1);
}
}
图形处理
import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.awt.Color; import java.awt. Graphics BufferedImage image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB); Graphics gg; gg.dispose(); FileOutputStream fw=new FileOutputStream(new File("cc.JPG")); ImageIO.write(image, "JPG",fw); 总结
•Swing 菜单由 JMenubar、JMenuItem 和 JMenu 组成 •AbstractButton 是 JMenu 类的父类 •创建 JMenuBar 的实例以创建菜单 •与 JMenuItem 及其与菜单栏关联的子类不同,JPopupMenu 可显示在屏幕的任何地方 •JCheckBoxMenuItem 和 JRadioButtonMenuItem 用于实现菜单栏中的复选框和单选按钮 •JOptionPane 类用于显示对话框
现在贴出代码:
public class AllLookAndFeel { public static void main(String[] args) { System.out.println("当前系统可用的所有LAF:"); for (UIManager.LookAndFeelInfo info : UIManager .getInstalledLookAndFeels()) { System.out.println(info.getName() + "--->" + info); } } }
public class BindKeyTest { JFrame jf = new JFrame("测试键盘绑定"); JTextArea jta = new JTextArea(5, 30); JButton jb = new JButton("发送"); JTextField jtf = new JTextField(15); public void init() { jf.add(jta); JPanel jp = new JPanel(); jp.add(jtf); jp.add(jb); jf.add(jp, BorderLayout.SOUTH); // 发送消息的Action,Action是ActionListener的子接口 Action sendMsg = new AbstractAction() { public void actionPerformed(ActionEvent e) { jta.append(jtf.getText() + "\n"); jtf.setText(""); } }; // 添加事件监听器 jb.addActionListener(sendMsg); // 将Ctrl+Enter键和"send"关联 jtf.getInputMap().put( KeyStroke.getKeyStroke('\n', java.awt.event.InputEvent.CTRL_MASK), "send"); // 将"send"和sendMsg Action关联 jtf.getActionMap().put("send", sendMsg); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new BindKeyTest().init(); } }
public class BorderTest { private JFrame jf = new JFrame("测试边框"); public void init() { jf.setLayout(new GridLayout(2, 4)); // 使用静态工厂方法创建BevelBorder Border bb = BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.RED, Color.GREEN, Color.BLUE, Color.GRAY); jf.add(getPanelWithBorder(bb, "BevelBorder")); // 使用静态工厂方法创建LineBorder Border lb = BorderFactory.createLineBorder(Color.ORANGE, 10); jf.add(getPanelWithBorder(lb, "LineBorder")); // 使用静态工厂方法创建EmptyBorder,EmptyBorder就是在组件四周留空 Border eb = BorderFactory.createEmptyBorder(20, 5, 10, 30); jf.add(getPanelWithBorder(eb, "EmptyBorder")); // 使用静态工厂方法创建EtchedBorder Border etb = BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.RED, Color.GREEN); jf.add(getPanelWithBorder(etb, "EtchedBorder")); // 直接创建TitledBorder,TitledBorder边框就是为原有的边框增加标题 TitledBorder tb = new TitledBorder(lb, "测试标题", TitledBorder.LEFT, TitledBorder.BOTTOM, new Font("StSong", Font.BOLD, 18), Color.BLUE); jf.add(getPanelWithBorder(tb, "TitledBorder")); // 直接创建MatteBorder,MatteBorder边框是EmptyBorder的子类, // 它可以指定留空区域的颜色或背景,此处是指定颜色 MatteBorder mb = new MatteBorder(20, 5, 10, 30, Color.GREEN); jf.add(getPanelWithBorder(mb, "MatteBorder")); // 直接创建CompoundBorder,CompoundBorder边框将两个边框组合成新边框 CompoundBorder cb = new CompoundBorder(new LineBorder(Color.RED, 8), tb); jf.add(getPanelWithBorder(cb, "CompoundBorder")); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new BorderTest().init(); } public JPanel getPanelWithBorder(Border b, String BorderName) { JPanel p = new JPanel(); p.add(new JLabel(BorderName)); // 为Panel组件设置边框 p.setBorder(b); return p; } }
public class HandDraw { // 画图区的宽度 private final int AREA_WIDTH = 500; // 画图区的高度 private final int AREA_HEIGHT = 400; // 下面的preX、preY保存了上一次鼠标拖动事件的鼠标坐标 private int preX = -1; private int preY = -1; // 定义一个右键菜单用于设置画笔颜色 JPopupMenu pop = new JPopupMenu(); JMenuItem chooseColor = new JMenuItem("选择颜色"); // 定义一个BufferedImage对象 BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB); // 获取image对象的Graphics Graphics g = image.getGraphics(); private JFrame f = new JFrame("简单手绘程序"); private DrawCanvas drawArea = new DrawCanvas(); // 用于保存画笔颜色 private Color foreColor = new Color(255, 0, 0); public void init() { chooseColor.addActionListener(ae -> { // 下面代码直接弹出一个模式的颜色选择对话框,并返回用户选择的颜色 // foreColor = JColorChooser.showDialog(f // , "选择画笔颜色" , foreColor); // ① // 下面代码则弹出一个非模式的颜色选择对话框, // 并可以分别为“确定”按钮、“取消”按钮指定事件监听器 final JColorChooser colorPane = new JColorChooser(foreColor); JDialog jd = JColorChooser.createDialog(f , "选择画笔颜色" , false, colorPane, e -> foreColor = colorPane.getColor(), null); jd.setVisible(true); }); // 将菜单项组合成右键菜单 pop.add(chooseColor); // 将右键菜单添加到drawArea对象中 drawArea.setComponentPopupMenu(pop); // 将image对象的背景色填充成白色 g.fillRect(0 , 0 ,AREA_WIDTH , AREA_HEIGHT); drawArea.setPreferredSize(new Dimension(AREA_WIDTH , AREA_HEIGHT)); // 监听鼠标移动动作 drawArea.addMouseMotionListener(new MouseMotionAdapter() { // 实现按下鼠标键并拖动的事件处理器 public void mouseDragged(MouseEvent e) { // 如果preX和preY大于0 if (preX > 0 && preY > 0) { // 设置当前颜色 g.setColor(foreColor); // 绘制从上一次鼠标拖动事件点到本次鼠标拖动事件点的线段 g.drawLine(preX , preY , e.getX() , e.getY()); } // 将当前鼠标事件点的X、Y坐标保存起来 preX = e.getX(); preY = e.getY(); // 重绘drawArea对象 drawArea.repaint(); } }); // 监听鼠标事件 drawArea.addMouseListener(new MouseAdapter() { // 实现鼠标松开的事件处理器 public void mouseReleased(MouseEvent e) { // 松开鼠标键时,把上一次鼠标拖动事件的X、Y坐标设为-1。 preX = -1; preY = -1; } }); f.add(drawArea); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); } public static void main(String[] args) { new HandDraw().init(); } // 让画图区域继承JPanel类 class DrawCanvas extends JPanel { // 重写JPanel的paint方法,实现绘画 public void paint(Graphics g) { // 将image绘制到该组件上 g.drawImage(image, 0, 0, null); } } }
public class ImageViewer { // 定义图片预览组件的大小 final int PREVIEW_SIZE = 100; JFrame jf = new JFrame("简单图片查看器"); JMenuBar menuBar = new JMenuBar(); // 该label用于显示图片 JLabel label = new JLabel(); // 以当前路径创建文件选择器 JFileChooser chooser = new JFileChooser("."); JLabel accessory = new JLabel(); // 定义文件过滤器 ExtensionFileFilter filter = new ExtensionFileFilter(); public void init() { // --------下面开始初始化JFileChooser的相关属性-------- // 创建一个FileFilter filter.addExtension("jpg"); filter.addExtension("jpeg"); filter.addExtension("gif"); filter.addExtension("png"); filter.setDescription("图片文件(*.jpg,*.jpeg,*.gif,*.png)"); chooser.addChoosableFileFilter(filter); // 禁止“文件类型”下拉列表中显示“所有文件”选项。 chooser.setAcceptAllFileFilterUsed(false); // ① // 为文件选择器指定自定义的FileView对象 chooser.setFileView(new FileIconView(filter)); // 为文件选择器指定一个预览图片的附件 chooser.setAccessory(accessory); // ② // 设置预览图片组件的大小和边框 accessory.setPreferredSize(new Dimension(PREVIEW_SIZE, PREVIEW_SIZE)); accessory.setBorder(BorderFactory.createEtchedBorder()); // 用于检测被选择文件的改变事件 chooser.addPropertyChangeListener(event -> { // JFileChooser的被选文件已经发生了改变 if (event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY) { // 获取用户选择的新文件 File f = (File) event.getNewValue(); if (f == null) { accessory.setIcon(null); return; } // 将所选文件读入ImageIcon对象中 ImageIcon icon = new ImageIcon(f.getPath()); // 如果图像太大,则缩小它 if(icon.getIconWidth() > PREVIEW_SIZE) { icon = new ImageIcon(icon.getImage().getScaledInstance (PREVIEW_SIZE, -1, Image.SCALE_DEFAULT)); } // 改变accessory Label的图标 accessory.setIcon(icon); } }); // ------下面代码开始为该窗口安装菜单------ JMenu menu = new JMenu("文件"); menuBar.add(menu); JMenuItem openItem = new JMenuItem("打开"); menu.add(openItem); // 单击openItem菜单项显示“打开文件”的对话框 openItem.addActionListener(event -> { // 设置文件对话框的当前路径 // chooser.setCurrentDirectory(new File(".")); // 显示文件对话框 int result = chooser.showDialog(jf , "打开图片文件"); // 如果用户选择了APPROVE(同意)按钮,即打开,保存的等效按钮 if(result == JFileChooser.APPROVE_OPTION) { String name = chooser.getSelectedFile().getPath(); // 显示指定图片 label.setIcon(new ImageIcon(name)); } }); JMenuItem exitItem = new JMenuItem("Exit"); menu.add(exitItem); // 为退出菜单绑定事件监听器 exitItem.addActionListener(event -> System.exit(0)); jf.setJMenuBar(menuBar); // 添加用于显示图片的JLabel组件。 jf.add(new JScrollPane(label)); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new ImageViewer().init(); } } // 创建FileFilter的子类,用以实现文件过滤功能 class ExtensionFileFilter extends FileFilter { private String description; private ArrayList<String> extensions = new ArrayList<>(); // 自定义方法,用于添加文件扩展名 public void addExtension(String extension) { if (!extension.startsWith(".")) { extension = "." + extension; extensions.add(extension.toLowerCase()); } } // 用于设置该文件过滤器的描述文本 public void setDescription(String aDescription) { description = aDescription; } // 继承FileFilter类必须实现的抽象方法,返回该文件过滤器的描述文本 public String getDescription() { return description; } // 继承FileFilter类必须实现的抽象方法,判断该文件过滤器是否接受该文件 public boolean accept(File f) { // 如果该文件是路径,接受该文件 if (f.isDirectory()) return true; // 将文件名转为小写(全部转为小写后比较,用于忽略文件名大小写) String name = f.getName().toLowerCase(); // 遍历所有可接受的扩展名,如果扩展名相同,该文件就可接受。 for (String extension : extensions) { if (name.endsWith(extension)) { return true; } } return false; } } // 自定义一个FileView类,用于为指定类型的文件或文件夹设置图标 class FileIconView extends FileView { private FileFilter filter; public FileIconView(FileFilter filter) { this.filter = filter; } // 重写该方法,为文件夹、文件设置图标 public Icon getIcon(File f) { if (!f.isDirectory() && filter.accept(f)) { return new ImageIcon("ico/pict.png"); } else if (f.isDirectory()) { // 获取所有根路径 File[] fList = File.listRoots(); for (File tmp : fList) { // 如果该路径是根路径 if (tmp.equals(f)) { return new ImageIcon("ico/dsk.png"); } } return new ImageIcon("ico/folder.png"); } // 使用默认图标 else { return null; } } }
public class JOptionPaneTest { JFrame jf = new JFrame("测试JOptionPane"); // 分别定义6个面板用于定义对话框的几种选项 private ButtonPanel messagePanel; private ButtonPanel messageTypePanel; private ButtonPanel msgPanel; private ButtonPanel confirmPanel; private ButtonPanel optionsPanel; private ButtonPanel inputPanel; private String messageString = "消息区内容"; private Icon messageIcon = new ImageIcon("ico/heart.png"); private Object messageObject = new Date(); private Component messageComponent = new JButton("组件消息"); private JButton msgBn = new JButton("消息对话框"); private JButton confrimBn = new JButton("确认对话框"); private JButton inputBn = new JButton("输入对话框"); private JButton optionBn = new JButton("选项对话框"); public void init() { JPanel top = new JPanel(); top.setBorder(new TitledBorder(new EtchedBorder(), "对话框的通用选项", TitledBorder.CENTER, TitledBorder.TOP)); top.setLayout(new GridLayout(1, 2)); // 消息类型Panel,该Panel中的选项决定对话框的图标 messageTypePanel = new ButtonPanel("选择消息的类型", new String[] { "ERROR_MESSAGE", "INFORMATION_MESSAGE", "WARNING_MESSAGE", "QUESTION_MESSAGE", "PLAIN_MESSAGE" }); // 消息内容类型的Panel,该Panel中的选项决定对话框的消息区的内容 messagePanel = new ButtonPanel("选择消息内容的类型", new String[] { "字符串消息", "图标消息", "组件消息", "普通对象消息", "Object[]消息" }); top.add(messageTypePanel); top.add(messagePanel); JPanel bottom = new JPanel(); bottom.setBorder(new TitledBorder(new EtchedBorder(), "弹出不同的对话框", TitledBorder.CENTER, TitledBorder.TOP)); bottom.setLayout(new GridLayout(1, 4)); // 创建用于弹出消息对话框的Panel msgPanel = new ButtonPanel("消息对话框", null); msgBn.addActionListener(new ShowAction()); msgPanel.add(msgBn); // 创建用于弹出确认对话框的Panel confirmPanel = new ButtonPanel("确认对话框", new String[] { "DEFAULT_OPTION", "YES_NO_OPTION", "YES_NO_CANCEL_OPTION", "OK_CANCEL_OPTION" }); confrimBn.addActionListener(new ShowAction()); confirmPanel.add(confrimBn); // 创建用于弹出输入对话框的Panel inputPanel = new ButtonPanel("输入对话框", new String[] { "单行文本框", "下拉列表选择框" }); inputBn.addActionListener(new ShowAction()); inputPanel.add(inputBn); // 创建用于弹出选项对话框的Panel optionsPanel = new ButtonPanel("选项对话框", new String[] { "字符串选项", "图标选项", "对象选项" }); optionBn.addActionListener(new ShowAction()); optionsPanel.add(optionBn); bottom.add(msgPanel); bottom.add(confirmPanel); bottom.add(inputPanel); bottom.add(optionsPanel); Box box = new Box(BoxLayout.Y_AXIS); box.add(top); box.add(bottom); jf.add(box); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } // 根据用户选择返回选项类型 private int getOptionType() { switch (confirmPanel.getSelection()) { case "DEFAULT_OPTION": return JOptionPane.DEFAULT_OPTION; case "YES_NO_OPTION": return JOptionPane.YES_NO_OPTION; case "YES_NO_CANCEL_OPTION": return JOptionPane.YES_NO_CANCEL_OPTION; default: return JOptionPane.OK_CANCEL_OPTION; } } // 根据用户选择返回消息 private Object getMessage() { switch (messagePanel.getSelection()) { case "字符串消息": return messageString; case "图标消息": return messageIcon; case "组件消息": return messageComponent; case "普通对象消息": return messageObject; default: return new Object[] { messageString, messageIcon, messageObject, messageComponent }; } } // 根据用户选择返回消息类型(决定图标区的图标) private int getDialogType() { switch (messageTypePanel.getSelection()) { case "ERROR_MESSAGE": return JOptionPane.ERROR_MESSAGE; case "INFORMATION_MESSAGE": return JOptionPane.INFORMATION_MESSAGE; case "WARNING_MESSAGE": return JOptionPane.WARNING_MESSAGE; case "QUESTION_MESSAGE": return JOptionPane.QUESTION_MESSAGE; default: return JOptionPane.PLAIN_MESSAGE; } } private Object[] getOptions() { switch (optionsPanel.getSelection()) { case "字符串选项": return new String[] { "a", "b", "c", "d" }; case "图标选项": return new Icon[] { new ImageIcon("ico/1.gif"), new ImageIcon("ico/2.gif"), new ImageIcon("ico/3.gif"), new ImageIcon("ico/4.gif") }; default: return new Object[] { new Date(), new Date(), new Date() }; } } // 为各按钮定义事件监听器 private class ShowAction implements ActionListener { public void actionPerformed(ActionEvent event) { switch (event.getActionCommand()) { case "确认对话框": JOptionPane.showConfirmDialog(jf, getMessage(), "确认对话框", getOptionType(), getDialogType()); break; case "输入对话框": if (inputPanel.getSelection().equals("单行文本框")) { JOptionPane.showInputDialog(jf, getMessage(), "输入对话框", getDialogType()); } else { JOptionPane.showInputDialog(jf, getMessage(), "输入对话框", getDialogType(), null, new String[] { "轻量级Java EE企业应用实战", "疯狂Java讲义" }, "疯狂Java讲义"); } break; case "消息对话框": JOptionPane.showMessageDialog(jf, getMessage(), "消息对话框", getDialogType()); break; case "选项对话框": JOptionPane.showOptionDialog(jf, getMessage(), "选项对话框", getOptionType(), getDialogType(), null, getOptions(), "a"); break; } } } public static void main(String[] args) { new JOptionPaneTest().init(); } } // 定义一个JPanel类扩展类,该类的对象包含多个纵向排列的 // JRadioButton控件,且Panel扩展类可以指定一个字符串作为TitledBorder class ButtonPanel extends JPanel { private ButtonGroup group; public ButtonPanel(String title, String[] options) { setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), title)); setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); group = new ButtonGroup(); for (int i = 0; options != null && i < options.length; i++) { JRadioButton b = new JRadioButton(options[i]); b.setActionCommand(options[i]); add(b); group.add(b); b.setSelected(i == 0); } } // 定义一个方法,用于返回用户选择的选项 public String getSelection() { return group.getSelection().getActionCommand(); } }
public class JToolBarTest { JFrame jf = new JFrame("测试工具条"); JTextArea jta = new JTextArea(6, 35); JToolBar jtb = new JToolBar(); JMenuBar jmb = new JMenuBar(); JMenu edit = new JMenu("编辑"); // 获取系统剪贴板 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); // 创建"粘贴"Action,该Action用于创建菜单项、工具按钮和普通按钮 Action pasteAction = new AbstractAction("粘贴", new ImageIcon("ico/paste.png")) { public void actionPerformed(ActionEvent e) { // 如果剪贴板中包含stringFlavor内容 if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { try { // 取出剪贴板中stringFlavor内容 String content = (String) clipboard .getData(DataFlavor.stringFlavor); // 将选中内容替换成剪贴板中的内容 jta.replaceRange(content, jta.getSelectionStart(), jta.getSelectionEnd()); } catch (Exception ee) { ee.printStackTrace(); } } } }; // 创建"复制"Action Action copyAction = new AbstractAction("复制", new ImageIcon("ico/copy.png")) { public void actionPerformed(ActionEvent e) { StringSelection contents = new StringSelection( jta.getSelectedText()); // 将StringSelection对象放入剪贴板 clipboard.setContents(contents, null); // 如果剪贴板中包含stringFlavor内容 if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { // 将pasteAction激活 pasteAction.setEnabled(true); } } }; public void init() { // pasteAction默认处于不激活状态 pasteAction.setEnabled(false); // ① jf.add(new JScrollPane(jta)); // 以Action创建按钮,并将该按钮添加到Panel中 JButton copyBn = new JButton(copyAction); JButton pasteBn = new JButton(pasteAction); JPanel jp = new JPanel(); jp.add(copyBn); jp.add(pasteBn); jf.add(jp, BorderLayout.SOUTH); // 向工具条中添加Action对象,该对象将会转换成工具按钮 jtb.add(copyAction); jtb.addSeparator(); jtb.add(pasteAction); // 向菜单中添加Action对象,该对象将会转换成菜单项 edit.add(copyAction); edit.add(pasteAction); // 将edit菜单添加到菜单条中 jmb.add(edit); jf.setJMenuBar(jmb); // 设置工具条和工具按钮之间的页边距。 jtb.setMargin(new Insets(20, 10, 5, 30)); // ② // 向窗口中添加工具条 jf.add(jtb, BorderLayout.NORTH); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new JToolBarTest().init(); } }
public class SwingComponent { JFrame f = new JFrame("测试"); // 定义一个按钮,并为之指定图标 Icon okIcon = new ImageIcon("ico/ok.png"); JButton ok = new JButton("确认", okIcon); // 定义一个单选按钮,初始处于选中状态 JRadioButton male = new JRadioButton("男", true); // 定义一个单选按钮,初始处于没有选中状态 JRadioButton female = new JRadioButton("女", false); // 定义一个ButtonGroup,用于将上面两个JRadioButton组合在一起 ButtonGroup bg = new ButtonGroup(); // 定义一个复选框,初始处于没有选中状态。 JCheckBox married = new JCheckBox("是否已婚?", false); String[] colors = new String[] { "红色", "绿色", "蓝色" }; // 定义一个下拉选择框 JComboBox<String> colorChooser = new JComboBox<>(colors); // 定义一个列表选择框 JList<String> colorList = new JList<>(colors); // 定义一个8行、20列的多行文本域 JTextArea ta = new JTextArea(8, 20); // 定义一个40列的单行文本域 JTextField name = new JTextField(40); JMenuBar mb = new JMenuBar(); JMenu file = new JMenu("文件"); JMenu edit = new JMenu("编辑"); // 创建“新建”菜单项,并为之指定图标 Icon newIcon = new ImageIcon("ico/new.png"); JMenuItem newItem = new JMenuItem("新建", newIcon); // 创建“保存”菜单项,并为之指定图标 Icon saveIcon = new ImageIcon("ico/save.png"); JMenuItem saveItem = new JMenuItem("保存", saveIcon); // 创建“退出”菜单项,并为之指定图标 Icon exitIcon = new ImageIcon("ico/exit.png"); JMenuItem exitItem = new JMenuItem("退出", exitIcon); JCheckBoxMenuItem autoWrap = new JCheckBoxMenuItem("自动换行"); // 创建“复制”菜单项,并为之指定图标 JMenuItem copyItem = new JMenuItem("复制", new ImageIcon("ico/copy.png")); // 创建“粘贴”菜单项,并为之指定图标 JMenuItem pasteItem = new JMenuItem("粘贴", new ImageIcon("ico/paste.png")); JMenu format = new JMenu("格式"); JMenuItem commentItem = new JMenuItem("注释"); JMenuItem cancelItem = new JMenuItem("取消注释"); // 定义一个右键菜单用于设置程序风格 JPopupMenu pop = new JPopupMenu(); // 用于组合三个风格菜单项的ButtonGroup ButtonGroup flavorGroup = new ButtonGroup(); // 创建五个单选框按钮,用于设定程序的外观风格 JRadioButtonMenuItem metalItem = new JRadioButtonMenuItem("Metal风格", true); JRadioButtonMenuItem nimbusItem = new JRadioButtonMenuItem("Nimbus风格"); JRadioButtonMenuItem windowsItem = new JRadioButtonMenuItem("Windows风格"); JRadioButtonMenuItem classicItem = new JRadioButtonMenuItem("Windows经典风格"); JRadioButtonMenuItem motifItem = new JRadioButtonMenuItem("Motif风格"); // -----------------用于执行界面初始化的init方法--------------------- public void init() { // 创建一个装载了文本框、按钮的JPanel JPanel bottom = new JPanel(); bottom.add(name); bottom.add(ok); f.add(bottom , BorderLayout.SOUTH); // 创建一个装载了下拉选择框、三个JCheckBox的JPanel JPanel checkPanel = new JPanel(); checkPanel.add(colorChooser); bg.add(male); bg.add(female); checkPanel.add(male); checkPanel.add(female); checkPanel.add(married); // 创建一个垂直排列组件的Box,盛装多行文本域JPanel Box topLeft = Box.createVerticalBox(); // 使用JScrollPane作为普通组件的JViewPort JScrollPane taJsp = new JScrollPane(ta); //⑤ topLeft.add(taJsp); topLeft.add(checkPanel); // 创建一个水平排列组件的Box,盛装topLeft、colorList Box top = Box.createHorizontalBox(); top.add(topLeft); top.add(colorList); // 将top Box容器添加到窗口的中间 f.add(top); // -----------下面开始组合菜单、并为菜单添加监听器---------- // 为newItem设置快捷键,设置快捷键时要使用大写字母 newItem.setAccelerator(KeyStroke.getKeyStroke('N' , InputEvent.CTRL_MASK)); //① newItem.addActionListener(e -> ta.append("用户单击了“新建”菜单\n")); // 为file菜单添加菜单项 file.add(newItem); file.add(saveItem); file.add(exitItem); // 为edit菜单添加菜单项 edit.add(autoWrap); // 使用addSeparator方法来添加菜单分隔线 edit.addSeparator(); edit.add(copyItem); edit.add(pasteItem); // 为commentItem组件添加提示信息 commentItem.setToolTipText("将程序代码注释起来!"); // 为format菜单添加菜单项 format.add(commentItem); format.add(cancelItem); // 使用添加new JMenuItem("-")的方式不能添加菜单分隔符 edit.add(new JMenuItem("-")); // 将format菜单组合到edit菜单中,从而形成二级菜单 edit.add(format); // 将file、edit菜单添加到mb菜单条中 mb.add(file); mb.add(edit); // 为f窗口设置菜单条 f.setJMenuBar(mb); // -----------下面开始组合右键菜单、并安装右键菜单---------- flavorGroup.add(metalItem); flavorGroup.add(nimbusItem); flavorGroup.add(windowsItem); flavorGroup.add(classicItem); flavorGroup.add(motifItem); pop.add(metalItem); pop.add(nimbusItem); pop.add(windowsItem); pop.add(classicItem); pop.add(motifItem); // 为5个风格菜单创建事件监听器 ActionListener flavorListener = e -> { try { switch(e.getActionCommand()) { case "Metal风格": changeFlavor(1); break; case "Nimbus风格": changeFlavor(2); break; case "Windows风格": changeFlavor(3); break; case "Windows经典风格": changeFlavor(4); break; case "Motif风格": changeFlavor(5); break; } } catch (Exception ee) { ee.printStackTrace(); } }; // 为五个风格菜单项添加事件监听器 metalItem.addActionListener(flavorListener); nimbusItem.addActionListener(flavorListener); windowsItem.addActionListener(flavorListener); classicItem.addActionListener(flavorListener); motifItem.addActionListener(flavorListener); // 调用该方法即可设置右键菜单,无须使用事件机制 ta.setComponentPopupMenu(pop); //④ // 设置关闭窗口时,退出程序 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.pack(); f.setVisible(true); } // 定义一个方法,用于改变界面风格 private void changeFlavor(int flavor) throws Exception { switch (flavor) { // 设置Metal风格 case 1: UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); break; // 设置Nimbus风格 case 2: UIManager .setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); break; // 设置Windows风格 case 3: UIManager .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); break; // 设置Windows经典风格 case 4: UIManager .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); break; // 设置Motif风格 case 5: UIManager .setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); break; } // 更新f窗口内顶级容器以及内部所有组件的UI SwingUtilities.updateComponentTreeUI(f.getContentPane()); // ② // 更新mb菜单条以及内部所有组件的UI SwingUtilities.updateComponentTreeUI(mb); // 更新pop右键菜单以及内部所有组件的UI SwingUtilities.updateComponentTreeUI(pop); } public static void main(String[] args) { // 设置Swing窗口使用Java风格 // JFrame.setDefaultLookAndFeelDecorated(true); //③ new SwingComponent().init(); } }
public class InternalDialogTest { private JFrame jf = new JFrame("测试内部对话框"); private JDesktopPane desktop = new JDesktopPane(); private JButton internalBn = new JButton("内部窗口的对话框"); private JButton deskBn = new JButton("虚拟桌面的对话框"); // 定义一个内部窗口,该窗口可拖动,但不可最大化、最小化、关闭 private JInternalFrame iframe = new JInternalFrame("内部窗口"); public void init() { // 向内部窗口中添加组件 iframe.add(new JScrollPane(new JTextArea(8, 40))); desktop.setPreferredSize(new Dimension(400, 300)); // 把虚拟桌面添加到JFrame窗口中 jf.add(desktop); // 设置内部窗口的大小、位置 iframe.reshape(0 , 0 , 300 , 200); // 显示并选中内部窗口 iframe.show(); desktop.add(iframe); JPanel jp = new JPanel(); deskBn.addActionListener(event -> // 弹出内部对话框,以虚拟桌面作为父组件 JOptionPane.showInternalMessageDialog(desktop , "属于虚拟桌面的对话框")); internalBn.addActionListener(event -> // 弹出内部对话框,以内部窗口作为父组件 JOptionPane.showInternalMessageDialog(iframe , "属于内部窗口的对话框")); jp.add(deskBn); jp.add(internalBn); jf.add(jp , BorderLayout.SOUTH); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new InternalDialogTest().init(); } }
public class JInternalFrameTest { final int DESKTOP_WIDTH = 480; final int DESKTOP_HEIGHT = 360; final int FRAME_DISTANCE = 30; JFrame jf = new JFrame("MDI界面"); // 定义一个虚拟桌面 private MyJDesktopPane desktop = new MyJDesktopPane(); // 保存下一个内部窗口的坐标点 private int nextFrameX; private int nextFrameY; // 定义内部窗口为虚拟桌面的1/2大小 private int width = DESKTOP_WIDTH / 2; private int height = DESKTOP_HEIGHT / 2; // 为主窗口定义两个菜单 JMenu fileMenu = new JMenu("文件"); JMenu windowMenu = new JMenu("窗口"); // 定义newAction用于创建菜单和工具按钮 Action newAction = new AbstractAction("新建", new ImageIcon("ico/new.png")) { public void actionPerformed(ActionEvent event) { // 创建内部窗口 final JInternalFrame iframe = new JInternalFrame("新文档", true, // 可改变大小 true, // 可关闭 true, // 可最大化 true); // 可最小化 iframe.add(new JScrollPane(new JTextArea(8, 40))); // 将内部窗口添加到虚拟桌面中 desktop.add(iframe); // 设置内部窗口的原始位置(内部窗口默认大小是0X0,放在0,0位置) iframe.reshape(nextFrameX, nextFrameY, width, height); // 使该窗口可见,并尝试选中它 iframe.show(); // 计算下一个内部窗口的位置 nextFrameX += FRAME_DISTANCE; nextFrameY += FRAME_DISTANCE; if (nextFrameX + width > desktop.getWidth()) nextFrameX = 0; if (nextFrameY + height > desktop.getHeight()) nextFrameY = 0; } }; // 定义exitAction用于创建菜单和工具按钮 Action exitAction = new AbstractAction("退出", new ImageIcon("ico/exit.png")) { public void actionPerformed(ActionEvent event) { System.exit(0); } }; public void init() { // 为窗口安装菜单条和工具条 JMenuBar menuBar = new JMenuBar(); JToolBar toolBar = new JToolBar(); jf.setJMenuBar(menuBar); menuBar.add(fileMenu); fileMenu.add(newAction); fileMenu.add(exitAction); toolBar.add(newAction); toolBar.add(exitAction); menuBar.add(windowMenu); JMenuItem nextItem = new JMenuItem("下一个"); nextItem.addActionListener(event -> desktop.selectNextWindow()); windowMenu.add(nextItem); JMenuItem cascadeItem = new JMenuItem("级联"); cascadeItem.addActionListener(event -> // 级联显示窗口,内部窗口的大小是外部窗口的0.75 desktop.cascadeWindows(FRAME_DISTANCE , 0.75)); windowMenu.add(cascadeItem); JMenuItem tileItem = new JMenuItem("平铺"); // 平铺显示所有内部窗口 tileItem.addActionListener(event -> desktop.tileWindows()); windowMenu.add(tileItem); final JCheckBoxMenuItem dragOutlineItem = new JCheckBoxMenuItem("仅显示拖动窗口的轮廓"); dragOutlineItem.addActionListener(event -> // 根据该菜单项是否选择来决定采用哪种拖动模式 desktop.setDragMode(dragOutlineItem.isSelected() ? JDesktopPane.OUTLINE_DRAG_MODE : JDesktopPane.LIVE_DRAG_MODE)); // ① windowMenu.add(dragOutlineItem); desktop.setPreferredSize(new Dimension(480, 360)); // 将虚拟桌面添加到顶级JFrame容器中 jf.add(desktop); jf.add(toolBar , BorderLayout.NORTH); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new JInternalFrameTest().init(); } } class MyJDesktopPane extends JDesktopPane { // 将所有窗口以级联方式显示, // 其中offset是两个窗口的位移距离, s // cale是内部窗口与JDesktopPane的大小比例 public void cascadeWindows(int offset, double scale) { // 定义级联显示窗口时内部窗口的大小 int width = (int) (getWidth() * scale); int height = (int) (getHeight() * scale); // 用于保存级联窗口时每个窗口的位置 int x = 0; int y = 0; for (JInternalFrame frame : getAllFrames()) { try { // 取消内部窗口的最大化,最小化 frame.setMaximum(false); frame.setIcon(false); // 把窗口重新放置在指定位置 frame.reshape(x, y, width, height); x += offset; y += offset; // 如果到了虚拟桌面边界 if (x + width > getWidth()) x = 0; if (y + height > getHeight()) y = 0; } catch (PropertyVetoException e) { } } } // 将所有窗口以平铺方式显示 public void tileWindows() { // 统计所有窗口 int frameCount = 0; for (JInternalFrame frame : getAllFrames()) { frameCount++; } // 计算需要多少行、多少列才可以平铺所有窗口 int rows = (int) Math.sqrt(frameCount); int cols = frameCount / rows; // 需要额外增加到其他列中的窗口 int extra = frameCount % rows; // 计算平铺时内部窗口的大小 int width = getWidth() / cols; int height = getHeight() / rows; // 用于保存平铺窗口时每个窗口在横向、纵向上的索引 int x = 0; int y = 0; for (JInternalFrame frame : getAllFrames()) { try { // 取消内部窗口的最大化,最小化 frame.setMaximum(false); frame.setIcon(false); // 将窗口放在指定位置 frame.reshape(x * width, y * height, width, height); y++; // 每排完一列窗口 if (y == rows) { // 开始排放下一列窗口 y = 0; x++; // 如果额外多出的窗口与剩下的列数相等, // 则后面所有列都需要多排列一个窗口 if (extra == cols - x) { rows++; height = getHeight() / rows; } } } catch (PropertyVetoException e) { } } } // 选中下一个非图标窗口 public void selectNextWindow() { JInternalFrame[] frames = getAllFrames(); for (int i = 0; i < frames.length; i++) { if (frames[i].isSelected()) { // 找出下一个非最小化的窗口,尝试选中它, // 如果选中失败,则继续尝试选中下一个窗口 int next = (i + 1) % frames.length; while (next != i) { // 如果该窗口不是处于最小化状态 if (!frames[next].isIcon()) { try { frames[next].setSelected(true); frames[next].toFront(); frames[i].toBack(); return; } catch (PropertyVetoException e) { } } next = (next + 1) % frames.length; } } } }
public class JLayeredPaneTest { JFrame jf = new JFrame("测试JLayeredPane"); JLayeredPane layeredPane = new JLayeredPane(); public void init() { // 向layeredPane中添加3个组件 layeredPane.add(new ContentPanel(10, 20, "疯狂Java讲义", "ico/java.png"), JLayeredPane.MODAL_LAYER); layeredPane.add(new ContentPanel(100, 60, "疯狂Android讲义", "ico/android.png"), JLayeredPane.DEFAULT_LAYER); layeredPane.add(new ContentPanel(190, 100, "轻量级Java EE企业应用实战", "ico/ee.png"), 4); layeredPane.setPreferredSize(new Dimension(400, 300)); layeredPane.setVisible(true); jf.add(layeredPane); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new JLayeredPaneTest().init(); } } // 扩展了JPanel类,可以直接创建一个放在指定位置, // 且有指定标题、放置指定图标的JPanel对象 class ContentPanel extends JPanel { public ContentPanel(int xPos, int yPos, String title, String ico) { setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), title)); JLabel label = new JLabel(new ImageIcon(ico)); add(label); setBounds(xPos, yPos, 160, 220); // ① } }
public class JTabbedPaneTest { JFrame jf = new JFrame("测试Tab页面"); // 创建一个Tab页面的标签放在左边,采用换行布局策略的JTabbedPane JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT, JTabbedPane.WRAP_TAB_LAYOUT); ImageIcon icon = new ImageIcon("ico/close.gif"); String[] layouts = { "换行布局", "滚动条布局" }; String[] positions = { "左边", "顶部", "右边", "底部" }; Map<String, String> books = new LinkedHashMap<>(); public void init() { books.put("疯狂Java讲义" , "java.png"); books.put("轻量级Java EE企业应用实战" , "ee.png"); books.put("疯狂Ajax讲义" , "ajax.png"); books.put("疯狂Android讲义" , "android.png"); books.put("经典Java EE企业应用实战" , "classic.png"); String tip = "可看到本书的封面照片"; // 向JTabbedPane中添加5个标签页面,指定了标题、图标和提示 // 但该标签页面的组件为null for (String bookName : books.keySet()) { tabbedPane.addTab(bookName, icon, null , tip); } jf.add(tabbedPane, BorderLayout.CENTER); // 为JTabbedPane添加事件监听器 tabbedPane.addChangeListener(event -> { // 如果被选择的组件依然是空 if (tabbedPane.getSelectedComponent() == null) { // 获取所选标签页 int n = tabbedPane.getSelectedIndex(); // 为指定标前页加载内容 loadTab(n); } }); // 系统默认选择第一页,加载第一页内容 loadTab(0); tabbedPane.setPreferredSize(new Dimension(500 , 300)); // 增加控制标签布局、标签位置的单选按钮 JPanel buttonPanel = new JPanel(); ChangeAction action = new ChangeAction(); buttonPanel.add(new ButtonPanel(action , "选择标签布局策略" , layouts)); buttonPanel.add (new ButtonPanel(action , "选择标签位置" , positions)); jf.add(buttonPanel, BorderLayout.SOUTH); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } // 为指定标签页加载内容 private void loadTab(int n) { String title = tabbedPane.getTitleAt(n); // 根据标签页的标题获取对应图书封面 ImageIcon bookImage = new ImageIcon("ico/" + books.get(title)); tabbedPane.setComponentAt(n, new JLabel(bookImage)); // 改变标签页的图标 tabbedPane.setIconAt(n, new ImageIcon("ico/open.gif")); } // 定义改变标签页的布局策略,放置位置的监听器 class ChangeAction implements ActionListener { public void actionPerformed(ActionEvent event) { JRadioButton source = (JRadioButton) event.getSource(); String selection = source.getActionCommand(); // 设置标签页的标题的布局策略 if (selection.equals(layouts[0])) { tabbedPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT); } else if (selection.equals(layouts[1])) { tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); } // 设置标签页上的标题的放置位置 else if (selection.equals(positions[0])) { tabbedPane.setTabPlacement(JTabbedPane.LEFT); } else if (selection.equals(positions[1])) { tabbedPane.setTabPlacement(JTabbedPane.TOP); } else if (selection.equals(positions[2])) { tabbedPane.setTabPlacement(JTabbedPane.RIGHT); } else if (selection.equals(positions[3])) { tabbedPane.setTabPlacement(JTabbedPane.BOTTOM); } } } public static void main(String[] args) { new JTabbedPaneTest().init(); } } // 定义一个JPanel类扩展类,该类的对象包含多个纵向排列的JRadioButton控件 // 且JPanel扩展类可以指定一个字符串作为TitledBorder class ButtonPanel extends JPanel { private ButtonGroup group; public ButtonPanel(JTabbedPaneTest.ChangeAction action, String title, String[] labels) { setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), title)); setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); group = new ButtonGroup(); for (int i = 0; labels != null && i < labels.length; i++) { JRadioButton b = new JRadioButton(labels[i]); b.setActionCommand(labels[i]); add(b); // 添加事件监听器 b.addActionListener(action); group.add(b); b.setSelected(i == 0); } } }
class Book { private String name; private Icon ico; private String desc; public Book() { } public Book(String name, Icon ico, String desc) { this.name = name; this.ico = ico; this.desc = desc; } // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // ico的setter和getter方法 public void setIco(Icon ico) { this.ico = ico; } public Icon getIco() { return this.ico; } // desc的setter和getter方法 public void setDesc(String desc) { this.desc = desc; } public String getDesc() { return this.desc; } public String toString() { return name; } } public class SplitPaneTest { Book[] books = new Book[] { new Book("疯狂Java讲义", new ImageIcon("ico/java.png"), "国内关于Java编程最全面的图书\n看得懂,学得会"), new Book("轻量级Java EE企业应用实战", new ImageIcon("ico/ee.png"), "SSH整合开发的经典图书,值得拥有"), new Book("疯狂Android讲义", new ImageIcon("ico/android.png"), "全面介绍Android平台应用程序\n开发的各方面知识") }; JFrame jf = new JFrame("测试JSplitPane"); JList<Book> bookList = new JList<>(books); JLabel bookCover = new JLabel(); JTextArea bookDesc = new JTextArea(); public void init() { // 为三个组件设置最佳大小 bookList.setPreferredSize(new Dimension(150, 300)); bookCover.setPreferredSize(new Dimension(300, 150)); bookDesc.setPreferredSize(new Dimension(300, 150)); // 为下拉列表添加事件监听器 bookList.addListSelectionListener(event ->{ Book book = (Book)bookList.getSelectedValue(); bookCover.setIcon(book.getIco()); bookDesc.setText(book.getDesc()); }); // 创建一个垂直的分割面板, // 将bookCover放在上面,将bookDesc放在下面, 支持连续布局 JSplitPane left = new JSplitPane(JSplitPane.VERTICAL_SPLIT , true , bookCover, new JScrollPane(bookDesc)); // 打开“一触即展”的特性 left.setOneTouchExpandable(true); // 下面代码设置分割条的大小。 // left.setDividerSize(50); // 设置该分割面板根据所包含组件的最佳大小来调整布局 left.resetToPreferredSizes(); // 创建一个水平的分割面板 // 将left组件放在左边,将bookList组件放在右边 JSplitPane content = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT , left, bookList); jf.add(content); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new SplitPaneTest().init(); } }
public class SwingDndSupport { JFrame jf = new JFrame("Swing的拖放支持"); JTextArea srcTxt = new JTextArea(8, 30); JTextField jtf = new JTextField(34); public void init() { srcTxt.append("Swing的拖放支持.\n"); srcTxt.append("将该文本域的内容拖入其他程序.\n"); // 启动文本域和单行文本框的拖放支持 srcTxt.setDragEnabled(true); jtf.setDragEnabled(true); jf.add(new JScrollPane(srcTxt)); jf.add(jtf, BorderLayout.SOUTH); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new SwingDndSupport().init(); } }
public class TransferHandlerTest { private JFrame jf = new JFrame("测试TransferHandler"); JColorChooser chooser = new JColorChooser(); JTextArea txt = new JTextArea("测试TransferHandler\n" + "直接将上面颜色拖入以改变文本颜色"); public void init() { // 启动颜色选择器面板和文本域的拖放功能 chooser.setDragEnabled(true); txt.setDragEnabled(true); jf.add(chooser, BorderLayout.SOUTH); // 允许直接将一个Color对象拖入该JTextArea对象 // 并赋给它的foreground属性 txt.setTransferHandler(new TransferHandler("foreground")); jf.add(new JScrollPane(txt)); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.pack(); jf.setVisible(true); } public static void main(String[] args) { new TransferHandlerTest().init(); } }
class FirstLayerUI extends LayerUI<JComponent> { public void paint(Graphics g, JComponent c) { super.paint(g, c); Graphics2D 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(); } } class BlurLayerUI extends LayerUI<JComponent> { private BufferedImage screenBlurImage; private BufferedImageOp operation; public BlurLayerUI() { float ninth = 1.0f / 9.0f; // 定义模糊参数 float[] blurKernel = { ninth, ninth, ninth, ninth, ninth, ninth, ninth, ninth, ninth }; // ConvolveOp代表一个模糊处理,它将原图片的每一个像素与周围 // 像素的颜色进行混合,从而计算出当前像素的颜色值, operation = new ConvolveOp(new Kernel(3, 3, blurKernel), ConvolveOp.EDGE_NO_OP, null); } public void paint(Graphics g, JComponent c) { int w = c.getWidth(); int h = c.getHeight(); // 如果被装饰窗口大小为0X0,直接返回 if (w == 0 || h == 0) return; // 如果screenBlurImage没有初始化,或它的尺寸不对。 if (screenBlurImage == null || screenBlurImage.getWidth() != w || screenBlurImage.getHeight() != h) { // 重新创建新的BufferdImage screenBlurImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); } Graphics2D ig2 = screenBlurImage.createGraphics(); // 把被装饰组件的界面绘制到当前screenBlurImage上 ig2.setClip(g.getClip()); super.paint(ig2, c); ig2.dispose(); Graphics2D g2 = (Graphics2D) g; // 对JLayer装饰的组件进行模糊处理 g2.drawImage(screenBlurImage, operation, 0, 0); } } class SpotlightLayerUI extends LayerUI<JComponent> { private boolean active; private int cx, cy; public void installUI(JComponent c) { super.installUI(c); JLayer layer = (JLayer) c; // 设置JLayer可以响应鼠标、鼠标动作事件 layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); } public void uninstallUI(JComponent c) { JLayer layer = (JLayer) c; // 设置JLayer不响应任何事件 layer.setLayerEventMask(0); super.uninstallUI(c); } public void paint(Graphics g, JComponent c) { Graphics2D g2 = (Graphics2D) g.create(); super.paint(g2, c); // 如果处于激活状态 if (active) { // 定义一个cx、cy位置的点 Point2D center = new Point2D.Float(cx, cy); float radius = 72; float[] dist = { 0.0f, 1.0f }; Color[] colors = { Color.YELLOW, Color.BLACK }; // 以center为中心、colors为颜色数组创建环形渐变 RadialGradientPaint 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.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 class JLayerTest { public void init() { JFrame f = new JFrame("JLayer测试"); JPanel p = new JPanel(); ButtonGroup group = new ButtonGroup(); JRadioButton radioButton; // 创建3个RadioButton,并将它们添加成一组 p.add(radioButton = new JRadioButton("网购购买", true)); group.add(radioButton); p.add(radioButton = new JRadioButton("书店购买")); group.add(radioButton); p.add(radioButton = new JRadioButton("图书馆借阅")); group.add(radioButton); // 添加3个JCheckBox p.add(new JCheckBox("疯狂Java讲义")); p.add(new JCheckBox("疯狂Android讲义")); p.add(new JCheckBox("疯狂Ajax讲义")); p.add(new JCheckBox("轻量级Java EE企业应用")); JButton orderButton = new JButton("投票"); p.add(orderButton); // 创建LayerUI对象 LayerUI<JComponent> layerUI = new SpotlightLayerUI(); // ② // 使用layerUI来装饰指定的JPanel组件 JLayer<JComponent> layer = new JLayer<JComponent>(p, layerUI); // 将装饰后的JPanel组件添加到容器中 f.add(layer); f.setSize(300, 170); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } public static void main(String[] args) { new JLayerTest().init(); }
public class NonRegularWindow extends JFrame implements ActionListener { // 定义3个窗口 JFrame transWin = new JFrame("透明窗口"); JFrame gradientWin = new JFrame("渐变透明窗口"); JFrame bgWin = new JFrame("背景图片窗口"); JFrame shapeWin = new JFrame("椭圆窗口"); public NonRegularWindow() { super("不规则窗口测试"); setLayout(new FlowLayout()); JButton transBn = new JButton("透明窗口"); JButton gradientBn = new JButton("渐变透明窗口"); JButton bgBn = new JButton("背景图片窗口"); JButton shapeBn = new JButton("椭圆窗口"); // 为3个按钮添加事件监听器 transBn.addActionListener(this); gradientBn.addActionListener(this); bgBn.addActionListener(this); shapeBn.addActionListener(this); add(transBn); add(gradientBn); add(bgBn); add(shapeBn); // -------设置透明窗口------- transWin.setLayout(new GridBagLayout()); transWin.setSize(300, 200); transWin.add(new JButton("透明窗口里的简单按钮")); // 设置透明度为0.65f,透明度为1时完全不透明。 transWin.setOpacity(0.65f); // -------设置渐变透明的窗口------- gradientWin.setBackground(new Color(0, 0, 0, 0)); gradientWin.setSize(new Dimension(300, 200)); // 使用一个JPanel对象作为渐变透明的背景 JPanel panel = new JPanel() { protected void paintComponent(Graphics g) { if (g instanceof Graphics2D) { final int R = 240; final int G = 240; final int B = 240; // 创建一个渐变画笔 Paint p = new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0), 0.0f, getHeight(), new Color(R, G, B, 255), true); Graphics2D g2d = (Graphics2D) g; g2d.setPaint(p); g2d.fillRect(0, 0, getWidth(), getHeight()); } } }; // 使用JPanel对象作为JFrame的contentPane gradientWin.setContentPane(panel); panel.setLayout(new GridBagLayout()); gradientWin.add(new JButton("渐变透明窗口里的简单按钮")); // -------设置有背景图片的窗口------- bgWin.setBackground(new Color(0, 0, 0, 0)); bgWin.setSize(new Dimension(300, 200)); // 使用一个JPanel对象作为背景图片 JPanel bgPanel = new JPanel() { protected void paintComponent(Graphics g) { try { Image bg = ImageIO.read(new File("images/java.png")); // 绘制一张图片作为背景 g.drawImage(bg, 0, 0, getWidth(), getHeight(), null); } catch (IOException ex) { ex.printStackTrace(); } } }; // 使用JPanel对象作为JFrame的contentPane bgWin.setContentPane(bgPanel); bgPanel.setLayout(new GridBagLayout()); bgWin.add(new JButton("有背景图片窗口里的简单按钮")); // -------设置椭圆形窗口------- shapeWin.setLayout(new GridBagLayout()); shapeWin.setUndecorated(true); shapeWin.setOpacity(0.7f); // 通过为shapeWin添加监听器来设置窗口的形状。 // 当shapeWin窗口的大小被改变时,程序动态设置该窗口的形状 shapeWin.addComponentListener(new ComponentAdapter() { // 当窗口大小被改变时,椭圆的大小也会相应地改变 public void componentResized(ComponentEvent e) { // 设置窗口的形状 shapeWin.setShape(new Ellipse2D.Double(0, 0, shapeWin .getWidth(), shapeWin.getHeight())); // ① } }); shapeWin.setSize(300, 200); shapeWin.add(new JButton("椭圆形窗口里的简单按钮")); // -------设置主程序的窗口------- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setVisible(true); } public void actionPerformed(ActionEvent event) { switch (event.getActionCommand()) { case "透明窗口": transWin.setVisible(true); break; case "渐变透明窗口": gradientWin.setVisible(true); break; case "背景图片窗口": bgWin.setVisible(true); break; case "椭圆窗口": shapeWin.setVisible(true); break; } } public static void main(String[] args) { JFrame.setDefaultLookAndFeelDecorated(true); new NonRegularWindow(); } }
class WaitingLayerUI extends LayerUI<JComponent> { private boolean isRunning; private Timer timer; // 记录转过的角度 private int angle; // ① public void paint(Graphics g, JComponent c) { super.paint(g, c); int w = c.getWidth(); int h = c.getHeight(); // 已经停止运行,直接返回 if (!isRunning) return; Graphics2D 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); // -----下面代码开始绘制转动中的“齿轮”---- // 计算得到宽、高中较小值的1/5 int s = Math.min(w, h) / 5; int cx = w / 2; int 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); // 画笔绕被装饰组件的中心转过angle度 g2.rotate(Math.PI * angle / 180, cx, cy); // 循环绘制12条线条,形成“齿轮” for (int 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; // 每隔0.1秒重绘一次 timer = new Timer(100, e -> { if (isRunning) { // 触发applyPropertyChange()方法,让JLayer重绘。 // 在这行代码中,后面两个参数没有意义。 firePropertyChange("crazyitFlag", 0 , 1); // 角度加6 angle += 6; // ② // 到达360后再从0开始 if (angle >= 360) angle = 0; } }); timer.start(); } // 控制停止等待(齿轮停止转动)的方法 public void stop() { isRunning = false; // 最后通知JLayer重绘一次,清除曾经绘制的图形 firePropertyChange("crazyitFlag", 0, 1); timer.stop(); } public void applyPropertyChange(PropertyChangeEvent pce, JLayer layer) { // 控制JLayer重绘 if (pce.getPropertyName().equals("crazyitFlag")) { layer.repaint(); } } } public class WaitingJLayerTest { public void init() { JFrame f = new JFrame("转动的“齿轮”"); JPanel p = new JPanel(); ButtonGroup group = new ButtonGroup(); JRadioButton radioButton; // 创建3个RadioButton,并将它们添加成一组 p.add(radioButton = new JRadioButton("网购购买", true)); group.add(radioButton); p.add(radioButton = new JRadioButton("书店购买")); group.add(radioButton); p.add(radioButton = new JRadioButton("图书馆借阅")); group.add(radioButton); // 添加3个JCheckBox p.add(new JCheckBox("疯狂Java讲义")); p.add(new JCheckBox("疯狂Android讲义")); p.add(new JCheckBox("疯狂Ajax讲义")); p.add(new JCheckBox("轻量级Java EE企业应用")); JButton orderButton = new JButton("投票"); p.add(orderButton); // 创建LayerUI对象 final WaitingLayerUI layerUI = new WaitingLayerUI(); // 使用layerUI来装饰指定JPanel组件 JLayer<JComponent> layer = new JLayer<JComponent>(p, layerUI); // 设置4秒之后执行指定动作:调用layerUI的stop()方法 final Timer stopper = new Timer(4000, ae -> layerUI.stop()); // 设置stopper定时器只触发一次。 stopper.setRepeats(false); // 为orderButton绑定事件监听器:单击该按钮时:调用layerUI的start()方法 orderButton.addActionListener(ae -> { layerUI.start(); // 如果stopper定时器已停止,启动它 if (!stopper.isRunning()) { stopper.start(); } }); // 将装饰后的JPanel组件添加到容器中 f.add(layer); f.setSize(300, 170); f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); f.setVisible (true); } public static void main(String[] args) { new WaitingJLayerTest().init(); } }
public class JProgressBarTest { JFrame frame = new JFrame("测试进度条"); // 创建一条垂直进度条 JProgressBar bar = new JProgressBar(JProgressBar.VERTICAL); JCheckBox indeterminate = new JCheckBox("不确定进度"); JCheckBox noBorder = new JCheckBox("不绘制边框"); public void init() { Box box = new Box(BoxLayout.Y_AXIS); box.add(indeterminate); box.add(noBorder); frame.setLayout(new FlowLayout()); frame.add(box); // 把进度条添加到JFrame窗口中 frame.add(bar); // 设置进度条的最大值和最小值 bar.setMinimum(0); bar.setMaximum(100); // 设置在进度条中绘制完成百分比 bar.setStringPainted(true); // 根据该选择框决定是否绘制进度条的边框 noBorder.addActionListener(event -> bar.setBorderPainted(!noBorder.isSelected())); indeterminate.addActionListener(event -> { // 设置该进度条的进度是否确定 bar.setIndeterminate(indeterminate.isSelected()); bar.setStringPainted(!indeterminate.isSelected()); }); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); // 采用循环方式来不断改变进度条的完成进度 for (int i = 0 ; i <= 100 ; i++) { // 改变进度条的完成进度 bar.setValue(i); try { // 程序暂停0.1秒 Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { new JProgressBarTest().init(); } }
public class JProgressBarTest2 { JFrame frame = new JFrame("测试进度条"); // 创建一条垂直进度条 JProgressBar bar = new JProgressBar(JProgressBar.VERTICAL); JCheckBox indeterminate = new JCheckBox("不确定进度"); JCheckBox noBorder = new JCheckBox("不绘制边框"); public void init() { Box box = new Box(BoxLayout.Y_AXIS); box.add(indeterminate); box.add(noBorder); frame.setLayout(new FlowLayout()); frame.add(box); // 把进度条添加到JFrame窗口中 frame.add(bar); // 设置在进度条中绘制完成百分比 bar.setStringPainted(true); // 根据该选择框决定是否绘制进度条的边框 noBorder.addActionListener(event -> bar.setBorderPainted(!noBorder.isSelected())); final SimulatedActivity target = new SimulatedActivity(1000); // 以启动一条线程的方式来执行一个耗时的任务 new Thread(target).start(); // 设置进度条的最大值和最小值, bar.setMinimum(0); // 以总任务量作为进度条的最大值 bar.setMaximum(target.getAmount()); // 以任务的当前完成量设置进度条的value Timer timer = new Timer(300 , e -> bar.setValue(target.getCurrent())); timer.start(); indeterminate.addActionListener(event -> { // 设置该进度条的进度是否确定 bar.setIndeterminate(indeterminate.isSelected()); bar.setStringPainted(!indeterminate.isSelected()); }); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setVisible(true); } public static void main(String[] args) { new JProgressBarTest2().init(); } } // 模拟一个耗时的任务 class SimulatedActivity implements Runnable { // 任务的当前完成量 private volatile int current; // 总任务量 private int amount; public SimulatedActivity(int amount) { current = 0; this.amount = amount; } public int getAmount() { return amount; } public int getCurrent() { return current; } // run方法代表不断完成任务的过程 public void run() { while (current < amount) { try { Thread.sleep(50); } catch (InterruptedException e) { } current++; } } }
public class ProgressMonitorTest { Timer timer; public void init() { final SimulatedActivity target = new SimulatedActivity(1000); // 以启动一条线程的方式来执行一个耗时的任务 final Thread targetThread = new Thread(target); targetThread.start(); final ProgressMonitor dialog = new ProgressMonitor(null , "等待任务完成" , "已完成:" , 0 , target.getAmount()); timer = new Timer(300 , e -> { // 以任务的当前完成量设置进度对话框的完成比例 dialog.setProgress(target.getCurrent()); // 如果用户单击了进度对话框的"取消"按钮 if (dialog.isCanceled()) { // 停止计时器 timer.stop(); // 中断任务的执行线程 targetThread.interrupt(); // ① // 系统退出 System.exit(0); } }); timer.start(); } public static void main(String[] args) { new ProgressMonitorTest().init(); } }
public class JSliderTest { JFrame mainWin = new JFrame("滑动条示范"); Box sliderBox = new Box(BoxLayout.Y_AXIS); JTextField showVal = new JTextField(); ChangeListener listener; public void init() { // 定义一个监听器,用于监听所有滑动条 listener = event -> { // 取出滑动条的值,并在文本中显示出来 JSlider source = (JSlider) event.getSource(); showVal.setText("当前滑动条的值为:" + source.getValue()); }; // -----------添加一个普通滑动条----------- JSlider slider = new JSlider(); addSlider(slider, "普通滑动条"); // -----------添加保留区为30的滑动条----------- slider = new JSlider(); slider.setExtent(30); addSlider(slider, "保留区为30"); // ---添加带主、次刻度的滑动条,并设置其最大值,最小值--- slider = new JSlider(30 , 200); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "有刻度"); // -----------添加滑块必须停在刻度处滑动条----------- slider = new JSlider(); // 设置滑块必须停在刻度处 slider.setSnapToTicks(true); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); addSlider(slider, "滑块停在刻度处"); // -----------添加没有滑轨的滑动条----------- slider = new JSlider(); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); // 设置不绘制滑轨 slider.setPaintTrack(false); addSlider(slider, "无滑轨"); // -----------添加方向反转的滑动条----------- slider = new JSlider(); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); // 设置方向反转 slider.setInverted(true); addSlider(slider, "方向反转"); // --------添加绘制默认刻度标签的滑动条-------- slider = new JSlider(); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); // 设置绘制刻度标签,默认绘制数值刻度标签 slider.setPaintLabels(true); addSlider(slider, "数值刻度标签"); // ------添加绘制Label类型的刻度标签的滑动条------ slider = new JSlider(); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); // 设置绘制刻度标签 slider.setPaintLabels(true); Dictionary<Integer, Component> labelTable = new Hashtable<>(); labelTable.put(0, new JLabel("A")); labelTable.put(20, new JLabel("B")); labelTable.put(40, new JLabel("C")); labelTable.put(60, new JLabel("D")); labelTable.put(80, new JLabel("E")); labelTable.put(100, new JLabel("F")); // 指定刻度标签,标签是JLabel slider.setLabelTable(labelTable); addSlider(slider, "JLable标签"); // ------添加绘制Label类型的刻度标签的滑动条------ slider = new JSlider(); // 设置绘制刻度 slider.setPaintTicks(true); // 设置主、次刻度的间距 slider.setMajorTickSpacing(20); slider.setMinorTickSpacing(5); // 设置绘制刻度标签 slider.setPaintLabels(true); labelTable = new Hashtable<Integer, Component>(); labelTable.put(0, new JLabel(new ImageIcon("ico/0.GIF"))); labelTable.put(20, new JLabel(new ImageIcon("ico/2.GIF"))); labelTable.put(40, new JLabel(new ImageIcon("ico/4.GIF"))); labelTable.put(60, new JLabel(new ImageIcon("ico/6.GIF"))); labelTable.put(80, new JLabel(new ImageIcon("ico/8.GIF"))); // 指定刻度标签,标签是ImageIcon slider.setLabelTable(labelTable); addSlider(slider, "Icon标签"); mainWin.add(sliderBox, BorderLayout.CENTER); mainWin.add(showVal, BorderLayout.SOUTH); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } // 定义一个方法,用于将滑动条添加到容器中 public void addSlider(JSlider slider, String description) { slider.addChangeListener(listener); Box box = new Box(BoxLayout.X_AXIS); box.add(new JLabel(description + ":")); box.add(slider); sliderBox.add(box); } public static void main(String[] args) { new JSliderTest().init(); } }
public class JSpinnerTest { final int SPINNER_NUM = 6; JFrame mainWin = new JFrame("微调控制器示范"); Box spinnerBox = new Box(BoxLayout.Y_AXIS); JSpinner[] spinners = new JSpinner[SPINNER_NUM]; JLabel[] valLabels = new JLabel[SPINNER_NUM]; JButton okBn = new JButton("确定"); public void init() { for (int i = 0 ; i < SPINNER_NUM ; i++ ) { valLabels[i] = new JLabel(); } // -----------普通JSpinner----------- spinners[0] = new JSpinner(); addSpinner(spinners[0], "普通" , valLabels[0]); // -----------指定最小值、最大值、步长的JSpinner----------- // 创建一个SpinnerNumberModel对象,指定最小值、最大值和步长 SpinnerNumberModel numModel = new SpinnerNumberModel( 3.4 , -1.1 , 4.3 , 0.1); spinners[1] = new JSpinner(numModel); addSpinner(spinners[1], "数值范围" , valLabels[1]); // -----------使用SpinnerListModel的JSpinner------------ String[] books = new String[] { "轻量级Java EE企业应用实战" , "疯狂Java讲义" , "疯狂Ajax讲义" }; // 使用字符串数组创建SpinnerListModel对象 SpinnerListModel bookModel = new SpinnerListModel(books); // 使用SpinnerListModel对象创建JSpinner对象 spinners[2] = new JSpinner(bookModel); addSpinner(spinners[2], "字符串序列值" , valLabels[2]); // -----------使用序列值是ImageIcon的JSpinner------------ ArrayList<ImageIcon> icons = new ArrayList<>(); icons.add(new ImageIcon("a.gif")); icons.add(new ImageIcon("b.gif")); // 使用ImageIcon数组创建SpinnerListModel对象 SpinnerListModel iconModel = new SpinnerListModel(icons); // 使用SpinnerListModel对象创建JSpinner对象 spinners[3] = new JSpinner(iconModel); addSpinner(spinners[3], "图标序列值" , valLabels[3]); // -----------使用SpinnerDateModel的JSpinner------------ // 分别获取起始时间、结束时间、初时时间 Calendar cal = Calendar.getInstance(); Date init = cal.getTime(); cal.add(Calendar.DAY_OF_MONTH , -3); Date start = cal.getTime(); cal.add(Calendar.DAY_OF_MONTH , 8); Date end = cal.getTime(); // 创建一个SpinnerDateModel对象,指定最小时间、最大时间和初始时间 SpinnerDateModel dateModel = new SpinnerDateModel(init , start , end , Calendar.HOUR_OF_DAY); // 以SpinnerDateModel对象创建JSpinner spinners[4] = new JSpinner(dateModel); addSpinner(spinners[4], "时间范围" , valLabels[4]); // -----------使用DateEditor来格式化JSpinner------------ dateModel = new SpinnerDateModel(); spinners[5] = new JSpinner(dateModel); // 创建一个JSpinner.DateEditor对象,用于对指定Spinner进行格式化 JSpinner.DateEditor editor = new JSpinner.DateEditor( spinners[5] , "公元yyyy年MM月dd日 HH时"); // 设置使用JSpinner.DateEditor对象进行格式化 spinners[5].setEditor(editor); addSpinner(spinners[5], "使用DateEditor" , valLabels[5]); // 为“确定”按钮添加一个事件监听器 okBn.addActionListener(evt -> { // 取出每个微调控制器的值,并将该值用后面的Label标签显示出来。 for (int i = 0 ; i < SPINNER_NUM ; i++) { // 将微调控制器的值通过指定的JLabel显示出来 valLabels[i].setText(spinners[i].getValue().toString()); } }); JPanel bnPanel = new JPanel(); bnPanel.add(okBn); mainWin.add(spinnerBox, BorderLayout.CENTER); mainWin.add(bnPanel, BorderLayout.SOUTH); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } // 定义一个方法,用于将滑动条添加到容器中 public void addSpinner(JSpinner spinner, String description, JLabel valLabel) { Box box = new Box(BoxLayout.X_AXIS); JLabel desc = new JLabel(description + ":"); desc.setPreferredSize(new Dimension(100, 30)); box.add(desc); box.add(spinner); valLabel.setPreferredSize(new Dimension(180, 30)); box.add(valLabel); spinnerBox.add(box); } public static void main(String[] args) { new JSpinnerTest().init(); } }
public class DefaultListModelTest { private JFrame mainWin = new JFrame("测试DefaultListModel"); // 定义一个JList对象 private JList<String> bookList; // 定义一个DefaultListModel对象 private DefaultListModel<String> bookModel = new DefaultListModel<>(); private JTextField bookName = new JTextField(20); private JButton removeBn = new JButton("删除选中图书"); private JButton addBn = new JButton("添加指定图书"); public void init() { // 向bookModel中添加元素 bookModel.addElement("疯狂Java讲义"); bookModel.addElement("轻量级Java EE企业应用实战"); bookModel.addElement("疯狂Android讲义"); bookModel.addElement("疯狂Ajax讲义"); bookModel.addElement("经典Java EE企业应用实战"); // 根据DefaultListModel对象创建一个JList对象 bookList = new JList<>(bookModel); // 设置最大可视高度 bookList.setVisibleRowCount(4); // 只能单选 bookList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 为添加按钮添加事件监听器 addBn.addActionListener(evt -> { // 当bookName文本框的内容不为空。 if (!bookName.getText().trim().equals("")) { // 向bookModel中添加一个元素, // 系统自动会向JList中添加对应的列表项 bookModel.addElement(bookName.getText()); } }); // 为删除按钮添加事件监听器 removeBn.addActionListener(evt -> { // 如果用户已经选中的一项 if (bookList.getSelectedIndex() >= 0) { // 从bookModel中删除指定索引处的元素, // 系统自动会删除JList对应的列表项 bookModel.removeElementAt(bookList.getSelectedIndex()); } }); JPanel p = new JPanel(); p.add(bookName); p.add(addBn); p.add(removeBn); // 添加bookList组件 mainWin.add(new JScrollPane(bookList)); // 将p面板添加到窗口中 mainWin.add(p , BorderLayout.SOUTH); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } public static void main(String[] args) { new DefaultListModelTest().init(); } }
public class ListModelTest { private JFrame mainWin = new JFrame("测试ListModel"); // 根据NumberListModel对象来创建一个JList对象 private JList<BigDecimal> numScopeList = new JList<>(new NumberListModel(1, 21, 2)); // 根据NumberComboBoxModel对象来创建JComboBox对象 private JComboBox<BigDecimal> numScopeSelector = new JComboBox<>( new NumberComboBoxModel(0.1, 1.2, 0.1)); private JTextField showVal = new JTextField(10); public void init() { // JList的可视高度可同时显示4个列表项 numScopeList.setVisibleRowCount(4); // 默认选中第三项到第五项(第一项的索引是0) numScopeList.setSelectionInterval(2, 4); // 设置每个列表项具有指定的高度和宽度。 numScopeList.setFixedCellHeight(30); numScopeList.setFixedCellWidth(90); // 为numScopeList添加监听器 numScopeList.addListSelectionListener(e -> { // 获取用户所选中的所有数字 List<BigDecimal> nums = numScopeList.getSelectedValuesList(); showVal.setText(""); // 把用户选中的数字添加到单行文本框中 for (BigDecimal num : nums ) { showVal.setText(showVal.getText() + num.toString() + ", "); } }); // 设置列表项的可视高度可显示5个列表项 numScopeSelector.setMaximumRowCount(5); Box box = new Box(BoxLayout.X_AXIS); box.add(new JScrollPane(numScopeList)); JPanel p = new JPanel(); p.add(numScopeSelector); box.add(p); // 为numScopeSelector添加监听器 numScopeSelector.addItemListener(e -> { // 获取JComboBox中选中的数字 Object num = numScopeSelector.getSelectedItem(); showVal.setText(num.toString()); }); JPanel bottom = new JPanel(); bottom.add(new JLabel("您选择的值是:")); bottom.add(showVal); mainWin.add(box); mainWin.add(bottom , BorderLayout.SOUTH); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } public static void main(String[] args) { new ListModelTest().init(); } } class NumberListModel extends AbstractListModel<BigDecimal> { protected BigDecimal start; protected BigDecimal end; protected BigDecimal step; public NumberListModel(double start, double end, double step) { this.start = BigDecimal.valueOf(start); this.end = BigDecimal.valueOf(end); this.step = BigDecimal.valueOf(step); } // 返回列表项的个数 public int getSize() { return (int) Math.floor(end.subtract(start).divide(step).doubleValue()) + 1; } // 返回指定索引处的列表项 public BigDecimal getElementAt(int index) { return BigDecimal.valueOf(index).multiply(step).add(start); } } class NumberComboBoxModel extends NumberListModel implements ComboBoxModel<BigDecimal> { // 用于保存用户选中项的索引 private int selectId = 0; public NumberComboBoxModel(double start, double end, double step) { super(start, end, step); } // 设置选中“选择项” public void setSelectedItem(Object anItem) { if (anItem instanceof BigDecimal) { BigDecimal target = (BigDecimal) anItem; // 根据选中的值来修改选中项的索引 selectId = target.subtract(super.start).divide(step).intValue(); } } // 获取“选择项”的值 public BigDecimal getSelectedItem() { // 根据选中项的索引来取得选中项 return BigDecimal.valueOf(selectId).multiply(step).add(start); } }
public class ListRenderingTest { private JFrame mainWin = new JFrame("好友列表"); private String[] friends = new String[] { "李清照", "苏格拉底", "李白", "弄玉", "虎头" }; // 定义一个JList对象 private JList<String> friendsList = new JList<>(friends); public void init() { // 设置该JList使用ImageCellRenderer作为列表项绘制器 friendsList.setCellRenderer(new ImageCellRenderer()); mainWin.add(new JScrollPane(friendsList)); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } public static void main(String[] args) { new ListRenderingTest().init(); } } class ImageCellRenderer extends JPanel implements ListCellRenderer<String> { private ImageIcon icon; private String name; // 定义绘制单元格时的背景色 private Color background; // 定义绘制单元格时的前景色 private Color foreground; public Component getListCellRendererComponent(JList list, String value, int index, boolean isSelected, boolean cellHasFocus) { icon = new ImageIcon("ico/" + value + ".gif"); name = value; background = isSelected ? list.getSelectionBackground() : list .getBackground(); foreground = isSelected ? list.getSelectionForeground() : list .getForeground(); // 返回该JPanel对象作为列表项绘制器 return this; } // 重写paintComponent方法,改变JPanel的外观 public void paintComponent(Graphics g) { int imageWidth = icon.getImage().getWidth(null); int imageHeight = icon.getImage().getHeight(null); g.setColor(background); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(foreground); // 绘制好友图标 g.drawImage(icon.getImage(), getWidth() / 2 - imageWidth / 2, 10, null); g.setFont(new Font("SansSerif", Font.BOLD, 18)); // 绘制好友用户名 g.drawString(name, getWidth() / 2 - name.length() * 10, imageHeight + 30); } // 通过该方法来设置该ImageCellRenderer的最佳大小 public Dimension getPreferredSize() { return new Dimension(60, 80); } }
public class ListTest { private JFrame mainWin = new JFrame("测试列表框"); String[] books = new String[] { "疯狂Java讲义", "轻量级Java EE企业应用实战", "疯狂Android讲义", "疯狂Ajax讲义", "经典Java EE企业应用实战" }; // 用一个字符串数组来创建一个JList对象 JList<String> bookList = new JList<>(books); JComboBox<String> bookSelector; // 定义布局选择按钮所在的面板 JPanel layoutPanel = new JPanel(); ButtonGroup layoutGroup = new ButtonGroup(); // 定义选择模式按钮所在的面板 JPanel selectModePanel = new JPanel(); ButtonGroup selectModeGroup = new ButtonGroup(); JTextArea favoriate = new JTextArea(4, 40); public void init() { // 设置JList的可视高度可同时显示三个列表项 bookList.setVisibleRowCount(3); // 默认选中第三项到第五项(第一项的索引是0) bookList.setSelectionInterval(2, 4); addLayoutButton("纵向滚动", JList.VERTICAL); addLayoutButton("纵向换行", JList.VERTICAL_WRAP); addLayoutButton("横向换行", JList.HORIZONTAL_WRAP); addSelectModelButton("无限制", ListSelectionModel .MULTIPLE_INTERVAL_SELECTION); addSelectModelButton("单选", ListSelectionModel .SINGLE_SELECTION); addSelectModelButton("单范围", ListSelectionModel .SINGLE_INTERVAL_SELECTION); Box listBox = new Box(BoxLayout.Y_AXIS); // 将JList组件放在JScrollPane中,再将该JScrollPane添加到listBox容器中 listBox.add(new JScrollPane(bookList)); // 添加布局选择按钮面板、选择模式按钮面板 listBox.add(layoutPanel); listBox.add(selectModePanel); // 为JList添加事件监听器 bookList.addListSelectionListener(e -> { // ① // 获取用户所选择的所有图书 List<String> books = bookList.getSelectedValuesList(); favoriate.setText(""); for (String book : books ) { favoriate.append(book + "\n"); } }); Vector<String> bookCollection = new Vector<>(); bookCollection.add("疯狂Java讲义"); bookCollection.add("轻量级Java EE企业应用实战"); bookCollection.add("疯狂Android讲义"); bookCollection.add("疯狂Ajax讲义"); bookCollection.add("经典Java EE企业应用实战"); // 用一个Vector对象来创建一个JComboBox对象 bookSelector = new JComboBox<>(bookCollection); // 为JComboBox添加事件监听器 bookSelector.addItemListener(e -> { // ② // 获取JComboBox所选中的项 Object book = bookSelector.getSelectedItem(); favoriate.setText(book.toString()); }); // 设置可以直接编辑 bookSelector.setEditable(true); // 设置下拉列表框的可视高度可同时显示4个列表项 bookSelector.setMaximumRowCount(4); JPanel p = new JPanel(); p.add(bookSelector); Box box = new Box(BoxLayout.X_AXIS); box.add(listBox); box.add(p); mainWin.add(box); JPanel favoriatePanel = new JPanel(); favoriatePanel.setLayout(new BorderLayout()); favoriatePanel.add(new JScrollPane(favoriate)); favoriatePanel.add(new JLabel("您喜欢的图书:") , BorderLayout.NORTH); mainWin.add(favoriatePanel , BorderLayout.SOUTH); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.pack(); mainWin.setVisible(true); } private void addLayoutButton(String label, final int orientation) { layoutPanel.setBorder(new TitledBorder(new EtchedBorder() , "确定选项布局")); JRadioButton button = new JRadioButton(label); // 把该单选按钮添加到layoutPanel面板中 layoutPanel.add(button); // 默认选中第一个按钮 if (layoutGroup.getButtonCount() == 0) button.setSelected(true); layoutGroup.add(button); button.addActionListener(event -> // 改变列表框里列表项的布局方向 bookList.setLayoutOrientation(orientation)); } private void addSelectModelButton(String label, final int selectModel) { selectModePanel.setBorder(new TitledBorder(new EtchedBorder() , "确定选择模式")); JRadioButton button = new JRadioButton(label); // 把该单选按钮添加到selectModePanel面板中 selectModePanel.add(button); // 默认选中第一个按钮 if(selectModeGroup.getButtonCount() == 0) button.setSelected(true); selectModeGroup.add(button); button.addActionListener(event -> // 改变列表框里的选择模式 bookList.setSelectionMode(selectModel)); } public static void main(String[] args) { new ListTest().init(); } }
public class ChangeAllCellRender { JFrame jf = new JFrame("改变所有节点的外观"); JTree tree; // 定义几个初始节点 DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国"); DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东"); DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西"); DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山"); DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头"); DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林"); DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁"); public void init() { // 通过add()方法建立树节点之间的父子关系 guangdong.add(foshan); guangdong.add(shantou); guangxi.add(guilin); guangxi.add(nanning); root.add(guangdong); root.add(guangxi); // 以根节点创建树 tree = new JTree(root); // 创建一个DefaultTreeCellRender对象 DefaultTreeCellRenderer cellRender = new DefaultTreeCellRenderer(); // 设置非选定节点的背景色。 cellRender.setBackgroundNonSelectionColor(new Color(220, 220, 220)); // 设置节点在选中状态下的背景颜色。 cellRender.setBackgroundSelectionColor(new Color(140, 140, 140)); // 设置选中状态下节点的边框颜色。 cellRender.setBorderSelectionColor(Color.BLACK); // 设置处于折叠状态下非叶子节点的图标。 cellRender.setClosedIcon(new ImageIcon("icon/close.gif")); // 设置节点文本的字体。 cellRender.setFont(new Font("SansSerif", Font.BOLD, 16)); // 设置叶子节点的图标。 cellRender.setLeafIcon(new ImageIcon("icon/leaf.png")); // 设置处于展开状态下非叶子节点的图标。 cellRender.setOpenIcon(new ImageIcon("icon/open.gif")); // 设置绘制非选中状态下节点文本的颜色。 cellRender.setTextNonSelectionColor(new Color(255, 0, 0)); // 设置绘制选中状态下节点文本的颜色。 cellRender.setTextSelectionColor(new Color(0, 0, 255)); tree.setCellRenderer(cellRender); // 设置是否显示根节点的“展开/折叠”图标,默认是false tree.setShowsRootHandles(true); // 设置节点是否可见,默认是true tree.setRootVisible(true); jf.add(new JScrollPane(tree)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new ChangeAllCellRender().init(); } }
public class CustomTreeNode { JFrame jf = new JFrame("定制树的节点"); JTree tree; // 定义几个初始节点 DefaultMutableTreeNode friends = new DefaultMutableTreeNode("我的好友"); DefaultMutableTreeNode qingzhao = new DefaultMutableTreeNode("李清照"); DefaultMutableTreeNode suge = new DefaultMutableTreeNode("苏格拉底"); DefaultMutableTreeNode libai = new DefaultMutableTreeNode("李白"); DefaultMutableTreeNode nongyu = new DefaultMutableTreeNode("弄玉"); DefaultMutableTreeNode hutou = new DefaultMutableTreeNode("虎头"); public void init() { // 通过add()方法建立树节点之间的父子关系 friends.add(qingzhao); friends.add(suge); friends.add(libai); friends.add(nongyu); friends.add(hutou); // 以根节点创建树 tree = new JTree(friends); // 设置是否显示根节点的“展开/折叠”图标,默认是false tree.setShowsRootHandles(true); // 设置节点是否可见,默认是true tree.setRootVisible(true); // 设置使用定制的节点绘制器 tree.setCellRenderer(new ImageCellRenderer()); jf.add(new JScrollPane(tree)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new CustomTreeNode().init(); } } // 实现自己的节点绘制器 class ImageCellRenderer extends JPanel implements TreeCellRenderer { private ImageIcon icon; private String name; // 定义绘制单元格时的背景色 private Color background; // 定义绘制单元格时的前景色 private Color foreground; public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { icon = new ImageIcon("icon/" + value + ".gif"); name = value.toString(); background = hasFocus ? new Color(140, 200, 235) : new Color(255, 255, 255); foreground = hasFocus ? new Color(255, 255, 3) : new Color(0, 0, 0); // 返回该JPanel对象作为单元格绘制器 return this; } // 重写paintComponent方法,改变JPanel的外观 public void paintComponent(Graphics g) { int imageWidth = icon.getImage().getWidth(null); int imageHeight = icon.getImage().getHeight(null); g.setColor(background); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(foreground); // 绘制好友图标 g.drawImage(icon.getImage(), getWidth() / 2 - imageWidth / 2, 10, null); g.setFont(new Font("SansSerif", Font.BOLD, 18)); // 绘制好友用户名 g.drawString(name, getWidth() / 2 - name.length() * 10, imageHeight + 30); } // 通过该方法来设置该ImageCellRenderer的最佳大小 public Dimension getPreferredSize() { return new Dimension(80, 80); } }
public class EditJTree { JFrame jf; JTree tree; // 上面JTree对象对应的model DefaultTreeModel model; // 定义几个初始节点 DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国"); DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东"); DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西"); DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山"); DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头"); DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林"); DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁"); // 定义需要被拖动的TreePath TreePath movePath; JButton addSiblingButton = new JButton("添加兄弟节点"); JButton addChildButton = new JButton("添加子节点"); JButton deleteButton = new JButton("删除节点"); JButton editButton = new JButton("编辑当前节点"); public void init() { guangdong.add(foshan); guangdong.add(shantou); guangxi.add(guilin); guangxi.add(nanning); root.add(guangdong); root.add(guangxi); jf = new JFrame("可编辑节点的树"); tree = new JTree(root); // 获取JTree对应的TreeModel对象 model = (DefaultTreeModel)tree.getModel(); // 设置JTree可编辑 tree.setEditable(true); MouseListener ml = new MouseAdapter() { // 按下鼠标时获得被拖动的节点 public void mousePressed(MouseEvent e) { // 如果需要唯一确定某个节点,必须通过TreePath来获取。 TreePath tp = tree.getPathForLocation( e.getX() , e.getY()); if (tp != null) { movePath = tp; } } // 鼠标松开时获得需要拖到哪个父节点 public void mouseReleased(MouseEvent e) { // 根据鼠标松开时的TreePath来获取TreePath TreePath tp = tree.getPathForLocation( e.getX(), e.getY()); if (tp != null && movePath != null) { // 阻止向子节点拖动 if (movePath.isDescendant(tp) && movePath != tp) { JOptionPane.showMessageDialog(jf, "目标节点是被移动节点的子节点,无法移动!", "非法操作", JOptionPane.ERROR_MESSAGE ); return; } // 既不是向子节点移动,而且鼠标按下、松开的不是同一个节点 else if (movePath != tp) { // add方法先将该节点从原父节下删除,再添加到新父节点下 ((DefaultMutableTreeNode)tp.getLastPathComponent()) .add((DefaultMutableTreeNode)movePath .getLastPathComponent()); movePath = null; tree.updateUI(); } } } }; // 为JTree添加鼠标监听器 tree.addMouseListener(ml); JPanel panel = new JPanel(); // 实现添加兄弟节点的监听器 addSiblingButton.addActionListener(event -> { // 获取选中节点 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); // 如果节点为空,直接返回 if (selectedNode == null) return; // 获取该选中节点的父节点 DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent(); // 如果父节点为空,直接返回 if (parent == null) return; // 创建一个新节点 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新节点"); // 获取选中节点的选中索引 int selectedIndex = parent.getIndex(selectedNode); // 在选中位置插入新节点 model.insertNodeInto(newNode, parent, selectedIndex + 1); // --------下面代码实现显示新节点(自动展开父节点)------- // 获取从根节点到新节点的所有节点 TreeNode[] nodes = model.getPathToRoot(newNode); // 使用指定的节点数组来创建TreePath TreePath path = new TreePath(nodes); // 显示指定TreePath tree.scrollPathToVisible(path); }); panel.add(addSiblingButton); // 实现添加子节点的监听器 addChildButton.addActionListener(event -> { // 获取选中节点 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); // 如果节点为空,直接返回 if (selectedNode == null) return; // 创建一个新节点 DefaultMutableTreeNode newNode = new DefaultMutableTreeNode("新节点"); // 通过model来添加新节点,则无须通过调用JTree的updateUI方法 // model.insertNodeInto(newNode, selectedNode // , selectedNode.getChildCount()); // 通过节点添加新节点,则需要调用tree的updateUI方法 selectedNode.add(newNode); // --------下面代码实现显示新节点(自动展开父节点)------- TreeNode[] nodes = model.getPathToRoot(newNode); TreePath path = new TreePath(nodes); tree.scrollPathToVisible(path); tree.updateUI(); }); panel.add(addChildButton); // 实现删除节点的监听器 deleteButton.addActionListener(event -> { DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); if (selectedNode != null && selectedNode.getParent() != null) { // 删除指定节点 model.removeNodeFromParent(selectedNode); } }); panel.add(deleteButton); // 实现编辑节点的监听器 editButton.addActionListener(event -> { TreePath selectedPath = tree.getSelectionPath(); if (selectedPath != null) { // 编辑选中节点 tree.startEditingAtPath(selectedPath); } }); panel.add(editButton); jf.add(new JScrollPane(tree)); jf.add(panel , BorderLayout.SOUTH); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new EditJTree().init(); } }
public class ExtendsDefaultTreeCellRenderer { JFrame jf = new JFrame("根据节点类型定义图标"); JTree tree; // 定义几个初始节点 DefaultMutableTreeNode root = new DefaultMutableTreeNode(new NodeData( DBObjectType.ROOT, "数据库导航")); DefaultMutableTreeNode salaryDb = new DefaultMutableTreeNode(new NodeData( DBObjectType.DATABASE, "公司工资数据库")); DefaultMutableTreeNode customerDb = new DefaultMutableTreeNode( new NodeData(DBObjectType.DATABASE, "公司客户数据库")); // 定义salaryDb的两个子节点 DefaultMutableTreeNode employee = new DefaultMutableTreeNode(new NodeData( DBObjectType.TABLE, "员工表")); DefaultMutableTreeNode attend = new DefaultMutableTreeNode(new NodeData( DBObjectType.TABLE, "考勤表")); // 定义customerDb的一个子节点 DefaultMutableTreeNode contact = new DefaultMutableTreeNode(new NodeData( DBObjectType.TABLE, "联系方式表")); // 定义employee的三个子节点 DefaultMutableTreeNode id = new DefaultMutableTreeNode(new NodeData( DBObjectType.INDEX, "员工ID")); DefaultMutableTreeNode name = new DefaultMutableTreeNode(new NodeData( DBObjectType.COLUMN, "姓名")); DefaultMutableTreeNode gender = new DefaultMutableTreeNode(new NodeData( DBObjectType.COLUMN, "性别")); public void init() { // 通过add()方法建立树节点之间的父子关系 root.add(salaryDb); root.add(customerDb); salaryDb.add(employee); salaryDb.add(attend); customerDb.add(contact); employee.add(id); employee.add(name); employee.add(gender); // 以根节点创建树 tree = new JTree(root); // 设置该JTree使用自定义的节点绘制器 tree.setCellRenderer(new MyRenderer()); // 设置是否显示根节点的“展开/折叠”图标,默认是false tree.setShowsRootHandles(true); // 设置节点是否可见,默认是true tree.setRootVisible(true); try { // 设置使用Windows风格外观 UIManager.setLookAndFeel("com.sun.java.swing.plaf." + "windows.WindowsLookAndFeel"); } catch (Exception ex) { } // 更新JTree的UI外观 SwingUtilities.updateComponentTreeUI(tree); jf.add(new JScrollPane(tree)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new ExtendsDefaultTreeCellRenderer().init(); } } // 定义一个NodeData类,用于封装节点数据 class NodeData { public int nodeType; public String nodeData; public NodeData(int nodeType, String nodeData) { this.nodeType = nodeType; this.nodeData = nodeData; } public String toString() { return nodeData; } } // 定义一个接口,该接口里包含数据库对象类型的常量 interface DBObjectType { int ROOT = 0; int DATABASE = 1; int TABLE = 2; int COLUMN = 3; int INDEX = 4; } class MyRenderer extends DefaultTreeCellRenderer { // 初始化5个图标 ImageIcon rootIcon = new ImageIcon("icon/root.gif"); ImageIcon databaseIcon = new ImageIcon("icon/database.gif"); ImageIcon tableIcon = new ImageIcon("icon/table.gif"); ImageIcon columnIcon = new ImageIcon("icon/column.gif"); ImageIcon indexIcon = new ImageIcon("icon/index.gif"); public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { // 执行父类默认的节点绘制操作 super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); DefaultMutableTreeNode node = (DefaultMutableTreeNode) value; NodeData data = (NodeData) node.getUserObject(); // 根据数据节点里的nodeType数据决定节点图标 ImageIcon icon = null; switch (data.nodeType) { case DBObjectType.ROOT: icon = rootIcon; break; case DBObjectType.DATABASE: icon = databaseIcon; break; case DBObjectType.TABLE: icon = tableIcon; break; case DBObjectType.COLUMN: icon = columnIcon; break; case DBObjectType.INDEX: icon = indexIcon; break; } // 改变图标 this.setIcon(icon); return this; } }
public class SelectJTree { JFrame jf = new JFrame("监听树的选择事件"); JTree tree; // 定义几个初始节点 DefaultMutableTreeNode root = new DefaultMutableTreeNode("中国"); DefaultMutableTreeNode guangdong = new DefaultMutableTreeNode("广东"); DefaultMutableTreeNode guangxi = new DefaultMutableTreeNode("广西"); DefaultMutableTreeNode foshan = new DefaultMutableTreeNode("佛山"); DefaultMutableTreeNode shantou = new DefaultMutableTreeNode("汕头"); DefaultMutableTreeNode guilin = new DefaultMutableTreeNode("桂林"); DefaultMutableTreeNode nanning = new DefaultMutableTreeNode("南宁"); JTextArea eventTxt = new JTextArea(5, 20); public void init() { // 通过add()方法建立树节点之间的父子关系 guangdong.add(foshan); guangdong.add(shantou); guangxi.add(guilin); guangxi.add(nanning); root.add(guangdong); root.add(guangxi); // 以根节点创建树 tree = new JTree(root); // 设置只能选择一个TreePath tree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION); // 添加监听树节点选择事件的监听器 // 当JTree中被选择节点发生改变时,将触发该方法 tree.addTreeSelectionListener(e -> { if (e.getOldLeadSelectionPath() != null) eventTxt.append("原选中的节点路径:" + e.getOldLeadSelectionPath().toString() + "\n"); eventTxt.append("新选中的节点路径:" + e.getNewLeadSelectionPath().toString() + "\n"); }); //设置是否显示根节点的“展开/折叠”图标,默认是false tree.setShowsRootHandles(true); //设置根节点是否可见,默认是true tree.setRootVisible(true); Box box = new Box(BoxLayout.X_AXIS); box.add(new JScrollPane(tree)); box.add(new JScrollPane(eventTxt)); jf.add(box); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new SelectJTree().init(); } }
public class SimpleJTree { JFrame jf = new JFrame("简单树"); JTree tree; DefaultMutableTreeNode root; DefaultMutableTreeNode guangdong; DefaultMutableTreeNode guangxi; DefaultMutableTreeNode foshan; DefaultMutableTreeNode shantou; DefaultMutableTreeNode guilin; DefaultMutableTreeNode nanning; public void init() { // 依次创建树中所有节点 root = new DefaultMutableTreeNode("中国"); guangdong = new DefaultMutableTreeNode("广东"); guangxi = new DefaultMutableTreeNode("广西"); foshan = new DefaultMutableTreeNode("佛山"); shantou = new DefaultMutableTreeNode("汕头"); guilin = new DefaultMutableTreeNode("桂林"); nanning = new DefaultMutableTreeNode("南宁"); // 通过add()方法建立树节点之间的父子关系 guangdong.add(foshan); guangdong.add(shantou); guangxi.add(guilin); guangxi.add(nanning); root.add(guangdong); root.add(guangxi); // 以根节点创建树 tree = new JTree(root); // ① jf.add(new JScrollPane(tree)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new SimpleJTree().init(); } }
public class AdjustingWidth { JFrame jf = new JFrame("调整表格列宽"); JMenuBar menuBar = new JMenuBar(); JMenu adjustModeMenu = new JMenu("调整方式"); JMenu selectUnitMenu = new JMenu("选择单元"); JMenu selectModeMenu = new JMenu("选择方式"); // 定义5个单选框按钮,用以控制表格的宽度调整方式 JRadioButtonMenuItem[] adjustModesItem = new JRadioButtonMenuItem[5]; // 定义3个单选框按钮,用以控制表格的选择方式 JRadioButtonMenuItem[] selectModesItem = new JRadioButtonMenuItem[3]; JCheckBoxMenuItem rowsItem = new JCheckBoxMenuItem("选择行"); JCheckBoxMenuItem columnsItem = new JCheckBoxMenuItem("选择列"); JCheckBoxMenuItem cellsItem = new JCheckBoxMenuItem("选择单元格"); ButtonGroup adjustBg = new ButtonGroup(); ButtonGroup selectBg = new ButtonGroup(); // 定义一个int类型的数组,用于保存表格所有的宽度调整方式 int[] adjustModes = new int[] { JTable.AUTO_RESIZE_OFF, JTable.AUTO_RESIZE_NEXT_COLUMN, JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS, JTable.AUTO_RESIZE_LAST_COLUMN, JTable.AUTO_RESIZE_ALL_COLUMNS }; int[] selectModes = new int[] { ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, ListSelectionModel.SINGLE_INTERVAL_SELECTION, ListSelectionModel.SINGLE_SELECTION }; JTable table; // 定义二维数组作为表格数据 Object[][] tableData = { new Object[] { "李清照", 29, "女" }, new Object[] { "苏格拉底", 56, "男" }, new Object[] { "李白", 35, "男" }, new Object[] { "弄玉", 18, "女" }, new Object[] { "虎头", 2, "男" } }; // 定义一维数据作为列标题 Object[] columnTitle = { "姓名", "年龄", "性别" }; public void init() { // 以二维数组和一维数组来创建一个JTable对象 table = new JTable(tableData , columnTitle); // -----------为窗口安装设置表格调整方式的菜单----------- adjustModesItem[0] = new JRadioButtonMenuItem("只调整表格"); adjustModesItem[1] = new JRadioButtonMenuItem("只调整下一列"); adjustModesItem[2] = new JRadioButtonMenuItem("平均调整余下列"); adjustModesItem[3] = new JRadioButtonMenuItem("只调整最后一列"); adjustModesItem[4] = new JRadioButtonMenuItem("平均调整所有列"); menuBar.add(adjustModeMenu); for (int i = 0; i < adjustModesItem.length ; i++) { // 默认选中第三个菜单项,即对应表格默认的宽度调整方式 if (i == 2) { adjustModesItem[i].setSelected(true); } adjustBg.add(adjustModesItem[i]); adjustModeMenu.add(adjustModesItem[i]); final int index = i; // 为设置调整方式的菜单项添加监听器 adjustModesItem[i].addActionListener(evt -> { // 如果当前菜单项处于选中状态,表格使用对应的调整方式 if (adjustModesItem[index].isSelected()) { table.setAutoResizeMode(adjustModes[index]); //① } }); } // -----------为窗口安装设置表格选择方式的菜单----------- selectModesItem[0] = new JRadioButtonMenuItem("无限制"); selectModesItem[1] = new JRadioButtonMenuItem("单独的连续区"); selectModesItem[2] = new JRadioButtonMenuItem("单选"); menuBar.add(selectModeMenu); for (int i = 0; i < selectModesItem.length ; i++) { // 默认选中第一个菜单项,即对应表格默认的选择方式 if (i == 0) { selectModesItem[i].setSelected(true); } selectBg.add(selectModesItem[i]); selectModeMenu.add(selectModesItem[i]); final int index = i; // 为设置选择方式的菜单项添加监听器 selectModesItem[i].addActionListener(evt -> { // 如果当前菜单项处于选中状态,表格使用对应的选择方式s if (selectModesItem[index].isSelected()) { table.getSelectionModel().setSelectionMode (selectModes[index]); //② } }); } menuBar.add(selectUnitMenu); // -----为窗口安装设置表格选择单元的菜单----- rowsItem.setSelected(table.getRowSelectionAllowed()); columnsItem.setSelected(table.getColumnSelectionAllowed()); cellsItem.setSelected(table.getCellSelectionEnabled()); rowsItem.addActionListener(event -> { table.clearSelection(); // 如果该菜单项处于选中状态,设置表格的选择单元是行 table.setRowSelectionAllowed(rowsItem.isSelected()); // 如果选择行、选择列同时被选中,其实质是选择单元格 cellsItem.setSelected(table.getCellSelectionEnabled()); }); selectUnitMenu.add(rowsItem); columnsItem.addActionListener(event -> { table.clearSelection(); // 如果该菜单项处于选中状态,设置表格的选择单元是列 table.setColumnSelectionAllowed(columnsItem.isSelected()); // 如果选择行、选择列同时被选中,其实质是选择单元格 cellsItem.setSelected(table.getCellSelectionEnabled()); }); selectUnitMenu.add(columnsItem); cellsItem.addActionListener(event -> { table.clearSelection(); // 如果该菜单项处于选中状态,设置表格的选择单元是单元格 table.setCellSelectionEnabled(cellsItem.isSelected()); // 该选项的改变会同时影响选择行、选择列两个菜单 rowsItem.setSelected(table.getRowSelectionAllowed()); columnsItem.setSelected(table.getColumnSelectionAllowed()); }); selectUnitMenu.add(cellsItem); jf.setJMenuBar(menuBar); // 分别获取表格的三个表格列,并设置三列的最小宽度,最佳宽度和最大宽度 TableColumn nameColumn = table.getColumn(columnTitle[0]); nameColumn.setMinWidth(40); TableColumn ageColumn = table.getColumn(columnTitle[1]); ageColumn.setPreferredWidth(50); TableColumn genderColumn = table.getColumn(columnTitle[2]); genderColumn.setMaxWidth(50); // 将JTable对象放在JScrollPane中,并将该JScrollPane放在窗口中显示出来 jf.add(new JScrollPane(table)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new AdjustingWidth().init(); } }
public class DefaultTableModelTest { JFrame mainWin = new JFrame("管理数据行、数据列"); final int COLUMN_COUNT = 5; DefaultTableModel model; JTable table; // 用于保存被隐藏列的List集合 ArrayList<TableColumn> hiddenColumns = new ArrayList<>(); public void init() { model = new DefaultTableModel(COLUMN_COUNT ,COLUMN_COUNT); for (int i = 0; i < COLUMN_COUNT ; i++ ) { for (int j = 0; j < COLUMN_COUNT ; j++ ) { model.setValueAt("老单元格值 " + i + " " + j , i , j); } } table = new JTable(model); mainWin.add(new JScrollPane(table), BorderLayout.CENTER); // 为窗口安装菜单 JMenuBar menuBar = new JMenuBar(); mainWin.setJMenuBar(menuBar); JMenu tableMenu = new JMenu("管理"); menuBar.add(tableMenu); JMenuItem hideColumnsItem = new JMenuItem("隐藏选中列"); hideColumnsItem.addActionListener(event -> { // 获取所有选中列的索引 int[] selected = table.getSelectedColumns(); TableColumnModel columnModel = table.getColumnModel(); // 依次把每一个选中的列隐藏起来,并使用List保存这些列 for (int i = selected.length - 1; i >= 0; i--) { TableColumn column = columnModel.getColumn(selected[i]); // 隐藏指定列 table.removeColumn(column); // 把隐藏的列保存起来,确保以后可以显示出来 hiddenColumns.add(column); } }); tableMenu.add(hideColumnsItem); JMenuItem showColumnsItem = new JMenuItem("显示隐藏列"); showColumnsItem.addActionListener(event -> { // 把所有隐藏列依次显示出来 for (TableColumn tc : hiddenColumns) { // 依次把所有隐藏的列显示出来 table.addColumn(tc); } // 清空保存隐藏列的List集合 hiddenColumns.clear(); }); tableMenu.add(showColumnsItem); JMenuItem addColumnItem = new JMenuItem("插入选中列"); addColumnItem.addActionListener(event -> { // 获取所有选中列的索引 int[] selected = table.getSelectedColumns(); TableColumnModel columnModel = table.getColumnModel(); // 依次把选中的列添加到JTable之后 for (int i = selected.length - 1; i >= 0; i--) { TableColumn column = columnModel .getColumn(selected[i]); table.addColumn(column); } }); tableMenu.add(addColumnItem); JMenuItem addRowItem = new JMenuItem("增加行"); addRowItem.addActionListener(event -> { // 创建一个String数组作为新增行的内容 String[] newCells = new String[COLUMN_COUNT]; for (int i = 0; i < newCells.length; i++) { newCells[i] = "新单元格值 " + model.getRowCount() + " " + i; } // 向TableModel中新增一行。 model.addRow(newCells); }); tableMenu.add(addRowItem); JMenuItem removeRowsItem = new JMenuItem("删除选中行"); removeRowsItem.addActionListener(event -> { // 获取所有选中行 int[] selected = table.getSelectedRows(); // 依次删除所有选中行 for (int i = selected.length - 1; i >= 0; i--) { model.removeRow(selected[i]); } }); tableMenu.add(removeRowsItem); mainWin.pack(); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); } public static void main(String[] args) { new DefaultTableModelTest().init(); } }
public class SimpleTable { JFrame jf = new JFrame("简单表格"); JTable table; // 定义二维数组作为表格数据 Object[][] tableData = { new Object[] { "李清照", 29, "女" }, new Object[] { "苏格拉底", 56, "男" }, new Object[] { "李白", 35, "男" }, new Object[] { "弄玉", 18, "女" }, new Object[] { "虎头", 2, "男" } }; // 定义一维数据作为列标题 Object[] columnTitle = { "姓名", "年龄", "性别" }; public void init() { // 以二维数组和一维数组来创建一个JTable对象 table = new JTable(tableData, columnTitle); // 将JTable对象放在JScrollPane中, // 并将该JScrollPane放在窗口中显示出来 jf.add(new JScrollPane(table)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new SimpleTable().init(); } }
public class SortTable { JFrame jf = new JFrame("可按列排序的表格"); // 定义二维数组作为表格数据 Object[][] tableData = { new Object[] { "李清照", 29, "女" }, new Object[] { "苏格拉底", 56, "男" }, new Object[] { "李白", 35, "男" }, new Object[] { "弄玉", 18, "女" }, new Object[] { "虎头", 2, "男" } }; // 定义一维数据作为列标题 Object[] columnTitle = { "姓名", "年龄", "性别" }; // 以二维数组和一维数组来创建一个JTable对象 JTable table = new JTable(tableData, columnTitle); // 将原表格里的model包装成新的SortableTableModel对象 SortableTableModel sorterModel = new SortableTableModel(table.getModel()); public void init() { // 使用包装后SortableTableModel对象作为JTable的model对象 table.setModel(sorterModel); // 为每列的列头增加鼠标监听器 table.getTableHeader().addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent event) // ① { // 如果单击次数小于2,即不是双击,直接返回 if (event.getClickCount() < 2) { return; } // 找出鼠标双击事件所在的列索引 int tableColumn = table.columnAtPoint(event.getPoint()); // 将JTable中的列索引转换成对应TableModel中的列索引 int modelColumn = table.convertColumnIndexToModel(tableColumn); // 根据指定列进行排序 sorterModel.sort(modelColumn); } }); // 将JTable对象放在JScrollPane中,并将该JScrollPane显示出来 jf.add(new JScrollPane(table)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new SortTable().init(); } } class SortableTableModel extends AbstractTableModel { private TableModel model; private int sortColumn; private Row[] rows; // 将一个已经存在TableModel对象包装成SortableTableModel对象 public SortableTableModel(TableModel m) { // 将被封装的TableModel传入 model = m; rows = new Row[model.getRowCount()]; // 将原TableModel中的每行记录的索引使用Row数组保存起来 for (int i = 0; i < rows.length; i++) { rows[i] = new Row(i); } } // 实现根据指定列进行排序 public void sort(int c) { sortColumn = c; java.util.Arrays.sort(rows); fireTableDataChanged(); } // 下面三个方法需要访问model中的数据,所以涉及本model中数据 // 和被包装model数据中的索引转换,程序使用rows数组完成这种转换。 public Object getValueAt(int r, int c) { return model.getValueAt(rows[r].index, c); } public boolean isCellEditable(int r, int c) { return model.isCellEditable(rows[r].index, c); } public void setValueAt(Object aValue, int r, int c) { model.setValueAt(aValue, rows[r].index, c); } // 下面方法的实现把该model的方法委托为原封装的model来实现 public int getRowCount() { return model.getRowCount(); } public int getColumnCount() { return model.getColumnCount(); } public String getColumnName(int c) { return model.getColumnName(c); } public Class getColumnClass(int c) { return model.getColumnClass(c); } // 定义一个Row类,该类用于封装JTable中的一行 // 实际上它并不封装行数据,它只封装行索引 private class Row implements Comparable<Row> { // 该index保存着被封装Model里每行记录的行索引 public int index; public Row(int index) { this.index = index; } // 实现两行之间的大小比较 public int compareTo(Row other) { Object a = model.getValueAt(index, sortColumn); Object b = model.getValueAt(other.index, sortColumn); if (a instanceof Comparable) { return ((Comparable) a).compareTo(b); } else { return a.toString().compareTo(b.toString()); } } } }
public class TableCellEditorTest { JFrame jf = new JFrame("使用单元格编辑器"); JTable table; // 定义二维数组作为表格数据 Object[][] tableData = { new Object[] { "李清照", 29, "女", new ImageIcon("icon/3.gif"), new ImageIcon("icon/3.gif"), true }, new Object[] { "苏格拉底", 56, "男", new ImageIcon("icon/1.gif"), new ImageIcon("icon/1.gif"), false }, new Object[] { "李白", 35, "男", new ImageIcon("icon/4.gif"), new ImageIcon("icon/4.gif"), true }, new Object[] { "弄玉", 18, "女", new ImageIcon("icon/2.gif"), new ImageIcon("icon/2.gif"), true }, new Object[] { "虎头", 2, "男", new ImageIcon("icon/5.gif"), new ImageIcon("icon/5.gif"), false } }; // 定义一维数据作为列标题 String[] columnTitle = { "姓名", "年龄", "性别", "主头像", "次头像", "是否中国人" }; public void init() { // 以二维数组和一维数组来创建一个ExtendedTableModel对象 ExtendedTableModel model = new ExtendedTableModel(columnTitle, tableData); // 以ExtendedTableModel来创建JTable table = new JTable(model); table.setRowSelectionAllowed(false); table.setRowHeight(40); // 为该表格指定默认的编辑器 table.setDefaultEditor(ImageIcon.class, new ImageCellEditor()); // 获取第五列 TableColumn lastColumn = table.getColumnModel().getColumn(4); // 创建JComboBox对象,并添加多个图标列表项 JComboBox<ImageIcon> editCombo = new JComboBox<>(); for (int i = 1; i <= 10; i++) { editCombo.addItem(new ImageIcon("icon/" + i + ".gif")); } // 设置第五列使用基于JComboBox的DefaultCellEditor lastColumn.setCellEditor(new DefaultCellEditor(editCombo)); // 将JTable对象放在JScrollPane中,并将该JScrollPane放在窗口中显示出来 jf.add(new JScrollPane(table)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new TableCellEditorTest().init(); } } class ExtendedTableModel extends DefaultTableModel { // 重新提供一个构造器,该构造器的实现委托给DefaultTableModel父类 public ExtendedTableModel(String[] columnNames, Object[][] cells) { super(cells, columnNames); } // 重写getColumnClass方法,根据每列的第一个值返回该列真实的数据类型 public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } } // 扩展DefaultCellEditor来实现TableCellEditor类 class ImageCellEditor extends DefaultCellEditor { // 定义文件选择器 private JFileChooser fDialog = new JFileChooser();; private JTextField field = new JTextField(15); private JButton button = new JButton("..."); public ImageCellEditor() { // 因为DefaultCellEditor没有无参数的构造器 // 所以这里显式调用父类有参数的构造器。 super(new JTextField()); initEditor(); } private void initEditor() { field.setEditable(false); // 为按钮添加监听器,当用户单击该按钮时, // 系统将出现一个文件选择器让用户选择图标文件。 button.addActionListener(e -> browse()); // 为文件选择器安装文件过滤器 fDialog.addChoosableFileFilter(new FileFilter() { public boolean accept(File f) { if (f.isDirectory()) { return true; } String extension = Utils.getExtension(f); if (extension != null) { if (extension.equals(Utils.tiff) || extension.equals(Utils.tif) || extension.equals(Utils.gif) || extension.equals(Utils.jpeg) || extension.equals(Utils.jpg) || extension.equals(Utils.png)) { return true; } else { return false; } } return false; } public String getDescription() { return "有效的图片文件"; } }); fDialog.setAcceptAllFileFilterUsed(false); } // 重写TableCellEditor接口的getTableCellEditorComponent方法 // 该方法返回单元格编辑器,该编辑器是一个JPanel, // 该容器包含一个文本框和一个按钮 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) // ① { this.button.setPreferredSize(new Dimension(20, 20)); JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); field.setText(value.toString()); panel.add(this.field, BorderLayout.CENTER); panel.add(this.button, BorderLayout.EAST); return panel; } public Object getCellEditorValue() { return new ImageIcon(field.getText()); } private void browse() { // 设置、打开文件选择器 fDialog.setCurrentDirectory(new File("icon")); int result = fDialog.showOpenDialog(null); // 如果单击了文件选择器的“取消”按钮 if (result == JFileChooser.CANCEL_OPTION) { // 取消编辑 super.cancelCellEditing(); return; } // 如果单击了文件选择器的“确定”按钮 else { // 设置field的内容 field.setText("icon/" + fDialog.getSelectedFile().getName()); } } } class Utils { public final static String jpeg = "jpeg"; public final static String jpg = "jpg"; public final static String gif = "gif"; public final static String tiff = "tiff"; public final static String tif = "tif"; public final static String png = "png"; // 获取文件扩展名的方法 public static String getExtension(File f) { String ext = null; String s = f.getName(); int i = s.lastIndexOf('.'); if (i > 0 && i < s.length() - 1) { ext = s.substring(i + 1).toLowerCase(); } return ext; } }
public class TableCellRendererTest { JFrame jf = new JFrame("使用单元格绘制器"); JTable table; // 定义二维数组作为表格数据 Object[][] tableData = { new Object[] { "李清照", 29, "女", new ImageIcon("icon/3.gif"), true }, new Object[] { "苏格拉底", 56, "男", new ImageIcon("icon/1.gif"), false }, new Object[] { "李白", 35, "男", new ImageIcon("icon/4.gif"), true }, new Object[] { "弄玉", 18, "女", new ImageIcon("icon/2.gif"), true }, new Object[] { "虎头", 2, "男", new ImageIcon("icon/5.gif"), false } }; // 定义一维数据作为列标题 String[] columnTitle = { "姓名", "年龄", "性别", "主头像", "是否中国人" }; public void init() { // 以二维数组和一维数组来创建一个ExtendedTableModel对象 ExtendedTableModel model = new ExtendedTableModel(columnTitle, tableData); // 以ExtendedTableModel来创建JTable table = new JTable(model); table.setRowSelectionAllowed(false); table.setRowHeight(40); // 获取第三列 TableColumn lastColumn = table.getColumnModel().getColumn(2); // 对第三列采用自定义的单元格绘制器 lastColumn.setCellRenderer(new GenderTableCellRenderer()); // 将JTable对象放在JScrollPane中,并将该JScrollPane显示出来 jf.add(new JScrollPane(table)); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } public static void main(String[] args) { new TableCellRendererTest().init(); } } class ExtendedTableModel extends DefaultTableModel { // 重新提供一个构造器,该构造器的实现委托给DefaultTableModel父类 public ExtendedTableModel(String[] columnNames, Object[][] cells) { super(cells, columnNames); } // 重写getColumnClass方法,根据每列的第一个值来返回其真实的数据类型 public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } } // 定义自定义的单元格绘制器 class GenderTableCellRenderer extends JPanel implements TableCellRenderer { private String cellValue; // 定义图标的宽度和高度 final int ICON_WIDTH = 23; final int ICON_HEIGHT = 21; public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { cellValue = (String) value; // 设置选中状态下绘制边框 if (hasFocus) { setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); } else { setBorder(null); } return this; } // 重写paint()方法,负责绘制该单元格内容 public void paint(Graphics g) { // 如果表格值为"男"或"male",则绘制一个男性图标 if (cellValue.equalsIgnoreCase("男") || cellValue.equalsIgnoreCase("male")) { drawImage(g, new ImageIcon("icon/male.gif").getImage()); } // 如果表格值为"女"或"female",则绘制一个女性图标 if (cellValue.equalsIgnoreCase("女") || cellValue.equalsIgnoreCase("female")) { drawImage(g, new ImageIcon("icon/female.gif").getImage()); } } // 绘制图标的方法 private void drawImage(Graphics g, Image image) { g.drawImage(image, (getWidth() - ICON_WIDTH) / 2, (getHeight() - ICON_HEIGHT) / 2, null); } }
public class TableModelTest { JFrame jf = new JFrame("数据表管理工具"); private JScrollPane scrollPane; private ResultSetTableModel model; // 用于装载数据表的JComboBox private JComboBox<String> tableNames = new JComboBox<>(); private JTextArea changeMsg = new JTextArea(4, 80); private ResultSet rs; private Connection conn; private Statement stmt; public void init() { // 为JComboBox添加事件监听器,当用户选择某个数据表时,触发该方法 tableNames.addActionListener(event -> { try { // 如果装载JTable的JScrollPane不为空 if (scrollPane != null) { // 从主窗口中删除表格 jf.remove(scrollPane); } // 从JComboBox中取出用户试图管理的数据表的表名 String tableName = (String) tableNames.getSelectedItem(); // 如果结果集不为空,则关闭结果集 if (rs != null) { rs.close(); } String query = "select * from " + tableName; // 查询用户选择的数据表 rs = stmt.executeQuery(query); // 使用查询到的ResultSet创建TableModel对象 model = new ResultSetTableModel(rs); // 为TableModel添加监听器,监听用户的修改 model.addTableModelListener(evt -> { int row = evt.getFirstRow(); int column = evt.getColumn(); changeMsg.append("修改的列:" + column + ",修改的行:" + row + "修改后的值:" + model.getValueAt(row , column)); }); // 使用TableModel创建JTable,并将对应表格添加到窗口中 JTable table = new JTable(model); scrollPane = new JScrollPane(table); jf.add(scrollPane, BorderLayout.CENTER); jf.validate(); } catch (SQLException e) { e.printStackTrace(); } }); JPanel p = new JPanel(); p.add(tableNames); jf.add(p, BorderLayout.NORTH); jf.add(new JScrollPane(changeMsg), BorderLayout.SOUTH); try { // 获取数据库连接 conn = getConnection(); // 获取数据库的MetaData对象 DatabaseMetaData meta = conn.getMetaData(); // 创建Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE , ResultSet.CONCUR_UPDATABLE); // 查询当前数据库的全部数据表 ResultSet tables = meta.getTables(null, null, null , new String[] { "TABLE" }); // 将全部数据表添加到JComboBox中 while (tables.next()) { tableNames.addItem(tables.getString(3)); } tables.close(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } jf.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { try { if (conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }); jf.pack(); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jf.setVisible(true); } private static Connection getConnection() throws SQLException, IOException, ClassNotFoundException { // 通过加载conn.ini文件来获取数据库连接的详细信息 Properties props = new Properties(); FileInputStream in = new FileInputStream("conn.ini"); props.load(in); in.close(); String drivers = props.getProperty("jdbc.drivers"); String url = props.getProperty("jdbc.url"); String username = props.getProperty("jdbc.username"); String password = props.getProperty("jdbc.password"); // 加载数据库驱动 Class.forName(drivers); // 取得数据库连接 return DriverManager.getConnection(url, username, password); } public static void main(String[] args) { new TableModelTest().init(); } } // 扩展AbstractTableModel,用于将一个ResultSet包装成TableModel class ResultSetTableModel extends AbstractTableModel // ① { private ResultSet rs; private ResultSetMetaData rsmd; // 构造器,初始化rs和rsmd两个属性 public ResultSetTableModel(ResultSet aResultSet) { rs = aResultSet; try { rsmd = rs.getMetaData(); } catch (SQLException e) { e.printStackTrace(); } } // 重写getColumnName方法,用于为该TableModel设置列名 public String getColumnName(int c) { try { return rsmd.getColumnName(c + 1); } catch (SQLException e) { e.printStackTrace(); return ""; } } // 重写getColumnCount方法,用于设置该TableModel的列数 public int getColumnCount() { try { return rsmd.getColumnCount(); } catch (SQLException e) { e.printStackTrace(); return 0; } } // 重写getValueAt方法,用于设置该TableModel指定单元格的值 public Object getValueAt(int r, int c) { try { rs.absolute(r + 1); return rs.getObject(c + 1); } catch (SQLException e) { e.printStackTrace(); return null; } } // 重写getColumnCount方法,用于设置该TableModel的行数 public int getRowCount() { try { rs.last(); return rs.getRow(); } catch (SQLException e) { e.printStackTrace(); return 0; } } // 重写isCellEditable返回true,让每个单元格可编辑 public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } // 重写setValueAt()方法,当用户编辑单元格时,将会触发该方法 public void setValueAt(Object aValue, int row, int column) { try { // 结果集定位到对应的行数 rs.absolute(row + 1); // 修改单元格多对应的值 rs.updateObject(column + 1, aValue); // 提交修改 rs.updateRow(); // 触发单元格的修改事件 fireTableCellUpdated(row, column); } catch (SQLException evt) { evt.printStackTrace(); } } }
drop database if exists auction; create database auction; use auction; #用户表 create table auction_user( user_id int(11) auto_increment, username varchar(50) not null, userpass varchar(50) not null, email varchar(100) not null, primary key(user_id), unique(username) ); INSERT INTO auction_user (username,userpass,email) VALUES ('tomcat','tomcat','spring_test@163.com'); INSERT INTO auction_user (username,userpass,email) VALUES ('mysql','mysql','spring_test@163.com'); #物品种类表 create table kind( kind_id int(11) auto_increment, kind_name varchar(50) not null, kind_desc varchar(255) not null, primary key(kind_id) ); INSERT INTO kind (kind_name,kind_desc) VALUES ('电脑硬件','这里并不是很主流的产品,但价格绝对令你心动'); INSERT INTO kind (kind_name,kind_desc) VALUES ('房产','提供非常稀缺的房源'); #物品状态表 create table state( state_id int(11) auto_increment, state_name varchar(10), primary key(state_id) ); INSERT INTO state (state_name) VALUES ('拍卖中'); INSERT INTO state (state_name) VALUES ('拍卖成功'); INSERT INTO state (state_name) VALUES ('流拍'); #物品表 create table item( item_id int(11) auto_increment, item_name varchar(255) not null, item_remark varchar(255), item_desc varchar(255), kind_id int(11) not null, addtime date not null, endtime date not null, init_price double not null, max_price double not null, owner_id int(11) not null, winer_id int(11), state_id int(11) not null, primary key(item_id), FOREIGN KEY(kind_id) REFERENCES kind(kind_id), FOREIGN KEY(owner_id) REFERENCES auction_user(user_id), FOREIGN KEY(winer_id) REFERENCES auction_user(user_id), FOREIGN KEY(state_id) REFERENCES state(state_id) ); # 拍卖中的物品 INSERT INTO item ( item_name , item_remark , item_desc, kind_id, addtime , endtime, init_price, max_price, owner_id, winer_id, state_id) VALUES ( '主板', '老式主板', '老主板,还可以用', 1, ADDDATE(CURDATE(), -5), ADDDATE(CURDATE(), 30) , 230, 250, 1, null, 1); # 流派的物品 INSERT INTO item ( item_name , item_remark , item_desc, kind_id, addtime , endtime, init_price, max_price, owner_id, winer_id, state_id) VALUES ( '显卡', '老式显卡', '老显卡,还可以用', 1, ADDDATE(CURDATE(), -9), ADDDATE(CURDATE(), -2), 210, 210, 2, null, 3); # 被竞得的物品 INSERT INTO item ( item_name , item_remark , item_desc, kind_id, addtime , endtime, init_price, max_price, owner_id, winer_id, state_id) VALUES ( '老房子', '老式房子', '40年的老房子', 2, ADDDATE(CURDATE(), -9), ADDDATE(CURDATE(), -5), 21000, 25000, 2, 1, 2); #竞标历史表 create table bid( bid_id int(11) auto_increment, user_id int(11) not null, item_id int(11) not null, bid_price double not null, bid_date date not null, primary key(bid_id), unique(item_id , bid_price), FOREIGN KEY(user_id) REFERENCES auction_user(user_id), FOREIGN KEY(item_id) REFERENCES item(item_id) ); INSERT INTO bid ( user_id , item_id , bid_price, bid_date) VALUES ( 2, 1, 250, ADDDATE(CURDATE(), -2)); INSERT INTO bid ( user_id , item_id , bid_price, bid_date) VALUES ( 1, 3, 25000, ADDDATE(CURDATE(), -6));
public class JEditorPaneTest { JFrame mainWin = new JFrame("测试JEditorPane"); LinkedList<String> urls = new LinkedList<String>(); JEditorPane editorPane = new JEditorPane(); JTextField url = new JTextField(30); JCheckBox editable = new JCheckBox(); JButton backButton = new JButton("后退"); public void init() { // 默认设置不允许编辑 editorPane.setEditable(false); editorPane.addHyperlinkListener(event -> { if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { try { // 将用户浏览过的URL urls.push(event.getURL().toString()); // 在文本框内输入URL字符串 url.setText(event.getURL().toString()); // 让JEditorPane装载新的页面 editorPane.setPage(event.getURL()); } catch (IOException e) { editorPane.setText("出现异常: " + e); } } }); // 为可编辑的复选框添加事件监听器。 // 如果该复选框处于选中状态,则该编辑器可编辑 editable.addActionListener(event -> editorPane.setEditable(editable.isSelected())); // 加载URL指定页面的监听器 ActionListener listener = event -> { try { // 将用户浏览后的URL添加到URL栈中 urls.push(url.getText()); editorPane.setPage(url.getText()); } catch (IOException e) { editorPane.setText("页面: " + e); } }; JButton loadButton = new JButton("载入"); loadButton.addActionListener(listener); url.addActionListener(listener); // 为后退按钮添加监听器 backButton.addActionListener(event -> { // 如果还没有已经浏览过的URL if (urls.size() <= 1) return; try { // 取出、并获取最后一个URL String urlString = urls.pop(); url.setText(urlString); // 重新加载新的URL editorPane.setPage(urlString); } catch (IOException e) { editorPane.setText("出现异常: " + e); } }); mainWin.add(new JScrollPane(editorPane), BorderLayout.CENTER); JPanel panel = new JPanel(); panel.add(new JLabel("输入网址:")); panel.add(url); panel.add(loadButton); panel.add(backButton); panel.add(new JLabel("是否可编辑")); panel.add(editable); mainWin.add(panel, BorderLayout.NORTH); mainWin.pack(); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); } public static void main(String[] args) { new JEditorPaneTest().init(); } }
public class JFormattedTextFieldTest { private JFrame mainWin = new JFrame("测试格式化文本框"); private JButton okButton = new JButton("确定"); // 定义用于添加格式化文本框的容器 private JPanel mainPanel = new JPanel(); JFormattedTextField[] fields = new JFormattedTextField[6]; String[] behaviorLabels = new String[] { "COMMIT", "COMMIT_OR_REVERT", "PERSIST", "REVERT" }; int[] behaviors = new int[] { JFormattedTextField.COMMIT, JFormattedTextField.COMMIT_OR_REVERT, JFormattedTextField.PERSIST, JFormattedTextField.REVERT }; ButtonGroup bg = new ButtonGroup(); public void init() { // 添加按钮 JPanel buttonPanel = new JPanel(); buttonPanel.add(okButton); mainPanel.setLayout(new GridLayout(0, 3)); mainWin.add(mainPanel, BorderLayout.CENTER); // 使用NumberFormat的integerInstance创建一个JFormattedTextField fields[0] = new JFormattedTextField(NumberFormat .getIntegerInstance()); // 设置初始值 fields[0].setValue(100); addRow("整数格式文本框 :", fields[0]); // 使用NumberFormat的currencyInstance创建一个JFormattedTextField fields[1] = new JFormattedTextField(NumberFormat .getCurrencyInstance()); fields[1].setValue(100.0); addRow("货币格式文本框:", fields[1]); // 使用默认的日期格式创建一个JFormattedTextField对象 fields[2] = new JFormattedTextField(DateFormat.getDateInstance()); fields[2].setValue(new Date()); addRow("默认的日期格式器:", fields[2]); // 使用SHORT类型的日期格式创建一个JFormattedTextField对象, // 且要求采用严格日期格式 DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT); // 要求采用严格的日期格式语法 format.setLenient(false); fields[3] = new JFormattedTextField(format); fields[3].setValue(new Date()); addRow("SHORT类型的日期格式器(语法严格):", fields[3]); try { // 创建默认的DefaultFormatter对象 DefaultFormatter formatter = new DefaultFormatter(); // 关闭overwrite状态 formatter.setOverwriteMode(false); fields[4] = new JFormattedTextField(formatter); // 使用DefaultFormatter来格式化URL fields[4].setValue(new URL("http://www.crazyit.org")); addRow("URL:", fields[4]); } catch (MalformedURLException e) { e.printStackTrace(); } try { MaskFormatter formatter = new MaskFormatter("020-########"); // 设置占位符 formatter.setPlaceholderCharacter('□'); fields[5] = new JFormattedTextField(formatter); // 设置初始值 fields[5].setValue("020-28309378"); addRow("电话号码:", fields[5]); } catch (ParseException ex) { ex.printStackTrace(); } JPanel focusLostPanel = new JPanel(); // 采用循环方式加入失去焦点行为的单选按钮 for (int i = 0; i < behaviorLabels.length ; i++ ) { final int index = i; final JRadioButton radio = new JRadioButton(behaviorLabels[i]); // 默认选中第二个单选按钮 if (i == 1) { radio.setSelected(true); } focusLostPanel.add(radio); bg.add(radio); // 为所有单选按钮添加事件监听器 radio.addActionListener(e -> { // 如果当前该单选按钮处于选中状态, if (radio.isSelected()) { // 设置所有的格式化文本框的失去焦点的行为 for (int j = 0 ; j < fields.length ; j++) { fields[j].setFocusLostBehavior(behaviors[index]); } } }); } focusLostPanel.setBorder(new TitledBorder(new EtchedBorder(), "请选择焦点失去后的行为")); JPanel p = new JPanel(); p.setLayout(new BorderLayout()); p.add(focusLostPanel , BorderLayout.NORTH); p.add(buttonPanel , BorderLayout.SOUTH); mainWin.add(p , BorderLayout.SOUTH); mainWin.pack(); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); } // 定义添加一行格式化文本框的方法 private void addRow(String labelText, final JFormattedTextField field) { mainPanel.add(new JLabel(labelText)); mainPanel.add(field); final JLabel valueLabel = new JLabel(); mainPanel.add(valueLabel); // 为"确定"按钮添加事件监听器 // 当用户单击“确定”按钮时,文本框后 okButton.addActionListener(event -> { Object value = field.getValue(); // 输出格式化文本框的值 valueLabel.setText(value.toString()); }); } public static void main(String[] args) { new JFormattedTextFieldTest().init(); } }
public class JFormattedTextFieldTest2 { private JFrame mainWin = new JFrame("测试格式化文本框"); private JButton okButton = new JButton("确定"); // 定义用于添加格式化文本框的容器 private JPanel mainPanel = new JPanel(); public void init() { // 添加按钮 JPanel buttonPanel = new JPanel(); buttonPanel.add(okButton); mainPanel.setLayout(new GridLayout(0, 3)); mainWin.add(mainPanel, BorderLayout.CENTER); JFormattedTextField intField0 = new JFormattedTextField( new InternationalFormatter(NumberFormat.getIntegerInstance()) { protected DocumentFilter getDocumentFilter() { return new NumberFilter(); } }); intField0.setValue(100); addRow("只接受数字的文本框", intField0); JFormattedTextField intField1 = new JFormattedTextField( NumberFormat.getIntegerInstance()); intField1.setValue(100); // 添加输入校验器 intField1.setInputVerifier(new FormattedTextFieldVerifier()); addRow("带输入校验器的文本框", intField1); // 创建自定义格式器对象 IPAddressFormatter ipFormatter = new IPAddressFormatter(); ipFormatter.setOverwriteMode(false); // 以自定义格式器对象创建格式化文本框 JFormattedTextField ipField = new JFormattedTextField(ipFormatter); ipField.setValue(new byte[] { (byte) 192, (byte) 168, 4, 1 }); addRow("IP地址格式", ipField); mainWin.add(buttonPanel, BorderLayout.SOUTH); mainWin.pack(); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); } // 定义添加一行格式化文本框的方法 private void addRow(String labelText, final JFormattedTextField field) { mainPanel.add(new JLabel(labelText)); mainPanel.add(field); final JLabel valueLabel = new JLabel(); mainPanel.add(valueLabel); // 为"确定"按钮添加事件监听器 // 当用户单击“确定”按钮时,文本框后显示文本框内的值 okButton.addActionListener(event -> { Object value = field.getValue(); // 如果该值是数组,使用Arrays的toString方法输出数组 if (value.getClass().isArray()) { StringBuilder builder = new StringBuilder(); builder.append('{'); for (int i = 0; i < Array.getLength(value); i++) { if (i > 0) builder.append(','); builder.append(Array.get(value, i).toString()); } builder.append('}'); valueLabel.setText(builder.toString()); } else { // 输出格式化文本框的值 valueLabel.setText(value.toString()); } }); } public static void main(String[] args) { new JFormattedTextFieldTest2().init(); } } // 输入校验器 class FormattedTextFieldVerifier extends InputVerifier { // 当输入组件失去焦点时,该方法被触发 public boolean verify(JComponent component) { JFormattedTextField field = (JFormattedTextField) component; // 返回用户输入是否有效 return field.isEditValid(); } } // 数字过滤器 class NumberFilter extends DocumentFilter { public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException { StringBuilder builder = new StringBuilder(string); // 过滤用户输入的所有字符 filterInt(builder); super.insertString(fb, offset, builder.toString(), attr); } public void replace(FilterBypass fb, int offset, int length, String string, AttributeSet attr) throws BadLocationException { if (string != null) { StringBuilder builder = new StringBuilder(string); // 过滤用户替换的所有字符 filterInt(builder); string = builder.toString(); } super.replace(fb, offset, length, string, attr); } // 过滤整数字符,把所有非0~9的字符全部删除 private void filterInt(StringBuilder builder) { for (int i = builder.length() - 1; i >= 0; i--) { int cp = builder.codePointAt(i); if (cp > '9' || cp < '0') { builder.deleteCharAt(i); } } } } class IPAddressFormatter extends DefaultFormatter { public String valueToString(Object value) throws ParseException { if (!(value instanceof byte[])) { throw new ParseException("该IP地址的值只能是字节数组", 0); } byte[] a = (byte[]) value; if (a.length != 4) { throw new ParseException("IP地址必须是四个整数", 0); } StringBuilder builder = new StringBuilder(); for (int i = 0; i < 4; i++) { int b = a[i]; if (b < 0) b += 256; builder.append(String.valueOf(b)); if (i < 3) builder.append('.'); } return builder.toString(); } public Object stringToValue(String text) throws ParseException { // 将格式化文本框内的字符串以点号(.)分成四节。 String[] nums = text.split("\\."); if (nums.length != 4) { throw new ParseException("IP地址必须是四个整数", 0); } byte[] a = new byte[4]; for (int i = 0; i < 4; i++) { int b = 0; try { b = Integer.parseInt(nums[i]); } catch (NumberFormatException e) { throw new ParseException("IP地址必须是整数", 0); } if (b < 0 || b >= 256) { throw new ParseException("IP地址值只能在0~255之间", 0); } a[i] = (byte) b; } return a; } }
public class JTextPaneTest { JFrame mainWin = new JFrame("测试JTextPane"); JTextPane txt = new JTextPane(); StyledDocument doc = txt.getStyledDocument(); // 定义三个SimpleAttributeSet对象 SimpleAttributeSet android = new SimpleAttributeSet(); SimpleAttributeSet java = new SimpleAttributeSet(); SimpleAttributeSet javaee = new SimpleAttributeSet(); public void init() { // 为android属性集设置颜色、字体大小、字体和下划线 StyleConstants.setForeground(android, Color.RED); StyleConstants.setFontSize(android, 24); StyleConstants.setFontFamily(android, "Dialog"); StyleConstants.setUnderline(android, true); // 为java属性集设置颜色、字体大小、字体和粗体字 StyleConstants.setForeground(java, Color.BLUE); StyleConstants.setFontSize(java, 30); StyleConstants.setFontFamily(java, "Arial Black"); StyleConstants.setBold(java, true); // 为javaee属性集设置颜色、字体大小、斜体字 StyleConstants.setForeground(javaee, Color.GREEN); StyleConstants.setFontSize(javaee, 32); StyleConstants.setItalic(javaee, true); // 设置不允许编辑 txt.setEditable(false); txt.setText("疯狂Android讲义\n" + "疯狂Java讲义\n" + "轻量级Java EE企业应用实战\n"); // 分别为文档中三段文字设置不同的外观样式 doc.setCharacterAttributes(0, 12, android, true); doc.setCharacterAttributes(12, 12, java, true); doc.setCharacterAttributes(24, 30, javaee, true); mainWin.add(new JScrollPane(txt), BorderLayout.CENTER); // 获取屏幕尺寸 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); int inset = 100; // 设置主窗口的大小 mainWin.setBounds(inset, inset, screenSize.width - inset * 2, screenSize.height - inset * 2); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); } public static void main(String[] args) { new JTextPaneTest().init(); } }
public class MonitorText { JFrame mainWin = new JFrame("监听Document对象"); JTextArea target = new JTextArea(4, 35); JTextArea msg = new JTextArea(5, 35); JLabel label = new JLabel("文本域的修改信息"); Document doc = target.getDocument(); // 保存撤销操作的List对象 LinkedList<UndoableEdit> undoList = new LinkedList<>(); // 最多允许撤销多少次 final int UNDO_COUNT = 20; public void init() { msg.setEditable(false); // 添加DocumentListener doc.addDocumentListener(new DocumentListener() { // 当Document的属性或属性集发生了改变时触发该方法 public void changedUpdate(DocumentEvent e){} // 当向Document中插入文本时触发该方法 public void insertUpdate(DocumentEvent e) { int offset = e.getOffset(); int len = e.getLength(); // 取得插入事件的位置 msg.append("插入文本的长度:" + len + "\n"); msg.append("插入文本的起始位置:" + offset + "\n"); try { msg.append("插入文本内容:" + doc.getText(offset, len) + "\n"); } catch (BadLocationException evt) { evt.printStackTrace(); } } // 当从Document中删除文本时触发该方法 public void removeUpdate(DocumentEvent e) { int offset = e.getOffset(); int len = e.getLength(); // 取得插入事件的位置 msg.append("删除文本的长度:" + len + "\n"); msg.append("删除文本的起始位置:" + offset + "\n"); } }); // 添加可撤销操作的监听器 doc.addUndoableEditListener(e -> { // 每次发生可撤销操作都会触发该代码块 // ① UndoableEdit edit = e.getEdit(); if (edit.canUndo() && undoList.size() < UNDO_COUNT) { // 将撤销操作装入List内 undoList.add(edit); } // 已经达到了最大撤销次数 else if (edit.canUndo() && undoList.size() >= UNDO_COUNT) { // 弹出第一个撤销操作 undoList.pop(); // 将撤销操作装入List内 undoList.add(edit); } }); // 为Ctrl+Z添加监听器 target.addKeyListener(new KeyAdapter() { public void keyTyped(KeyEvent e) // ② { System.out.println(e.getKeyChar() + 0); // 如果按键是Ctrl + Z或Ctrl + z if (e.getKeyChar() == 26) { if (undoList.size() > 0) { // 移出最后一个可撤销操作,并取消该操作 undoList.removeLast().undo(); } } } }); Box box = new Box(BoxLayout.Y_AXIS); box.add(new JScrollPane(target)); JPanel panel = new JPanel(); panel.add(label); box.add(panel); box.add(new JScrollPane(msg)); mainWin.add(box); mainWin.pack(); mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainWin.setVisible(true); } public static void main(String[] args) throws Exception { new MonitorText().init(); } }
public class MyTextPane extends JTextPane { protected StyledDocument doc; protected SyntaxFormatter formatter = new SyntaxFormatter("my.stx"); // 定义该文档的普通文本的外观属性 private SimpleAttributeSet normalAttr = formatter.getNormalAttributeSet(); private SimpleAttributeSet quotAttr = new SimpleAttributeSet(); // 保存文档改变的开始位置 private int docChangeStart = 0; // 保存文档改变的长度 private int docChangeLength = 0; public MyTextPane() { StyleConstants.setForeground(quotAttr, new Color(255, 0, 255)); StyleConstants.setFontSize(quotAttr, 16); this.doc = super.getStyledDocument(); // 设置该文档的页边距 this.setMargin(new Insets(3, 40, 0, 0)); // 添加按键监听器,当按键松开时进行语法分析 this.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent ke) { syntaxParse(); } }); // 添加文档监听器 doc.addDocumentListener(new DocumentListener() { // 当Document的属性或属性集发生了改变时触发该方法 public void changedUpdate(DocumentEvent e) { } // 当向Document中插入文本时触发该方法 public void insertUpdate(DocumentEvent e) { docChangeStart = e.getOffset(); docChangeLength = e.getLength(); } // 当从Document中删除文本时触发该方法 public void removeUpdate(DocumentEvent e) { } }); } public void syntaxParse() { try { // 获取文档的根元素,即文档内的全部内容 Element root = doc.getDefaultRootElement(); // 获取文档中光标插入符的位置 int cursorPos = this.getCaretPosition(); int line = root.getElementIndex(cursorPos); // 获取光标所在位置的行 Element para = root.getElement(line); // 定义光标所在行的行头在文档中位置 int start = para.getStartOffset(); // 让start等于start与docChangeStart中较小值。 start = start > docChangeStart ? docChangeStart : start; // 定义被修改部分的长度 int length = para.getEndOffset() - start; length = length < docChangeLength ? docChangeLength + 1 : length; // 取出所有可能被修改的字符串 String s = doc.getText(start, length); // 以空格、点号等作为分隔符 String[] tokens = s.split("\\s+|\\.|\\(|\\)|\\{|\\}|\\[|\\]"); // 定义当前分析单词的在s字符串中的开始位置 int curStart = 0; // 定义单词是否处于引号以内 boolean isQuot = false; for (String token : tokens) { // 找出当前分析单词在s字符串中的位置 int tokenPos = s.indexOf(token, curStart); if (isQuot && (token.endsWith("\"") || token.endsWith("\'"))) { doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false); isQuot = false; } else if (isQuot && !(token.endsWith("\"") || token.endsWith("\'"))) { doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false); } else if ((token.startsWith("\"") || token.startsWith("\'")) && (token.endsWith("\"") || token.endsWith("\'"))) { doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false); } else if ((token.startsWith("\"") || token.startsWith("\'")) && !(token.endsWith("\"") || token.endsWith("\'"))) { doc.setCharacterAttributes(start + tokenPos, token.length(), quotAttr, false); isQuot = true; } else { // 使用格式器对当前单词设置颜色 formatter.setHighLight(doc, token, start + tokenPos, token.length()); } // 开始分析下一个单词 curStart = tokenPos + token.length(); } } catch (Exception ex) { ex.printStackTrace(); } } // 重画该组件,设置行号 public void paint(Graphics g) { super.paint(g); Element root = doc.getDefaultRootElement(); // 获得行号 int line = root.getElementIndex(doc.getLength()); // 设置颜色 g.setColor(new Color(230, 230, 230)); // 绘制显示行数的矩形框 g.fillRect(0, 0, this.getMargin().left - 10, getSize().height); // 设置行号的颜色 g.setColor(new Color(40, 40, 40)); // 每行绘制一个行号 for (int count = 0, j = 1; count <= line; count++, j++) { g.drawString(String.valueOf(j), 3, (int) ((count + 1) * 1.535 * StyleConstants .getFontSize(normalAttr))); } } public static void main(String[] args) { JFrame frame = new JFrame("文本编辑器"); // 使用MyTextPane frame.getContentPane().add(new JScrollPane(new MyTextPane())); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final int inset = 50; Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); frame.setBounds(inset, inset, screenSize.width - inset * 2, screenSize.height - inset * 2); frame.setVisible(true); } } // 定义语法格式器 class SyntaxFormatter { // 以一个Map保存关键字和颜色的对应关系 private Map<SimpleAttributeSet, ArrayList<String>> attMap = new HashMap<>(); // 定义文档的正常文本的外观属性 SimpleAttributeSet normalAttr = new SimpleAttributeSet(); public SyntaxFormatter(String syntaxFile) { // 设置正常文本的颜色、大小 StyleConstants.setForeground(normalAttr, Color.BLACK); StyleConstants.setFontSize(normalAttr, 16); // 创建一个Scanner对象,负责根据语法文件加载颜色信息 Scanner scaner = null; try { scaner = new Scanner(new File(syntaxFile)); } catch (FileNotFoundException e) { throw new RuntimeException("丢失语法文件:" + e.getMessage()); } int color = -1; ArrayList<String> keywords = new ArrayList<>(); // 不断读取语法文件的内容行 while (scaner.hasNextLine()) { String line = scaner.nextLine(); // 如果当前行以#开头 if (line.startsWith("#")) { if (keywords.size() > 0 && color > -1) { // 取出当前行的颜色值,并封装成SimpleAttributeSet对象 SimpleAttributeSet att = new SimpleAttributeSet(); StyleConstants.setForeground(att, new Color(color)); StyleConstants.setFontSize(att, 16); // 将当前颜色和关键字List对应起来 attMap.put(att, keywords); } // 重新创建新的关键字List,为下一个语法格式准备 keywords = new ArrayList<>(); color = Integer.parseInt(line.substring(1), 16); } else { // 对于普通行,每行内容添加到关键字List里 if (line.trim().length() > 0) { keywords.add(line.trim()); } } } // 把所有关键字和颜色对应起来 if (keywords.size() > 0 && color > -1) { SimpleAttributeSet att = new SimpleAttributeSet(); StyleConstants.setForeground(att, new Color(color)); StyleConstants.setFontSize(att, 16); attMap.put(att, keywords); } } // 返回该格式器里正常文本的外观属性 public SimpleAttributeSet getNormalAttributeSet() { return normalAttr; } // 设置语法高亮 public void setHighLight(StyledDocument doc, String token, int start, int length) { // 保存需要对当前单词对应的外观属性 SimpleAttributeSet currentAttributeSet = null; outer: for (SimpleAttributeSet att : attMap.keySet()) { // 取出当前颜色对应的所有关键字 ArrayList<String> keywords = attMap.get(att); // 遍历所有关键字 for (String keyword : keywords) { // 如果该关键字与当前单词相同 if (keyword.equals(token)) { // 跳出循环,并设置当前单词对应的外观属性 currentAttributeSet = att; break outer; } } } // 如果当前单词对应的外观属性不为空 if (currentAttributeSet != null) { // 设置当前单词的颜色 doc.setCharacterAttributes(start, length, currentAttributeSet, false); } // 否则使用普通外观来设置该单词 else { doc.setCharacterAttributes(start, length, normalAttr, false); } } }
#FF0000 System Class String Integer Object #0000FF abstract assert boolean break byte case catch char class const continue default do double else enum extends false final finally float for goto if import implements int interface instanceof long native new null package private protected public return short static strictfp super switch synchronized this throw throws transient try true void volatile while
|



































浙公网安备 33010602011771号