本教程是针对JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅Java语言变化以了解Java SE 9及后续版本中更新的语言功能的摘要。
请参阅JDK发行说明以获取有关所有JDK版本的新功能、增强功能和已删除或弃用选项的信息。
接下来,我们将在框架中添加一个自定义绘图表面。为此,我们将创建一个javax.swing.JPanel
的子类(一个通用的轻量级容器),该子类将提供绘制自定义绘画的代码。
javax.swing.JPanel子类
点击“启动”按钮使用Java™ Web Start(下载JDK 7或更高版本)运行SwingPaintDemo2。或者,要自己编译和运行示例,请参考示例索引。
package painting; import javax.swing.SwingUtilities; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.BorderFactory; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; public class SwingPaintDemo2 { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } private static void createAndShowGUI() { System.out.println("在EDT上创建GUI? "+ SwingUtilities.isEventDispatchThread()); JFrame f = new JFrame("Swing绘图演示"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new MyPanel()); f.pack(); f.setVisible(true); } } class MyPanel extends JPanel { public MyPanel() { setBorder(BorderFactory.createLineBorder(Color.black)); } public Dimension getPreferredSize() { return new Dimension(250,200); } public void paintComponent(Graphics g) { super.paintComponent(g); // 绘制文本 g.drawString("这是我的自定义面板!",10,20); } }
你会注意到的第一个变化是我们现在导入了许多额外的类,比如JPanel
、Color
和Graphics
。由于一些旧的AWT类仍然在现代的Swing应用程序中使用,所以在一些导入语句中看到java.awt
包是正常的。我们还定义了一个名为MyPanel
的自定义JPanel
子类,它包含了大部分新代码。
MyPanel
类定义了一个构造函数,该构造函数在其边缘周围设置了一个黑色边框。这是一个细微的细节,可能一开始很难看到(如果是这样,只需注释掉setBorder
的调用,然后重新编译即可)。MyPanel
还覆盖了getPreferredSize
方法,该方法返回面板的期望宽度和高度(在本例中,宽度为250,高度为200)。因此,SwingPaintDemo
类不再需要指定帧的像素大小。它只需将面板添加到帧中,然后调用pack
方法即可。
paintComponent
方法是所有自定义绘图发生的地方。这个方法由javax.swing.JComponent
定义,然后由你的子类覆盖以提供它们的自定义行为。它的唯一参数是一个java.awt.Graphics
对象,它提供了一些绘制2D形状和获取有关应用程序图形环境信息的方法。在大多数情况下,实际接收到该方法的对象将是java.awt.Graphics2D
的一个实例(Graphics
的子类),它提供了对复杂的2D图形渲染的支持。
大多数标准的Swing组件通过单独的"UI Delegate"对象实现其外观和感觉。调用super.paintComponent(g)
将图形上下文传递给组件的UI委托,后者会绘制面板的背景。有关此过程的更详细信息,请参阅前述SDN文章中的"绘制和UI Delegate"部分。
练习:
paintComponent
方法。