Car*_*aru 6 java graphics swing awt paint
我有一个简单的类,当鼠标拖动时绘制一条线或鼠标按下(释放)时画一个点.
当我最小化应用程序然后恢复它时,窗口的内容消失,除了最后一个点(像素).我知道super.paint(g)每次窗口改变时该方法都会重新绘制背景,但无论我是否使用它,结果似乎都是一样的.它们之间的区别在于,当我不使用它时,窗口上绘制的不仅仅是一个像素,而不是我的所有绘画.我怎样才能解决这个问题?
这是班级.
package painting;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
class CustomCanvas extends Canvas{
Point oldLocation= new Point(10, 10);
Point location= new Point(10, 10);
Dimension dimension = new Dimension(2, 2);
CustomCanvas(Dimension dimension){
this.dimension = dimension;
this.init();
addListeners();
}
private void init(){
oldLocation= new Point(0, 0);
location= new Point(0, 0);
}
public void paintLine(){
if ((location.x!=oldLocation.x) || (location.y!=oldLocation.y)) {
repaint(location.x,location.y,1,1);
}
}
private void addListeners(){
addMouseListener(new MouseAdapter(){
@Override
public void mousePressed(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
paintLine();
}
@Override
public void mouseReleased(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
paintLine();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
paintLine();
}
});
}
@Override
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.red);
g.drawLine(location.x, location.y, oldLocation.x, oldLocation.y);
}
@Override
public Dimension getMinimumSize() {
return dimension;
}
@Override
public Dimension getPreferredSize() {
return dimension;
}
}
class CustomFrame extends JPanel {
JPanel displayPanel = new JPanel(new BorderLayout());
CustomCanvas canvas = new CustomCanvas(new Dimension(200, 200));
public CustomFrame(String titlu) {
canvas.setBackground(Color.white);
displayPanel.add(canvas, BorderLayout.CENTER);
this.add(displayPanel);
}
}
public class CustomCanvasFrame {
public static void main(String args[]) {
CustomFrame panel = new CustomFrame("Test Paint");
JFrame f = new JFrame();
f.add(panel);
f.pack();
SwingConsole.run(f, 700, 700);
}
}
Run Code Online (Sandbox Code Playgroud)
您没有存储您正在绘制的点的状态.重新绘制面板时,它仅显示其绘制的最后一点的信息.
回复评论:
例如,您需要拥有一组Points ArrayList<Point> location = new ArrayList<Point>();
然后,在你的听众中: location.add(new Point(me.getX(), me.getY()));
最后,在paintLine()中:
for (Point location : locations) {
repaint(location.x,location.y,1,1);
}
Run Code Online (Sandbox Code Playgroud)
该集合locations通常称为显示列表.大多数图形程序都使用它们
回复评论:
是的,我希望如此.我只是根据你的代码抛出一个想法给你一个起点.完全按照我的描述做几乎肯定是个坏主意.
这是不是意味着每次按或拖动鼠标时我都会绘制所有点(而不是一个点)?
是的,但@ Dave的方法对于数千个节点来说是完全令人满意的,如可以看到的那样GraphPanel.除此之外,请考虑渲染器使用的flyweight模式,并在此处进行说明.JTable
附录:关注您的AWTPainting问题,下面的变化可能说明系统和应用程序触发的绘画之间的差异.拖动鼠标时,repaint()调用update(),调用paint(); 这是应用程序触发的.在调整窗口大小时,仅paint()调用(不绘制红色数字); 这是系统触发的.请注意,调整大小后释放鼠标时会出现闪烁.
当整个组件的背景被清除并重新绘制时,通常会发生闪烁:
4.如果组件并没有重写
update(),默认实现update()清除组件的背景(如果它不是一个轻量级组件),并简单地调用paint().

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
public class AWTPainting {
public static void main(String args[]) {
CustomPanel panel = new CustomPanel();
Frame f = new Frame();
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(panel);
f.pack();
f.setVisible(true);
}
}
class CustomPanel extends Panel {
public CustomPanel() {
this.add(new CustomCanvas(new Dimension(320, 240)));
}
}
class CustomCanvas extends Canvas {
private MouseAdapter handler = new MouseHandler();
private List<Point> locations = new ArrayList<Point>();
private Point sentinel = new Point();
private Dimension dimension;
CustomCanvas(Dimension dimension) {
this.dimension = dimension;
this.setBackground(Color.white);
this.addMouseListener(handler);
this.addMouseMotionListener(handler);
this.locations.add(sentinel);
}
@Override
public void paint(Graphics g) {
g.setColor(Color.blue);
Point p1 = locations.get(0);
for (Point p2 : locations.subList(1, locations.size())) {
g.drawLine(p1.x, p1.y, p2.x, p2.y);
p1 = p2;
}
}
@Override
public void update(Graphics g) {
paint(g);
g.clearRect(0, getHeight() - 24, 50, 20); // to background
g.setColor(Color.red);
g.drawString(String.valueOf(locations.size()), 8, getHeight() - 8);
}
private class MouseHandler extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (locations.get(0) == sentinel) { // reference identity
locations.set(0, new Point(e.getX(), e.getY()));
}
}
@Override
public void mouseDragged(MouseEvent e) {
locations.add(new Point(e.getX(), e.getY()));
repaint();
}
}
@Override
public Dimension getPreferredSize() {
return dimension;
}
}
Run Code Online (Sandbox Code Playgroud)