首先先吐槽一下用JAVA做界面的辛苦,往面板里绘制东西要获取他的Graphics,可往往要往里面画的类是别的类,然后你往里面画的时候…..坑就出来了。
以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()
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);