无法同时调整JFrame的大小和设置位置。

huangapple go评论66阅读模式
英文:

can't resize and set location of JFrame in the same time

问题

我尝试进行一些训练项目,在其中我添加了一个没有装饰的JFrame,然后我为它添加了MouseMotionListener以改变鼠标光标,然后改变它的大小和位置,以使其看起来像任何可调整大小的有装饰的JFrame。

问题:在北部和西部,窗口框架没有被调整大小,而是持续改变位置而不改变大小,但当我以调试模式运行程序时,它可以正常工作。

我尝试使用线程和setBounds代替setSize,还尝试添加frame.revalidate()和frame.repaint(),但都没有奏效,有什么建议吗?

谢谢你的时间。

英文:

I was trying to do some projects for traning, in this one I added an undecorated JFrame, so I added MouseMotionListener to it to change the mouse cursor then change it's size and location to look like any resizable decorated JFrame

pblm: at north and west the frame doesn't resized it keeps change location without change it's size, but when I run the program in the debug mode it works

I tried use threads and setBounds instead of setSize, i tried also to add frame.revalidate() and frame.repaint(), but nothing work, any suggesion

thank you for your time


package newpackage;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;



public class ResizeUndecoratedJFrame {

    private int oldCursPosX;
    private int oldCursPosY;
    private Dimension lastSize;
    private Dimension minFrameSize;
    private int tempX, tempY;

    public ResizeUndecoratedJFrame() {
        JFrame frame = new JFrame();
        frame.setUndecorated(true);
        JPanel p = new JPanel();
        p.setMinimumSize(new Dimension(400, 300));
        p.setPreferredSize(new Dimension(400, 300));
        p.setMaximumSize(new Dimension(400, 300));
        frame.add(p);
        frame.setSize(400, 300);
        minFrameSize = new Dimension(400, 300);
        frame.setLocationRelativeTo(null);
        

        frame.addMouseMotionListener(new MouseMotionAdapter() {
            // change Cursor
            @Override
            public void mouseMoved(MouseEvent e) {
                tempX = e.getX();
                tempY = e.getY();
                int w = frame.getWidth();
                int h = frame.getHeight();
                if ((tempX <= 3) || (tempY <= 3) || (w - tempX <= 3) || (h - tempY <= 3)) {
                    int type;
                    if (w - tempX <= 3) {
                        type = Cursor.E_RESIZE_CURSOR;
                    } else {
                        if (tempX <= 3) {
                            type = Cursor.W_RESIZE_CURSOR;
                        } else {
                            if (tempY <= 3) {
                                type = Cursor.N_RESIZE_CURSOR;
                            } else {
                                type = Cursor.S_RESIZE_CURSOR;
                            }
                        }
                    }

                    frame.setCursor(Cursor.getPredefinedCursor(type));
                    oldCursPosX = e.getX();
                    oldCursPosY = e.getY();
                    lastSize = frame.getSize();
                } else {
                    frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                }
            }


            @Override
            public void mouseDragged(MouseEvent e) {
                int type = frame.getCursor().getType();
                if (type != Cursor.DEFAULT_CURSOR) {
                    // calculate the distance between last cursor position when it's pressed and the current position
                    int distX = 0, distY = 0;
                    int currentX = e.getX();
                    int currentY = e.getY();
                    boolean isWestOrNorth = false;

                    if (type == Cursor.E_RESIZE_CURSOR) {
                        distX = currentX - oldCursPosX;
                    } else {
                        if (type == Cursor.W_RESIZE_CURSOR) {
                            isWestOrNorth = true;
                            distX = oldCursPosX - currentX;
                        } else {
                            if (type == Cursor.N_RESIZE_CURSOR) {
                                isWestOrNorth = true;
                                distY = oldCursPosY - currentY;
                            } else {
                                distY = currentY - oldCursPosY;
                            }
                        }
                    }

                    int tempW = (int) (lastSize.getWidth() + distX);
                    int tempH = (int) (lastSize.getHeight() + distY);
                    // make sure user can't resize JFrame less than this minimum size
                    if ((distX < 0 && tempW <= minFrameSize.getWidth()) || (distY < 0 && tempH <= minFrameSize.getHeight())) {
                        return;
                    }

                    if (isWestOrNorth) {
                        frame.setLocation(Math.round(frame.getLocationOnScreen().x + e.getX() - tempX),
                                Math.round(frame.getLocationOnScreen().y + e.getY() - tempY));
                    }
                    frame.setSize(new Dimension(tempW, tempH));
                }
            }
        });

        frame.setVisible(true);
    }


