目标:利用Graphics类的方法绘制字符串、指向、矩形、椭圆、弧形、多边形和图像以及如何开发重用的GUI组件(复用类)
1.图形坐标系:
两句话:每个GUI组件都有自己的坐标系;原点(0,0)在组件的左上角
2.Graphics类
package test;
import javax.swing.*;
import java.awt.Graphics;
public class Test extends JFrame {
public Test() {
add(new NewPanel());
}
public static void main(String[] args) {
Test frame = new Test();
frame.setTitle("Test");
frame.setSize(200, 100);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class NewPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawLine(0, 0, 50, 50);
g.drawString("Banner", 0, 40);
}
}
3.FigurePanel类
主要是用于绘制字符串、直线、矩形和椭圆等(绘制、填充+直角、圆角、三维)
第一个类:FigurePanel类
package test;
import java.awt.*;
import javax.swing.JPanel;
public class FigurePanel extends JPanel {
// Define constants
public static final int LINE = 1;
public static final int RECTANGLE = 2;
public static final int ROUND_RECTANGLE = 3;
public static final int OVAL = 4;
private int type = 1;
private boolean filled;
/** Construct a default FigurePanel */
public FigurePanel() {
}
/** Construct a FigurePanel with the specified type */
public FigurePanel(int type) {
this.type = type;
}
/** Construct a FigurePanel with the specified type and filled */
public FigurePanel(int type, boolean filled) {
this.type = type;
this.filled = filled;
}
/** Draw a figure on the panel */
public void paintComponent(Graphics g) {
super.paintComponent(g);
// Get the appropriate size for the figure
int width = getWidth();
int height = getHeight();
switch (type) {
case LINE: // Display two cross lines
g.setColor(Color.BLACK);
g.drawLine(10, 10, width - 10, height - 10);
g.drawLine(width - 10, 10, 10, height - 10);
break;
case RECTANGLE: // Display a rectangle
g.setColor(Color.BLUE);
if (filled)
g.fillRect((int)(0.1 * width), (int)(0.1 * height),
(int)(0.8 * width), (int)(0.8 * height));
else
g.drawRect((int)(0.1 * width), (int)(0.1 * height),
(int)(0.8 * width), (int)(0.8 * height));
break;
case ROUND_RECTANGLE: // Display a round-cornered rectangle
g.setColor(Color.RED);
if (filled)
g.fillRoundRect((int)(0.1 * width), (int)(0.1 * height),
(int)(0.8 * width), (int)(0.8 * height), 20, 20);
else
g.drawRoundRect((int)(0.1 * width), (int)(0.1 * height),
(int)(0.8 * width), (int)(0.8 * height), 20, 20);
break;
case OVAL: // Display an oval
g.setColor(Color.BLACK);
if (filled)
g.fillOval((int)(0.1 * width), (int)(0.1 * height),
(int)(0.8 * width), (int)(0.8 * height));
else
g.drawOval((int)(0.1 * width), (int)(0.1 * height),
(int)(0.8 * width), (int)(0.8 * height));
}
}
/** Set a new figure type */
public void setType(int type) {
this.type = type;
repaint();
}
/** Return figure type */
public int getType() {
return type;
}
/** Set a new filled property */
public void setFilled(boolean filled) {
this.filled = filled;
repaint();
}
/** Check if the figure is filled */
public boolean isFilled() {
return filled;
}
/** Specify preferred size */
public Dimension getPreferredSize() {
return new Dimension(80, 80);
}
}
第二个类:实现类
package test;
import java.awt.*;
import javax.swing.*;
import test.FigurePanel;
public class TestFigurePanel extends JFrame {
public TestFigurePanel() {
setLayout(new GridLayout(2, 3, 5, 5));
add(new FigurePanel(FigurePanel.LINE));
add(new FigurePanel(FigurePanel.RECTANGLE));
add(new FigurePanel(FigurePanel.ROUND_RECTANGLE));
add(new FigurePanel(FigurePanel.OVAL));
add(new FigurePanel(FigurePanel.RECTANGLE, true));
add(new FigurePanel(FigurePanel.ROUND_RECTANGLE, true));
}
public static void main(String[] args) {
TestFigurePanel frame = new TestFigurePanel();
frame.setSize(400, 200);
frame.setTitle("TestFigurePanel");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
4.绘制弧形
package test;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
public class DrawArcs extends JFrame {
public DrawArcs() {
add(new ArcsPanel());
}
/** Main method */
public static void main(String[] args) {
DrawArcs frame = new DrawArcs();
frame.setTitle("DrawArcs");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(250, 300);
frame.setVisible(true);
}
}
// The class for drawing arcs on a panel
class ArcsPanel extends JPanel {
// Draw four blazes of a fan
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.4);
int x = xCenter - radius;
int y = yCenter - radius;
g.fillArc(x, y, 2 * radius, 2 * radius, 0, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 90, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 180, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 270, 30);
}
}
5.绘制多边形和折线段
注意点:为了绘制一个多边形,首先需要使用多边形类Polygon创建一个Ploygan对象
package test;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Polygon;
public class DrawPolygon extends JFrame {
public DrawPolygon() {
add(new PolygonsPanel());
}
/** Main method */
public static void main(String[] args) {
DrawPolygon frame = new DrawPolygon();
frame.setTitle("xiaoming");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 250);
frame.setVisible(true);
}
}
// Draw a polygon in the panel
/*相对于之前也就需要注意点:
* 第一:首先创建一个面对象,不然无法向里面添加点的坐标信息
* */
class PolygonsPanel extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.4);
// Create a Polygon object
Polygon polygon = new Polygon();
// Add points to the polygon
polygon.addPoint(xCenter + radius, yCenter);
polygon.addPoint((int)(xCenter + radius *
Math.cos(2 * Math.PI / 6)), (int)(yCenter - radius *
Math.sin(2 * Math.PI / 6)));
polygon.addPoint((int)(xCenter + radius *
Math.cos(2 * 2 * Math.PI / 6)), (int)(yCenter - radius *
Math.sin(2 * 2 * Math.PI / 6)));
polygon.addPoint((int)(xCenter + radius *
Math.cos(3 * 2 * Math.PI / 6)), (int)(yCenter - radius *
Math.sin(3 * 2 * Math.PI / 6)));
polygon.addPoint((int)(xCenter + radius *
Math.cos(4 * 2 * Math.PI / 6)), (int)(yCenter - radius *
Math.sin(4 * 2 * Math.PI / 6)));
polygon.addPoint((int)(xCenter + radius *
Math.cos(5 * 2 * Math.PI / 6)), (int)(yCenter - radius *
Math.sin(5 * 2 * Math.PI / 6)));
// Draw the polygon
g.drawPolygon(polygon);
}
}
6.使用FontMetrics类居中显示字符串
package test;
import javax.swing.*;
import java.awt.*;
public class DrawPolygon extends JFrame {
public DrawPolygon() {
CenterMessage messagePanel = new CenterMessage();
add(messagePanel);
messagePanel.setBackground(Color.WHITE);
messagePanel.setFont(new Font("Californian FB", Font.BOLD, 30));
}
/** Main method */
public static void main(String[] args) {
DrawPolygon frame = new DrawPolygon();
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 150);
frame.setVisible(true);
}
}
class CenterMessage extends JPanel {
/** Paint the message */
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Get font metrics for the current font
FontMetrics fm = g.getFontMetrics();
// Find the center location to display
int stringWidth = fm.stringWidth("Welcome to Java");
int stringAscent = fm.getAscent();
// Get the position of the leftmost character in the baseline
int xCoordinate = getWidth() / 2 - stringWidth / 2;
int yCoordinate = getHeight() / 2 + stringAscent / 2;
g.drawString("Welcome to Java", xCoordinate, yCoordinate);
}
}
7.MessgePanel类
第一个类:MessagePanel类
package test;
import java.awt.FontMetrics;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MessagePanel extends JPanel {
/** The message to be displayed */
private String message = "Welcome to Java";
/** The x coordinate where the message is displayed */
private int xCoordinate = 20;
/** The y coordinate where the message is displayed */
private int yCoordinate = 20;
/** Indicate whether the message is displayed in the center */
private boolean centered;
/** The interval for moving the message horizontally and vertically */
private int interval = 10;
/** Construct with default properties */
public MessagePanel() {
}
/** Construct a message panel with a specified message */
public MessagePanel(String message) {
this.message = message;
}
/** Return message */
public String getMessage() {
return message;
}
/** Set a new message */
public void setMessage(String message) {
this.message = message;
repaint();
}
/** Return xCoordinator */
public int getXCoordinate() {
return xCoordinate;
}
/** Set a new xCoordinator */
public void setXCoordinate(int x) {
this.xCoordinate = x;
repaint();
}
/** Return yCoordinator */
public int getYCoordinate() {
return yCoordinate;
}
/** Set a new yCoordinator */
public void setYCoordinate(int y) {
this.yCoordinate = y;
repaint();
}
/** Return centered */
public boolean isCentered() {
return centered;
}
/** Set a new centered */
public void setCentered(boolean centered) {
this.centered = centered;
repaint();
}
/** Return interval */
public int getInterval() {
return interval;
}
/** Set a new interval */
public void setInterval(int interval) {
this.interval = interval;
repaint();
}
/** Paint the message */
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (centered) {
// Get font metrics for the current font
FontMetrics fm = g.getFontMetrics();
// Find the center location to display
int stringWidth = fm.stringWidth(message);
int stringAscent = fm.getAscent();
// Get the position of the leftmost character in the baseline
xCoordinate = getWidth() / 2 - stringWidth / 2;
yCoordinate = getHeight() / 2 + stringAscent / 2;
}
g.drawString(message, xCoordinate, yCoordinate);
}
/** Move the message left */
public void moveLeft() {
xCoordinate -= interval;
repaint();
}
/** Move the message right */
public void moveRight() {
xCoordinate += interval;
repaint();
}
/** Move the message up */
public void moveUp() {
yCoordinate -= interval;
repaint();
}
/** Move the message down */
public void moveDown() {
yCoordinate += interval;
repaint();
}
/** Override get method for preferredSize */
/* setSize是设定的固定大小,而setPreferredSize仅仅是设置最好的大小,
* 这个不一定与实际显示出来的控件大小一致(根据界面整体的变化而变化)*/
/* getPreferedSize方法是获取组的首选大小,因为布局管理器会根据组件自动调整框架窗口的大小,
可以通过这个方法来获取自动调整后的组件大小, 没有自动调用只是能获取大小而已
*/
public Dimension getPreferredSize() {
return new Dimension(200, 60);
}
}
第二个类:实现类
package test;
import java.awt.*;
import javax.swing.*;
import test.MessagePanel;
public class TestMessagePanel extends JFrame{
public TestMessagePanel(){
MessagePanel messagePanel1 = new MessagePanel("welcome to java");
MessagePanel messagePanel2 = new MessagePanel("welcome to java");
MessagePanel messagePanel3 = new MessagePanel("welcome to java");
MessagePanel messagePanel4 = new MessagePanel("welcome to java");
messagePanel1.setFont(new Font("SanSerif", Font.ITALIC, 20));
messagePanel2.setFont(new Font("SanSerif", Font.ITALIC, 20));
messagePanel3.setFont(new Font("SanSerif", Font.ITALIC, 20));
messagePanel4.setFont(new Font("SanSerif", Font.ITALIC, 20));
messagePanel1.setBackground(Color.red);
messagePanel2.setBackground(Color.cyan);
messagePanel3.setBackground(Color.green);
messagePanel4.setBackground(Color.white);
messagePanel1.setCentered(true);
setLayout(new GridLayout(2, 2));
add(messagePanel1);
add(messagePanel2);
add(messagePanel3);
add(messagePanel4);
}
public static void main(String[] args){
TestMessagePanel frame = new TestMessagePanel();
frame.setSize(300, 200);
frame.setTitle("xiaoming");
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
8.实例学习:StiilClock类(显示静态的时钟)
第一个类:MessagePanel类
package test;
import java.awt.*;
import javax.swing.*;
import java.util.*;
//涉及到图形的field,在使用set方法的时候都需要repaint();
/*在涉及java绘制图形,写重复利用的类一般步骤:
* 第一步:设置私有变量
* 第二步:构造出事函数
* 第三步:为私有变量设置getter和setter的方法,注意在这是setter方法的时候要重新repaint方法
* 第四步:重新绘制图形,自己就是显示自己想要展示的图形
* 第五步: public Dimension getPreferredSize() 设置大小
* */
public class StillClock extends JPanel {
private int hour;
private int minute;
private int second;
/** Construct a default clock with the current time*/
public StillClock() {
setCurrentTime();
}
/** Construct a clock with specified hour, minute, and second */
public StillClock(int hour, int minute, int second) {
this.hour = hour;
this.minute = minute;
this.second = second;
}
/** Return hour */
public int getHour() {
return hour;
}
/** Set a new hour */
public void setHour(int hour) {
this.hour = hour;
repaint();
}
/** Return minute */
public int getMinute() {
return minute;
}
/** Set a new minute */
public void setMinute(int minute) {
this.minute = minute;
repaint();
}
/** Return second */
public int getSecond() {
return second;
}
/** Set a new second */
public void setSecond(int second) {
this.second = second;
repaint();
}
/** Draw the clock */
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Initialize clock parameters
int clockRadius =
(int)(Math.min(getWidth(), getHeight()) * 0.8 * 0.5);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
// Draw circle
g.setColor(Color.black);
g.drawOval(xCenter - clockRadius, yCenter - clockRadius,
2 * clockRadius, 2 * clockRadius);
g.drawString("12", xCenter - 5, yCenter - clockRadius + 12);
g.drawString("9", xCenter - clockRadius + 3, yCenter + 5);
g.drawString("3", xCenter + clockRadius - 10, yCenter + 3);
g.drawString("6", xCenter - 3, yCenter + clockRadius - 3);
// Draw second hand
int sLength = (int)(clockRadius * 0.8);
int xSecond = (int)(xCenter + sLength *
Math.sin(second * (2 * Math.PI / 60)));
int ySecond = (int)(yCenter - sLength *
Math.cos(second * (2 * Math.PI / 60)));
g.setColor(Color.red);
g.drawLine(xCenter, yCenter, xSecond, ySecond);
// Draw minute hand
int mLength = (int)(clockRadius * 0.65);
int xMinute = (int)(xCenter + mLength *
Math.sin(minute * (2 * Math.PI / 60)));
int yMinute = (int)(yCenter - mLength *
Math.cos(minute * (2 * Math.PI / 60)));
g.setColor(Color.blue);
g.drawLine(xCenter, yCenter, xMinute, yMinute);
// Draw hour hand
int hLength = (int)(clockRadius * 0.5);
int xHour = (int)(xCenter + hLength *
Math.sin((hour % 12 + minute / 60.0) * (2 * Math.PI / 12)));
int yHour = (int)(yCenter - hLength *
Math.cos((hour % 12 + minute / 60.0) * (2 * Math.PI / 12)));
g.setColor(Color.green);
g.drawLine(xCenter, yCenter, xHour, yHour);
}
public void setCurrentTime() {
// Construct a calendar for the current date and time
Calendar calendar = new GregorianCalendar();
// Set current hour, minute and second
this.hour = calendar.get(Calendar.HOUR_OF_DAY);
this.minute = calendar.get(Calendar.MINUTE);
this.second = calendar.get(Calendar.SECOND);
}
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
第三个:实现类
package test;
import java.awt.*;
import javax.swing.*;
//MessagePanel 需要自己定义重写;StillClock也是如此;--------java的主要特征之一类的复用
import test.MessagePanel;
import test.StillClock;
/*一般程序可以分为三个部分
* 主函数:负责框架的显示、关闭等
* Jframe的继承子类:负责初始化画图的函数
* Jpanel的继承子类:负责利用protected void paintComponent(Graphics g)展示需要画的图
* */
public class Test extends JFrame {
public Test() {
// Create an analog clock for the current time
StillClock clock = new StillClock();
// Display hour, minute, and seconds in the message panel
MessagePanel messagePanel = new MessagePanel(clock.getHour() +
":" + clock.getMinute() + ":" + clock.getSecond());
// 设置显示时间的字体居中显示、颜色、字体本身相关属性
messagePanel.setCentered(true);
messagePanel.setForeground(Color.black);
messagePanel.setFont(new Font("Courie", Font.BOLD, 16));
// Add the clock and message panel to the frame
// Jframe默认属性是BorderLayout.CENTER
add(clock);
add(messagePanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
Test frame = new Test();
frame.setTitle("Test");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 350);
frame.setVisible(true);
}
}
9.图像图标
package test;
import javax.swing.*;
import java.awt.*;
public class DisplayImage extends JFrame {
private ImageIcon usIcon = new ImageIcon("001.jpg");
private ImageIcon myIcon = new ImageIcon("002.jpg");
private ImageIcon frIcon = new ImageIcon("003.jpg");
private ImageIcon ukIcon = new ImageIcon("004.jpg");
public DisplayImage() {
setLayout(new GridLayout(1, 4, 5, 5));
add(new JButton(usIcon));
add(new JLabel(myIcon));
add(new JButton(frIcon));
add(new JLabel(ukIcon));
}
/** Main method */
public static void main(String[] args) {
DisplayImage frame = new DisplayImage();
frame.setTitle("DisplayImage");
frame.setSize(500, 125);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
10.显示图像
package test;
import java.awt.*;
import javax.swing.*;
public class DisplayImage extends JFrame {
public DisplayImage() {
add(new ImagePanel());
}
public static void main(String[] args) {
JFrame frame = new DisplayImage();
frame.setTitle("DisplayImage");
frame.setSize(300, 300);
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class ImagePanel extends JPanel {
private ImageIcon imageIcon = new ImageIcon("001.jpg");
private Image image = imageIcon.getImage();
/** Draw image on the panel */
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null)
g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
}
}
11.ImageViewer类
第一个类:ImageViewer
package test;
import java.awt.*;
import javax.swing.*;
public class ImageViewer extends JPanel {
/** Hold value of property image. */
private java.awt.Image image;
/** Hold value of property stretched. */
private boolean stretched = true;
/** Hold value of property xCoordinate. */
private int xCoordinate;
/** Hold value of property yCoordinate. */
private int yCoordinate;
/** Construct an empty image viewer */
public ImageViewer() {
}
/** Construct an image viewer for a specified Image object */
public ImageViewer(Image image) {
this.image = image;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null)
if (isStretched())
g.drawImage(image, xCoordinate, yCoordinate,
getSize().width, getSize().height, this);
else
g.drawImage(image, xCoordinate, yCoordinate, this);
}
/** Return value of property image */
public java.awt.Image getImage() {
return image;
}
/** Set a new value for property image */
public void setImage(java.awt.Image image) {
this.image = image;
repaint();
}
/** Return value of property stretched */
public boolean isStretched() {
return stretched;
}
/** Set a new value for property stretched */
public void setStretched(boolean stretched) {
this.stretched = stretched;
repaint();
}
/** Return value of property xCoordinate */
public int getXCoordinate() {
return xCoordinate;
}
/** Set a new value for property xCoordinate */
public void setXCoordinate(int xCoordinate) {
this.xCoordinate = xCoordinate;
repaint();
}
/** Return value of property yCoordinate */
public int getYCoordinate() {
return yCoordinate;
}
/** Set a new value for property yCoordinate */
public void setYCoordinate(int yCoordinate) {
this.yCoordinate = yCoordinate;
repaint();
}
}
第二个类:
package test;
import javax.swing.*;
import java.awt.*;
/*注意事项:
* 第一点: Image image1 = new ImageIcon("001.jpg").getImage();直接在后面跟上函数,没有像以前的分为两步
* 第二点: add(new ImageViewer(image1));添加多张照片的时候使用ImageViewer
* 区别于一张时候的显示图像
* 第三点:在ImageViewer可重用的类中没有dimension属性
* */
public class SixFlags extends JFrame {
public SixFlags() {
Image image1 = new ImageIcon("001.jpg").getImage();
Image image2 = new ImageIcon("002.jpg").getImage();
Image image3 = new ImageIcon("003.jpg").getImage();
Image image4 = new ImageIcon("004.jpg").getImage();
Image image5 = new ImageIcon("005.jpg").getImage();
Image image6 = new ImageIcon("006.jpg").getImage();
setLayout(new GridLayout(2, 0, 5, 5));
add(new ImageViewer(image1));
add(new ImageViewer(image2));
add(new ImageViewer(image3));
add(new ImageViewer(image4));
add(new ImageViewer(image5));
add(new ImageViewer(image6));
}
public static void main(String[] args) {
SixFlags frame = new SixFlags();
frame.setTitle("SixFlags");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 320);
frame.setVisible(true);
}
}