在Jpanel上绘制一块可移动的画布

时间:2013-03-21 10:31:18

标签: java swing jpanel java-canvas

我想绘制一个可在Jpanel上移动的画布。也就是说,当用户点击画布并拖动它时,它必须移动到新的位置。我已经实现了MouseMotionListener但我不知道要包含什么内容以使画布按照要求移动。这是DisplayCanvas类:

class DisplayCanvas extends Canvas
{
    public DisplayCanvas()
    {
        setBounds(20, 40, 300, 300);
        setBackground(Color.white);
    }
}
class shape extends JFrame  implements MouseMotionListener{

static JPanel panel;
static Container contentpane;
static DisplayCanvas canvas;
shape()
{
    canvas=new DisplayCanvas();
    canvas.addMouseMotionListener(this);
    panel= new JPanel();
    panel.setBounds(20,20,250,140);
    panel.setLayout(null);
    contentpane = getContentPane();
    contentpane.add(canvas);
    contentpane.add(panel);
}
@Override
public void mouseDragged(MouseEvent e) {}
@Override
public void mouseMoved(MouseEvent arg0) {}
}

这就是我测试它的方式。

public class display 
{
    static JFrame frame;
    public static void main(String[] args) 
    {
        frame=new shape();
        frame.setBounds(380, 200, 500, 400);
        frame.setTitle("SHAPE AND COLOR");
        frame.setVisible(true);
    }
}

注意:请不要建议我使用JPanel来使用画布。

1 个答案:

答案 0 :(得分:4)

你不想扩展JPanel的事实似乎很奇怪,但这并不是不可行的。然而,您可能会在某些时候遇到问题,因为您正在混合轻量级和重量级组件。您可能会遇到视觉故障和其他显示问题。

但是,我会提请您注意您在当前代码中犯下的几个重要错误:

  1. 如果不需要,不要扩展课程(无需扩展JFrame也不要Canvas
  2. 除非绝对必要,否则不要制作变量static
  3. 遵循Java命名约定:类名始终以大写字母开头
  4. 请勿使用null LayoutManager
  5. 这是一个片段,说明了使这项工作非常基本的方式(代码需要重构以正确分离方面)

    import java.awt.Canvas;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Container;
    import java.awt.Dimension;
    import java.awt.LayoutManager2;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class TestHeavyweightLightweight {
    
        public class MyLayoutManager implements LayoutManager2 {
    
            private Map<Component, Rectangle> constraints = new LinkedHashMap<Component, Rectangle>();
    
            @Override
            public void addLayoutComponent(String name, Component comp) {
                constraints.put(comp, comp.getBounds());
            }
    
            @Override
            public void removeLayoutComponent(Component comp) {
                constraints.remove(comp);
            }
    
            @Override
            public Dimension preferredLayoutSize(Container parent) {
                Rectangle rect = new Rectangle();
                for (Rectangle r : constraints.values()) {
                    rect = rect.union(r);
                }
                return rect.getSize();
            }
    
            @Override
            public Dimension minimumLayoutSize(Container parent) {
                return preferredLayoutSize(parent);
            }
    
            @Override
            public void layoutContainer(Container parent) {
                for (Map.Entry<Component, Rectangle> e : constraints.entrySet()) {
                    e.getKey().setBounds(e.getValue());
                }
            }
    
            @Override
            public void addLayoutComponent(Component comp, Object constraints) {
                if (constraints instanceof Rectangle) {
                    this.constraints.put(comp, (Rectangle) constraints);
                } else {
                    addLayoutComponent((String) null, comp);
                }
            }
    
            @Override
            public Dimension maximumLayoutSize(Container target) {
                return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
            }
    
            @Override
            public float getLayoutAlignmentX(Container target) {
                return 0;
            }
    
            @Override
            public float getLayoutAlignmentY(Container target) {
                return 0;
            }
    
            @Override
            public void invalidateLayout(Container target) {
    
            }
    
            public void setConstraints(Component component, Rectangle rect) {
                constraints.put(component, rect);
            }
    
            public class MouseDragger extends MouseAdapter {
                private Point lastLocation;
                private Component draggedComponent;
    
                @Override
                public void mousePressed(MouseEvent e) {
                    draggedComponent = e.getComponent();
                    lastLocation = SwingUtilities.convertPoint(draggedComponent, e.getPoint(), draggedComponent.getParent());
                }
    
                @Override
                public void mouseDragged(MouseEvent e) {
                    Point location = SwingUtilities.convertPoint(draggedComponent, e.getPoint(), draggedComponent.getParent());
                    if (draggedComponent.getParent().getBounds().contains(location)) {
                        Point newLocation = draggedComponent.getLocation();
                        newLocation.translate(location.x - lastLocation.x, location.y - lastLocation.y);
                        newLocation.x = Math.max(newLocation.x, 0);
                        newLocation.x = Math.min(newLocation.x, draggedComponent.getParent().getWidth() - draggedComponent.getWidth());
                        newLocation.y = Math.max(newLocation.y, 0);
                        newLocation.y = Math.min(newLocation.y, draggedComponent.getParent().getHeight() - draggedComponent.getHeight());
                        setConstraints(draggedComponent, new Rectangle(newLocation, draggedComponent.getSize()));
                        if (draggedComponent.getParent() instanceof JComponent) {
                            ((JComponent) draggedComponent.getParent()).revalidate();
                        } else {
                            draggedComponent.getParent().invalidate();
                            draggedComponent.getParent().validate();
                        }
                        lastLocation = location;
                    }
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
                    lastLocation = null;
                    draggedComponent = null;
                }
    
                public void makeDraggable(Component component) {
                    component.addMouseListener(this);
                    component.addMouseMotionListener(this);
                }
    
            }
    
        }
    
        private Canvas canvas;
        private JPanel panel;
    
        protected void createAndShowGUI() {
            JFrame frame = new JFrame(TestHeavyweightLightweight.class.getSimpleName());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            canvas = new Canvas();
            canvas.setBackground(Color.WHITE);
            panel = new JPanel();
            MyLayoutManager mgr = new MyLayoutManager();
            panel.setLayout(mgr);
            panel.add(canvas, new Rectangle(20, 40, 300, 300));
            MyLayoutManager.MouseDragger mouseDragger = mgr.new MouseDragger();
            mouseDragger.makeDraggable(canvas);
            frame.add(panel);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new TestHeavyweightLightweight().createAndShowGUI();
                }
            });
        }
    
    }