    public static void main(String[] args) {
        new ResizeUndecoratedJFrame();
    }
}

答案1

得分: 1

我会使用MouseListener来保存鼠标按下时的位置,而不是在mouseMoved中执行此操作:

frame.addMouseListener(new MouseAdapter() {
    @Override
    public void mousePressed(MouseEvent e) {
        oldCursPosX = e.getX();
        oldCursPosY = e.getY();
    }
});

mouseDragged中,类似这样的操作:

int x = frame.getX();
int y = frame.getY();
int width = frame.getWidth();
int height = frame.getHeight();
int dx = e.getX() - oldCursPosX;
int dy = e.getY() - oldCursPosY;
switch (type) {
    case Cursor.N_RESIZE_CURSOR:
        frame.setLocation(x, y+dy);
        if (height-dy >= minFrameSize.height) {
            frame.setSize(width, height-dy);
        }
        dy = 0; // frame has moved - it is the reference for coordinates
        break;
    case Cursor.S_RESIZE_CURSOR:
        if (height+dy >= minFrameSize.height) {
            frame.setSize(width, height+dy);
        }
        break;
    // ... 类似于 W 和 E
}
oldCursPosX += dx;
oldCursPosY += dy;

设置光标仍然在mouseMoved()中完成,只需删除赋值语句。

<sub>此答案中的代码旨在完整、优化,甚至不是有效的 - 仅提供基本思路</sub>

英文:

I would use a MouseListener to save the mouse position when pressed, instead of doing that inside mouseMoved:

frame.addMouseListener(new MouseAdapter() {
    @Override
    public void mousePressed(MouseEvent e) {
        oldCursPosX = e.getX();
        oldCursPosY = e.getY();
    }
});

and in mouseDragged, something like:

int x = frame.getX();
int y = frame.getY();
int width = frame.getWidth();
int height = frame.getHeight();
int dx = e.getX() - oldCursPosX;
int dy = e.getY() - oldCursPosY;
switch (type) {
    case Cursor.N_RESIZE_CURSOR:
        frame.setLocation(x, y+dy);
        if (height-dy &gt;= minFrameSize.height) {
            frame.setSize(width, height-dy);
        }
        dy = 0; // frame has moved - it is the reference for coordinates
        break;
    case Cursor.S_RESIZE_CURSOR:
        if (height+dy &gt;= minFrameSize.height) {
            frame.setSize(width, height+dy);
        }
        break;
    // ... similar for W and E
}
oldCursPosX += dx;
oldCursPosY += dy;

Setting the Cursor would still be done in mouseMoved(), just remove the assignment statements.

<sub>code in this answer is not intended to be complete, optimized, not even valid - just the basic idea</sub>

答案2

得分: 0

有点奇怪的是,在拖动进行时移动窗口时发生了一些问题。尝试使用绝对坐标,并且如某人所说,在mousePressed事件中保存位置。

我经常使用以下接口的实现来处理鼠标拖动事件:

public interface MouseDragger {
    public void mouseDragged(int x, int y);
    public void mouseReleased(int x, int y);
}

在被移动/调整大小的组件中,我会实现MouseListenerMouseMotionListener,并实现以下方法:

...
MouseDragger mouseDragger;
...

@Override
public void mousePressed(MouseEvent e) {
    if (e.getButton() == MouseEvent.BUTTON1) {
        System.out.println(e);
        mouseDragger = ResizeMouseDragger.get(this, e.getX(), e.getY());
    }
}

@Override
public void mouseReleased(MouseEvent e) {
    if (mouseDragger != null && e.getButton() == MouseEvent.BUTTON1) {
        mouseDragger.mouseReleased(e.getX(), e.getY());
        mouseDragger = null;
    }
}

@Override
public void mouseDragged(MouseEvent e) {
    if (mouseDragger != null) {
        System.out.println(e);
        mouseDragger.mouseDragged(e.getX(), e.getY());
    }
}

