图像化界面paint,repaint方法的总结

JAVA 画图中出现的paint()函数

问题:刚学JAVA,有一个问题。以下是一段JAVA代码,它弹出了一个窗口,并在窗口上使用paint()画出矩形、椭圆、扇面等图形。现在我想让画图行为受用户控制,比如说,开始只有一个空白窗口。当用户输入1,画出矩形。用户输入2,擦掉矩形。用户输入3,画出椭圆。等等等等。

所以小弟应该如何做?有什么思路?需要什么东西?

案例代码:

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);
	}

一,我们先运行第一个Test程序,得到的图像是:

图像化界面paint,repaint方法的总结_第1张图片
我们可以看到paint方法是被调用了的。

二,原因分析

首先paint方法,并不仅是JPanel的方法,而是继承自JComponent的方法,该方法说明如下:
/**
     * 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特殊的图形组件

其次,那么为什么不应该直接调用paint而应该调用repaint呢?查了很多资料,有一个说的很简单,直接。
  • repaint()是重要概念,它是在图形线程后追加一段重绘操作,是安全的!是系统真正调用的重绘!所以如果你需要某个部件刷新一下界面,记得调用repaint(),千万不要直接调用paint()!
  • Graphics是一个抽象类,其实现大都是平台相关的,所以不容易自己创建一个graphics实例。一般graphics的实例会由依照你所在的桌面环境给出。
最后, repaint里面间接调用了paint方法。但是是如何间接调用的呢?repaint方法里面是否new了一个graphics对象呢然后传给paint呢?

repeat方法被调用时,发生什么
Graphics与平台有关的详细介绍

图像化界面paint,repaint方法的总结_第2张图片

三,程序员使用过程:

所以做一个图形组件的基本思路可以总结为以下过程:
选择适合的基本图形组件 -> 继承它 -> 重写paint等方法->在需要刷新图形的时候调用repaint等方法!
至于Graphics,先假设它存在,因为真正的Graphics实例只有当程序在jvm上跑的时候才会创建。
图像化界面paint,repaint方法的总结_第3张图片
俄罗斯方块中使用此技术的部分代码:

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)画字符串

应该注意的是,这里面没有多少其他组件插入的情况,完全是自己造的,从最基本的开始。

你可能感兴趣的:(java)