Java,鼠标拖动仿射变换

Java,鼠标拖动仿射变换,java,swing,affinetransform,custom-painting,Java,Swing,Affinetransform,Custom Painting,我正在研究JavaSwing 我需要一个应用程序,使用户可以缩放图形 绘图是在自定义的方法中完成的 比如说,绘图是一个方法调用 在应用程序中,缩放图形有两种方式(我称之为“模式”): 调用图形的方法时,只需增加图形的宽度和高度。例如: graphics.drawRect(x, y, width + addX, height + addY); graphics.transform(at); graphics.drawRect(x, y, width, height); 其中,addX和addY

我正在研究JavaSwing

我需要一个应用程序,使用户可以缩放图形

绘图是在自定义的方法中完成的

比如说,绘图是一个方法调用

在应用程序中,缩放图形有两种方式(我称之为“模式”):

  • 调用图形的方法时,只需增加图形的宽度和高度。例如:

    graphics.drawRect(x, y, width + addX, height + addY);
    
    graphics.transform(at);
    graphics.drawRect(x, y, width, height);
    
    其中,
    addX
    addY
    是用户鼠标拖动手势的偏移量

  • 在绘制图形之前,使用/更改处理图形缩放的。例如:

    graphics.drawRect(x, y, width + addX, height + addY);
    
    graphics.transform(at);
    graphics.drawRect(x, y, width, height);
    
  • 这两种缩放模式组合在一起

    用户在图形边缘拖动鼠标以缩放图形

    用户通过两个按钮选择每次启用的模式:第一个模式为1个按钮(“绘制比例”),第二个模式为1个按钮(“仿射变换比例”)

    以下是我目前的代码:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Cursor;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.awt.geom.AffineTransform;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class Main {
    
        //The panel which handles drawing:
        private static class PaintPanel extends JPanel {
            private final double drawX, drawY;
            private final AffineTransform at;
            private double drawWidth, drawHeight;
    
            public PaintPanel(final double drawX,
                              final double drawY,
                              final double drawWidth,
                              final double drawHeight) {
                at = new AffineTransform();
                this.drawX = drawX;
                this.drawY = drawY;
                this.drawWidth = drawWidth;
                this.drawHeight = drawHeight;
            }
    
            public AffineTransform getAffineTransform() {
                return at;
            }
    
            public double getDrawX() {
                return drawX;
            }
    
            public double getDrawY() {
                return drawY;
            }
    
            public double getDrawWidth() {
                return drawWidth;
            }
    
            public double getDrawHeight() {
                return drawHeight;
            }
    
            public double getTotalWidth() {
                return getDrawWidth() * getAffineTransform().getScaleX();
            }
    
            public double getTotalHeight() {
                return getDrawHeight() * getAffineTransform().getScaleY();
            }
    
            @Override
            public void paintComponent(final Graphics g) {
                super.paintComponent(g);
                final Graphics2D g2d = (Graphics2D) g.create();
    
                //Red rectangle for clarity.
                g.setColor(Color.RED);
                g.drawRect((int)getDrawX(), (int)getDrawY(), (int)getTotalWidth()-1, (int)getTotalHeight()-1);
    
                //The drawing!
                g2d.transform(getAffineTransform());
                g2d.drawRect((int)getDrawX(), (int)getDrawY(), (int)getDrawWidth()-1, (int)getDrawHeight()-1);
                g2d.drawOval((int)getDrawX(), (int)getDrawY(), (int)getDrawWidth()-1, (int)getDrawHeight()-1);
    
                g2d.dispose();
            }
    
            //The scale(...) method scales the drawing.
            //The scale(...) method needs changes.
            public void scale(final boolean drawScale,
                              final double addX,
                              final double addY) {
                if (drawScale) {
                    drawWidth += (addX / getAffineTransform().getScaleX());
                    drawHeight += (addY / getAffineTransform().getScaleY());
                }
                else {
                    final double tmpAddX = addX / getAffineTransform().getScaleX(),
                                 tmpAddY = addY / getAffineTransform().getScaleY();
                    final double sx = (getDrawWidth() + tmpAddX) / getDrawWidth(),
                                 sy = (getDrawHeight() + tmpAddY) / getDrawHeight();
    
                    getAffineTransform().scale(sx, sy);
    
                    final double tmpAddX2 = addX / getAffineTransform().getScaleX(),
                                 tmpAddY2 = addY / getAffineTransform().getScaleY();
                    final double sx2 = (getDrawWidth() + tmpAddX2) / getDrawWidth(),
                                 sy2 = (getDrawHeight() + tmpAddY2) / getDrawHeight();
    
                    getAffineTransform().translate(getDrawX() - getDrawX()*sx2,
                                                   getDrawY() - getDrawY()*sy2);
                }
                repaint();
            }
        }
    
        private static boolean drawScale;
    
        public static void main(final String[] args) {
            final Dimension dim = new Dimension(300, 300);
            final int drawOff = 100;
    
            final PaintPanel paintPanel = new PaintPanel(drawOff/2, drawOff/2, dim.width - 2*drawOff, dim.height - 2*drawOff);
            paintPanel.setPreferredSize(dim);
            final MouseAdapter ma = new MouseAdapter() {
                private Point dragLocation;
                private boolean dragX, dragY;
    
                //Tells if the width is dragged:
                private boolean isDragX(final Point loc) {
                    return (loc.getX() > paintPanel.getTotalWidth()-10+paintPanel.getDrawX()
                            && loc.getX() < paintPanel.getTotalWidth()+10+paintPanel.getDrawX()
                            && loc.getY() < paintPanel.getTotalHeight()+paintPanel.getDrawY()+10
                            && loc.getY() > paintPanel.getDrawY());
                }
    
                //Tells if the height is dragged:
                private boolean isDragY(final Point loc) {
                    return (loc.getY() > paintPanel.getTotalHeight()-10+paintPanel.getDrawY()
                            && loc.getY() < paintPanel.getTotalHeight()+10+paintPanel.getDrawY()
                            && loc.getX() < paintPanel.getTotalWidth()+paintPanel.getDrawX()+10
                            && loc.getX() > paintPanel.getDrawX());
                }
    
                //Only used to set the cursor:
                @Override
                public void mouseMoved(final MouseEvent mevt) {
                    final Point loc = mevt.getPoint();
                    if (isDragX(loc) && isDragY(loc))
                        paintPanel.setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
                    else if (isDragX(loc))
                        paintPanel.setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
                    else if (isDragY(loc))
                        paintPanel.setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
                    else if (paintPanel.getCursor() != Cursor.getDefaultCursor())
                        paintPanel.setCursor(Cursor.getDefaultCursor());
                }
    
                //Determines (on mouse click) which sides are dragged:
                @Override
                public void mousePressed(final MouseEvent mevt) {
                    final Point loc = mevt.getPoint();
                    dragX = isDragX(loc);
                    dragY = isDragY(loc);
                    dragLocation = loc;
                }
    
                //Scales while dragging:
                @Override
                public void mouseDragged(final MouseEvent mevt) {
                    final Point loc = mevt.getPoint();
                    if (dragX && dragY)
                        paintPanel.scale(drawScale, loc.getX()-dragLocation.getX(), loc.getY()-dragLocation.getY());
                    else if (dragX)
                        paintPanel.scale(drawScale, loc.getX()-dragLocation.getX(), 0);
                    else if (dragY)
                        paintPanel.scale(drawScale, 0, loc.getY()-dragLocation.getY());
                    dragLocation = loc;
                }
            };
            paintPanel.addMouseListener(ma);
            paintPanel.addMouseMotionListener(ma);
    
            final JButton drawScaleButton = new JButton("Draw scale"),
                          affineTransformScaleButton = new JButton("AffineTransform scale");
            drawScaleButton.addActionListener(e -> {
                drawScale = true;
                drawScaleButton.setEnabled(false);
                affineTransformScaleButton.setEnabled(true);
            });
            affineTransformScaleButton.addActionListener(e -> {
                drawScale = false;
                drawScaleButton.setEnabled(true);
                affineTransformScaleButton.setEnabled(false);
            });
            drawScale = false;
            drawScaleButton.setEnabled(true);
            affineTransformScaleButton.setEnabled(false);
    
            final JPanel buttons = new JPanel(/*FlowLayout*/);
            buttons.add(affineTransformScaleButton);
            buttons.add(drawScaleButton);
    
            final JPanel contents = new JPanel(new BorderLayout());
            contents.add(buttons, BorderLayout.PAGE_START);
            contents.add(paintPanel, BorderLayout.CENTER);
    
            final JFrame frame = new JFrame("Scaling shape test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(contents);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }
    
    导入java.awt.BorderLayout;
    导入java.awt.Color;
    导入java.awt.Cursor;
    导入java.awt.Dimension;
    导入java.awt.Graphics;
    导入java.awt.Graphics2D;
    导入java.awt.Point;
    导入java.awt.event.MouseAdapter;
    导入java.awt.event.MouseEvent;
    导入java.awt.geom.AffineTransform;
    导入javax.swing.JButton;
    导入javax.swing.JFrame;
    导入javax.swing.JPanel;
    公共班机{
    //处理图形的面板:
    私有静态类PaintPanel扩展了JPanel{
    私人最终双抽绳,抽绳;
    私人最终仿射翻译在;
    私人双抽宽,抽高;
    公共漆面(最终双抽,
    最后的双抽,
    最终双拉伸宽度,
    最终双抽高度){
    at=新仿射变换();
    this.drawX=drawX;
    this.drawY=drawY;
    this.drawWidth=drawWidth;
    this.drawHeight=drawHeight;
    }
    公共AffineTransform getAffineTransform(){
    返回;
    }
    公共双getDrawX(){
    回采;
    }
    公共双盲法(){
    回程慢;
    }
    公共双getDrawWidth(){
    返回宽度;
    }
    公共双高{
    回程高度;
    }
    公共双getTotalWidth(){
    返回getDrawWidth()*getAffineTransform().getScaleX();
    }
    公共双getTotalHeight(){
    返回getDrawHeight()*getAffineTransform().getScaleY();
    }
    @凌驾
    公共组件(最终图形g){
    超级组件(g);
    最终图形2d g2d=(图形2d)g.创建();
    //为清晰起见,红色矩形。
    g、 setColor(Color.RED);
    g、 drawRect((int)getDrawX(),(int)getDrawY(),(int)getTotalWidth()-1,(int)getTotalHeight()-1);
    //这幅画!
    变换(getAffineTransform());
    g2d.drawRect((int)getDrawX(),(int)getDrawY(),(int)getDrawWidth()-1,(int)getDrawHeight()-1);
    g2d.drawOval((int)getDrawX(),(int)getDrawY(),(int)getDrawWidth()-1,(int)getDrawHeight()-1);
    g2d.dispose();
    }
    //缩放(…)方法缩放图形。
    //scale(…)方法需要更改。
    公共空隙比例(最终布尔拉伸比例,
    最终双地址,
    最终双地址){
    if(提取比例){
    drawWidth+=(addX/getAffineTransform().getScaleX());
    drawHeight+=(addY/getAffineTransform().getScaleY());
    }
    否则{
    final double tmpAddX=addX/getAffineTransform().getScaleX(),
    tmpAddY=addY/getAffineTransform().getScaleY();
    最终双精度sx=(getDrawWidth()+tmpAddX)/getDrawWidth(),
    sy=(getDrawHeight()+tmpAddY)/getDrawHeight();
    getAffineTransform().scale(sx,sy);
    final double tmpAddX2=addX/getAffineTransform().getScaleX(),
    tmpAddY2=addY/getAffineTransform().getScaleY();
    最终双精度sx2=(getDrawWidth()+tmpAddX2)/getDrawWidth(),
    sy2=(getDrawHeight()+tmpAddY2)/getDrawHeight();
    getAffineTransform().translate(getDrawX()-getDrawX()*sx2,
    getDrawY()-getDrawY()*sy2);
    }
    重新油漆();
    }
    }
    私有静态布尔尺度;
    公共静态void main(最终字符串[]args){
    最终尺寸尺寸=新尺寸(300300);
    最终整数支取=100;
    最终油漆面板油漆面板=新油漆面板(拉深/2,拉深/2,尺寸宽度-2*拉深,尺寸高度-2*拉深);
    油漆面板。设置首选尺寸(尺寸);
    最终MouseAdapter ma=新MouseAdapter(){
    私用点定位;
    私有布尔dragX,dragY;
    //指示是否拖动宽度:
    专用布尔isDragX(终点位置){
    返回(loc.getX()>paintPanel.getTotalWidth()-10+paintPanel.getDrawX()
    &&loc.getX()paintPanel.getDrawY());
    }
    //指示是否拖动高度:
    专用布尔isDragY(终点位置){
    return(loc.getY()>paintPanel.getTotalHeight()-10+paintPanel.getDrawY()
    &&loc.getY()