@Override
public void mouseMoved(MouseEvent e) {
    Direction dir = Direction.hitTest(
            getSize(), e.getX(), e.getY());
    if (dir == null) {
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    } else {
        setCursor(dir.getCursor());
    }
}

ResizeMouseDragger类如下:

class ResizeMouseDragger implements MouseDragger {
    private final Component comp;
    private final Direction dir;
    private final Rectangle bounds;
    private final int x;
    private final int y;

    public ResizeMouseDragger(Component comp, Direction dir, int x, int y) {
        this.comp = comp;
        this.bounds = comp.getBounds();
        this.dir = dir;
        Point pt = MouseInfo.getPointerInfo().getLocation();
        this.x = pt.x;
        this.y = pt.y;
    }

    public static MouseDragger get(Component comp, int x, int y) {
        Direction dir = Direction.hitTest(comp.getSize(), x, y);
        if (dir == null) {
            return null;
        } else {
            return new ResizeMouseDragger(comp, dir, x, y);
        }
    }

    @Override
    public void mouseDragged(int x, int y) {
        Point pt = MouseInfo.getPointerInfo().getLocation();
        int dx = pt.x - this.x;
        int dy = pt.y - this.y;
        switch (dir) {
            case NORTH: {
                if (dy != 0) {
                    comp.setBounds(bounds.x, bounds.y + dy,
                            bounds.width, bounds.height - dy);
                }
                break;
            }
            case SOUTH: {
                if (dy != 0) {
                    comp.setBounds(bounds.x, bounds.y,
                            bounds.width, bounds.height + dy);
                }
                break;
            }
            case WEST: {
                if (dx != 0) {
                    comp.setBounds(bounds.x + dx, bounds.y,
                            bounds.width - dx, bounds.height);
                }
                break;
            }
            case EAST: {
                if (dx != 0) {
                    comp.setBounds(bounds.x, bounds.y,
                            bounds.width + dx, bounds.height);
                }
                break;
            }
        }
    }

    @Override
    public void mouseReleased(int x, int y) {
    }
}

还有一个Direction类:

public enum Direction {
    NORTH(Cursor.N_RESIZE_CURSOR),
    SOUTH(Cursor.S_RESIZE_CURSOR),
    WEST(Cursor.W_RESIZE_CURSOR),
    EAST(Cursor.E_RESIZE_CURSOR),
    NORTH_WEST(Cursor.NW_RESIZE_CURSOR),
    NORTH_EAST(Cursor.NE_RESIZE_CURSOR),
    SOUTH_WEST(Cursor.SW_RESIZE_CURSOR),
    SOUTH_EAST(Cursor.SE_RESIZE_CURSOR);
    
    private static final int HANDLE_WIDTH = 4;
    
    private final int cursor;
    
    public static Direction hitTest(Dimension size, int x, int y) {
        if (x < 0 || y < 0 || x > size.width || y > size.height) {
            // outside of the frame
            return null;
        } else if (x <= HANDLE_WIDTH) {
            // west
            if (y <= HANDLE_WIDTH) {
                return NORTH_WEST;
            } else if (y >= size.height-HANDLE_WIDTH) {
                return SOUTH_WEST;
            } else {
                return WEST;
            }
        } else if (x >= size.width-HANDLE_WIDTH) {
            // east
            if (y <= HANDLE_WIDTH) {
                return NORTH_EAST;
            } else if (y >= size.height-HANDLE_WIDTH) {
                return SOUTH_EAST;
            } else {
                return EAST;
            }
        } else {
            if (y <= HANDLE_WIDTH) {
                return NORTH;
            } else if (y >= size.height-HANDLE_WIDTH) {
                return SOUTH;
            } else {
                // center
                return null;
            }
        }
    }
    
    private Direction(int cursor) {
        this.cursor = cursor;
    }
    
    public Cursor getCursor() {
        return Cursor.getPredefinedCursor(cursor);
    }
}
英文:

There's something weird going on when you move a window while a drag is in progress. Try to use absolute coordinates, and, as someone has said, save the position on mousePressed event.

I often use an implementation of the following interface to handle mouse drag events:

public interface MouseDragger {
public void mouseDragged(int x, int y);
public void mouseReleased(int x, int y);
}

in the component being moved/resized, I would implement MouseListener and MouseMotionListener, and implement the following methods:

