您的位置:首页 > 编程语言 > Java开发

JAVA中Swing的绘制原理以及如何实现动态图画

2017-10-27 22:04 1091 查看
首先先吐槽一下用JAVA做界面的辛苦,往面板里绘制东西要获取他的Graphics,可往往要往里面画的类是别的类,然后你往里面画的时候…..坑就出来了。

Swing组件绘制的原理

组件在初始画的时候会调用组件本身自带的paint()和paintComponent(),绘制出他想要的样子,如果你单纯想改变他的形状和样子时,就可以重写paint()或者paintComponent来达成。不过要注意,在Swing的原始组件中的paint()会调用paintComponent(),假如你想在paint()里绘制某个图像,paintComponent中绘制另一个()并且不想两个图像混在一起。看下列实例

以JPanel为例

public class MyPanel extends JPanel{
@Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
System.out.println("component");
}

@Override
public void paint (Graphics g) {
super.paint(g);
System.out.println("paint");
}

public static void main(String [] ars){
JFrame frame = new JFrame("paintTest");
MyPanel panel = new MyPanel();
frame.add(panel);
frame.setSize(300,300);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
class MyButton()
}


运行结果是:
component
paint


如果不想调用paintComponent(),可以将super.paint()注释掉,这对于Jpanel来说是没有什么问题的,但对于其他组件,例如JButton来说,JButton就不可正常显示了。

public class MyButton extends JButton {
public MyButton (String string) {
super(string);
}

@Override
protected void paintComponent (Graphics g) {
super.paintComponent(g);
}

@Override
public void paint (Graphics g) {
// super.paint(g);
}
}
MyButton button = new MyButton("button");
frame.add(button,BorderLayout.EAST);


图片插入不了,自己脑补吧。

所以可以自己根据实际情况来将自己要写的函数写在paint()或者paintComponent()

repaint()的实质其实是调用paint()重新绘制组件

timer.schedule(new TimerTask() {
@Override
public void run ( ) {
panel.repaint();
}
},1000);


这里要注意,如果你在调用了paint()同一个线程里调用repaint(),他不会重新绘制,因为paint()会查看你是否已经绘制了该组件,如果绘制了就不可重新绘制。所以在这里我们新建一个线程来执行重新绘制。同理,在已经绘制组件后获取组件的Graphics进行绘图也不会有任何显示。

例如

public static void main(String [] ars){
JFrame frame = new JFrame("paintTest");
MyPanel panel = new MyPanel();
frame.add(panel);
frame.setSize(400,400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
/*panel.repaint();这样不会panel不会重新绘制*/
/*或者
Graphics graphics = panel.getGraphics();
graphics.drawLine(0,0,50,50) 这样也不会有任何作用
*/
}


源码里的调用时这样的,具体逻辑可在JDK里看。

boolean printing = getFlag(IS_PRINTING);


结果是
component
paint
component
paint


动态图画的绘制

下面举出一个实例来实现动态图画

public class MyPanel extends JPanel{
int x =50;
int y =50;
@Override
public void paint (Graphics g) {
super.paint(g);
g.setColor(Color.red);
g.fillOval(x,y,30,30);
}
public static void main(String [] ars){
JFrame frame = new JFrame("paintTest");
MyPanel panel = new MyPanel();
frame.add(panel);
frame.setSize(400,400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
panel.repaint();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run ( ) {
if(panel.x<=300){
panel.x++;
panel.repaint();
}
}
},0,20);
}
}


Timer的主要用处在于创建一个新的线程,也可以用监听器代替。

注意不要写成这样,这样图画会闪烁不连续,具体为什么我也不太清楚了,可能是Swing画图时的会自己创建线程,导致抢资源了。

timer.schedule(new TimerTask() {
Graphics graphics = panel.getGraphics();
@Override
public void run ( ) {
if(panel.x<=300){
graphics.setColor(Color.red);
graphics.fillOval(panel.x,panel.y,30,30);
panel.x++;
panel.repaint();
}
}
},0,10);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息