我有一个简单的类,绘制一条线时鼠标拖动或者当鼠标按下的点(释放)。
当我最小化应用程序,然后将其还原,窗口的内容除了最后一个点(像素)消失。 据我所知,该方法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);
}
}
你是不是保存您绘制的点的状态。 当面板被粉刷一新,它只有在最后一点上,画了的信息。
回应评论:
你需要有个点的集合,比如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);
}
集合locations
通常被称为显示列表中。 大多数图形程序中使用它们。
回应评论:
是的,我想会的。 我只是把剩下的想法基于代码给你一个起点。 这是几乎可以肯定是一个坏主意,因为我所描述做的正是。
难道这不是意味着我就要吸引点(而不是一个),每次我按下或拖动鼠标?
是的,但@戴维的方法是数千个节点的完全令人满意,如可在可见GraphPanel
。 除此之外,考虑到轻量级的模式 ,如使用JTable
渲染和说明这里 。
附录:以您的AWTPainting
问题,下面的变化可以说明的区别系统-和App触发的绘画 。 当鼠标被拖动, 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;
}
}
@Andrew,@戴夫,@trashgod嗨,我做了这方面的一些研究,最后,这是我的本钱。 如果我错了请纠正我。 你不能覆盖paint()方法,所以你打电话,你需要做的应用触发的画repaint()每次。 重绘()调用update(),它的默认行为是调用paint()。 更新()被用于增量画; 解释当paint()方法在做所有的工作,这实际上意味着它在每一步画整个图像闪烁的屏幕。 不过,我的问题是,如果我在更新方法“locationsAdded = 0”添加这意味着每次我拖动鼠标我画的整体形象(如油漆),那么为什么没有眨眼像以前一样? 我也看到了一些关于在挥杆画,我不明白为什么更新()永远不会调用挥杆。 你能解释我为什么?
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
class CustomCanvas extends Canvas{
ArrayList<Point> locations;
int locationsAdded;
Point oldLocation;
Point location;
Dimension dimension;
CustomCanvas(Dimension dimension){
locations = new ArrayList<>();
this.dimension = dimension;
this.init();
addListeners();
}
private void init(){
oldLocation= new Point(0, 0);
location= new Point(0, 0);
}
public void paintLine(Graphics g, int x){
Point p1 = (Point)locations.get(x);
Point p2 = (Point)locations.get(x+1);
g.drawLine(p1.x, p1.y, p2.x, p2.y);
locationsAdded++;
}
@Override
public void paint(Graphics g){
locationsAdded = 0;
g.setColor(Color.red);
for(int i = locationsAdded; i < locations.size()-1; i++){
paintLine(g, i);
}
}
public void update(Graphics g) {
//locationsAdded = 0;
for (int i = locationsAdded; i < locations.size()-1; i++) {
paintLine(g, i);
}
}
private void addListeners(){
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent me){
oldLocation = location;
location = new Point(me.getX(), me.getY());
locations.add(location);
repaint();
}
});
}
@Override
public Dimension getMinimumSize() {
return dimension;
}
@Override
public Dimension getPreferredSize() {
return dimension;
}
}
class CustomFrame extends Panel {
Panel displayPanel = new Panel(new BorderLayout());
CustomCanvas canvas = new CustomCanvas(new Dimension(700, 700));
public CustomFrame(String titlu) {
canvas.setBackground(Color.white);
displayPanel.add(canvas, BorderLayout.CENTER);
this.add(displayPanel);
}
}
public class AWTPainting {
public static void main(String args[]) {
CustomFrame panel = new CustomFrame("Test Paint");
Frame f = new Frame();
f.add(panel);
f.pack();
f.setSize(700,700);
f.show();
}
}