...
MouseDragger mouseDragger;
...
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
System.out.println(e);
mouseDragger = ResizeMouseDragger.get(this, e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (mouseDragger != null &amp;&amp; e.getButton() == MouseEvent.BUTTON1) {
mouseDragger.mouseReleased(e.getX(), e.getY());
mouseDragger = null;
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (mouseDragger != null) {
System.out.println(e);
mouseDragger.mouseDragged(e.getX(), e.getY());
}
}
@Override
public void mouseMoved(MouseEvent e) {
Direction dir = Direction.hitTest(
getSize(), e.getX(), e.getY());
if (dir == null) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} else {
setCursor(dir.getCursor());
}
}

To class ResizeMouseDragger looks like this:

class ResizeMouseDragger implements MouseDragger {
private final Component comp;
private final Direction dir;
private final Rectangle bounds;
private final int x;
private final int y;

public ResizeMouseDragger(Component comp, Direction dir, int x, int y) {
this.comp = comp;
this.bounds = comp.getBounds();
this.dir = dir;
Point pt = MouseInfo.getPointerInfo().getLocation();
this.x = pt.x;
this.y = pt.y;
}
public static MouseDragger get(Component comp, int x, int y) {
Direction dir = Direction.hitTest(comp.getSize(), x, y);
if (dir == null) {
return null;
} else {
return new ResizeMouseDragger(comp, dir, x, y);
}
}
@Override
public void mouseDragged(int x, int y) {
Point pt = MouseInfo.getPointerInfo().getLocation();
int dx = pt.x - this.x;
int dy = pt.y - this.y;
switch (dir) {
case NORTH: {
if (dy != 0) {
comp.setBounds(bounds.x, bounds.y + dy,
bounds.width, bounds.height - dy);
}
break;
}
case SOUTH: {
if (dy != 0) {
comp.setBounds(bounds.x, bounds.y,
bounds.width, bounds.height + dy);
}
break;
}
case WEST: {
if (dx != 0) {
comp.setBounds(bounds.x + dx, bounds.y,
bounds.width - dx, bounds.height);
}
break;
}
case EAST: {
if (dx != 0) {
comp.setBounds(bounds.x, bounds.y,
bounds.width + dx, bounds.height);
}
break;
}
}
}
@Override
public void mouseReleased(int x, int y) {
}

}

And I would have a Direction class:

public enum Direction {
NORTH(Cursor.N_RESIZE_CURSOR),
SOUTH(Cursor.S_RESIZE_CURSOR),
WEST(Cursor.W_RESIZE_CURSOR),
EAST(Cursor.E_RESIZE_CURSOR),
NORTH_WEST(Cursor.NW_RESIZE_CURSOR),
NORTH_EAST(Cursor.NE_RESIZE_CURSOR),
SOUTH_WEST(Cursor.SW_RESIZE_CURSOR),
SOUTH_EAST(Cursor.SE_RESIZE_CURSOR);
private static final int HANDLE_WIDTH = 4;
private final int cursor;
public static Direction hitTest(Dimension size, int x, int y) {
if (x &lt; 0 || y &lt; 0 || x &gt; size.width || y &gt; size.height) {
// outside of the frame
return null;
} else if (x &lt;= HANDLE_WIDTH) {
// west
if (y &lt;= HANDLE_WIDTH) {
return NORTH_WEST;
} else if (y &gt;= size.height-HANDLE_WIDTH) {
return SOUTH_WEST;
} else {
return WEST;
}
} else if (x &gt;= size.width-HANDLE_WIDTH) {
// east
if (y &lt;= HANDLE_WIDTH) {
return NORTH_EAST;
} else if (y &gt;= size.height-HANDLE_WIDTH) {
return SOUTH_EAST;
} else {
return EAST;
}
} else {
if (y &lt;= HANDLE_WIDTH) {
return NORTH;
} else if (y &gt;= size.height-HANDLE_WIDTH) {
return SOUTH;
} else {
// center
return null;
}
}
}
private Direction(int cursor) {
this.cursor = cursor;
}
public Cursor getCursor() {
return Cursor.getPredefinedCursor(cursor);
}
}

huangapple
  • 本文由 发表于 2023年5月11日 09:01:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76223480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定