案例代码:
import java.awt.*;
import javax.swing.*;
public class Test extends JFrame {
public static void main(String[] args){
Test sl = new Test();
sl.update();
}
Test(){
super("Sample");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(600,600);
setVisible(true);
}
public void update(){
repaint();
}
public void paint(Graphics g) {
g.setColor(Color.black);
//有角矩形,起始点(10,30),宽80,高50
g.drawRect(10,30,80,50);
//圆角矩形,起始点(110,30),宽80,高50,角(a=20,b=10)
g.drawRoundRect(110,30,80,50,20,10);
//椭圆,圆心(110,90)、a=80,b=50
g.drawOval(110,90,80,50);
//一条弧,圆心(219,30)、a=80,b=50 角度在0-90之间
g.drawArc(210,30,80,50,0,90);
//扇面,圆心(219,90)、a=80,b=50 角度在0-90之间
g.fillArc(210,90,80,50,0,90);
}
}
同样的,在俄罗斯方块的代码中,我们也看到了一个public void paint(Graphics g)
函数,似乎这个函数没有被任何东西调用,并且还有一个相关联的repeat
方法,代码见下面的:
public void paint(Graphics g){
g.drawImage(background, 0, 0, null);//使用this 作为观察者
g.translate(15, 15);//平移绘图坐标系
paintTetromino(g);//绘制正在下落的方块
paintWall(g);//画墙
paintNextOne(g);
paintScore(g);
}
/**
* Invoked by Swing to draw components
* Applications should not invoke paint
directly,
* but should instead use the repaint
method to
* schedule the component for redrawing.
*
* This method actually delegates the work of painting to three
* protected methods: paintComponent
,
* paintBorder
,
* and paintChildren
. They're called in the order
* listed to ensure that children appear on top of component itself.
* Generally speaking, the component and its children should not
* paint in the insets area allocated to the border. Subclasses can
* just override this method, as always. A subclass that just
* wants to specialize the UI (look and feel) delegate's
* paint
method should just override
* paintComponent
.
*
* @param g the Graphics
context in which to paint
* @see #paintComponent
* @see #paintBorder
* @see #paintChildren
* @see #getComponentGraphics
* @see #repaint
*/
---------------------
原文:https://blog.csdn.net/tanjun592/article/details/54926041
这个方法是被swing调用来画组件的,应用不应该直接调用paint,而应该调用repaint。paint这个方法实际上代表了三个protected的方法。 *paintComponent
,paintBorder
,paintChildren
. *里面一次调用者三种方法来确保…(略)
重要的是子类通常要重写这个方法,来定制special特殊的图形组件
repeat方法被调用时,发生什么
Graphics与平台有关的详细介绍
所以做一个图形组件的基本思路可以总结为以下过程:
选择适合的基本图形组件 -> 继承它 -> 重写paint等方法->在需要刷新图形的时候调用repaint等方法!
至于Graphics,先假设它存在,因为真正的Graphics实例只有当程序在jvm上跑的时候才会创建。
俄罗斯方块中使用此技术的部分代码:
public class Tetris extends JPanel{
public static void main(String[] args) {
JFrame frame = new JFrame();
Tetris tetris = new Tetris();
frame.add(tetris);
frame.setSize(525, 590);
frame.setUndecorated(false);//true去掉窗口框!
frame.setTitle("俄罗斯方块");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Location 位置 RelativeTo相对于
frame.setLocationRelativeTo(null);//使当前窗口居中
frame.setVisible(true);
tetris.action();
}
public void action(){
//tetromino = Tetromino.randomTetromino();
//nextOne = Tetromino.randomTetromino();
//wall[19][2] = new Cell(19,2,Tetris.T);
startAction();
repaint();
KeyAdapter l = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_Q){
System.exit(0);//退出当前的Java进程
}
if(gameOver){
if(key==KeyEvent.VK_S){
startAction();
}
return;
}
//如果暂停并且按键是[C]就继续动作
if(pause){//pause = false
if(key==KeyEvent.VK_C){ continueAction(); }
return;
}
//否则处理其它按键
switch(key){
case KeyEvent.VK_RIGHT: moveRightAction(); break;
case KeyEvent.VK_LEFT: moveLeftAction(); break;
case KeyEvent.VK_DOWN: softDropAction() ; break;
case KeyEvent.VK_UP: rotateRightAction() ; break;
case KeyEvent.VK_Z: rotateLeftAction() ; break;
case KeyEvent.VK_SPACE: hardDropAction() ; break;
case KeyEvent.VK_P: pauseAction() ; break;
}
repaint();
}
};
this.requestFocus();
this.addKeyListener(l);
}
public void paint(Graphics g){
g.drawImage(background, 0, 0, null);//使用this 作为观察者
g.translate(15, 15);//平移绘图坐标系
paintTetromino(g);//绘制正在下落的方块
paintWall(g);//画墙
paintNextOne(g);
paintScore(g);
}
可以看到,main
方法中调用了action()
,而action()
方法中多次使用repaint()
方法进行页面刷新。
在paint()
方法中,实现具体的画图操作,可以看到都是使用Graphics
的相关函数,下面列举下其方法
g.drawImage(background, 0, 0, null)加载图像,画出图像
g.translate(15, 15);//平移绘图坐标系
g.setColor(new Color(FONT_COLOR))设置颜色;
g.setFont(font);设置字符串的字体
g.drawString(str, x, y)画字符串
应该注意的是,这里面没有多少其他组件插入的情况,完全是自己造的,从最基本的开始。