当前位置: 首页 > 知识库问答 >
问题:

调整JPanel大小后组件消失

刘永望
2023-03-14

我试图创建JPanel与可拖动的交叉显示后,鼠标点击。一切都很好,但是当我调整JPanel的大小时,交叉消失了。我试图重写JPanel中的paintComponent方法,但所有交叉都在坐标(0,0)处。我该怎么修好它?

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class CrossPanel extends JPanel implements MouseListener {

private int orderOfCross = 0;
private ArrayList<Cross> crosses;
private int defaultSizeOfCrosses = 10;

CrossPanel() {
    setOpaque(false);
    addMouseListener(this);
    crosses = new ArrayList<Cross>();
}

@Override
public void mouseClicked(MouseEvent e) {
    int x = e.getX();
    int y = e.getY();
    Cross cross = new Cross(orderOfCross++, defaultSizeOfCrosses);
    crosses.add(cross);
    cross.setLocation(x - defaultSizeOfCrosses, y - defaultSizeOfCrosses);
    add(cross);
    repaint();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    //        for (int i = 0; i < crosses.size(); i++) {
    //            crosses.get(i).paint(g);
    //        }
}

@Override
public void mousePressed(MouseEvent e) {}

@Override
public void mouseReleased(MouseEvent e) {}

@Override
public void mouseEntered(MouseEvent e) {}

@Override
public void mouseExited(MouseEvent e) {}

public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    CrossPanel crossPane = new CrossPanel();
    f.getContentPane().add(crossPane);
    f.setSize(600, 500);
    f.setLocation(200, 200);
    f.setVisible(true);
}
}

class Cross extends JComponent {

private int order;
protected Cursor draggingCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
private volatile int draggedAtX, draggedAtY;
int size;

public Cross(int order, int size) {
    this.order = order;
    this.size = size;
    this.setBounds(0, 0, 4 * size, 3 * size + 10);
    addDragListeners();
    setCursor(draggingCursor);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(Color.red);
    g2.setStroke(new BasicStroke(3));
    g2.drawLine(0, size, size + size, size);
    g2.drawLine(size, 0, size, size + size);
    Font f = new Font("Monospaced", Font.BOLD, size + 10);
    g2.setFont(f);
    g2.drawString(String.valueOf(order), size - size / 2, 3 * size + 10);
}

private void addDragListeners() {
    addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            draggedAtX = e.getX();
            draggedAtY = e.getY();
        }
    });
  addMouseMotionListener(new MouseMotionAdapter() {
        @Override
        public void mouseDragged(MouseEvent e) {
            Point newLocation = new Point(e.getX() - draggedAtX + getLocation().x,  e.getY() - draggedAtY + getLocation().y);
            setLocation(newLocation);
        }
    });
}
}

共有1个答案

马胜泫
2023-03-14

我很少看到null布局的使用,对于所有感觉到的好处来说,有很多好处。

整个Swing API都是围绕布局管理器的使用而设计的,所以如果你把所有这些工作都扔掉,那就太疯狂了(IMHO)。

如果您发现自己处于一个位置,可用的布局管理器似乎没有做您想做的事情,那么编写自己的布局管理器可能更值得。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class CrossPanel extends JPanel implements MouseListener {

    private int orderOfCross = 0;
    private ArrayList<Cross> crosses;
    private int defaultSizeOfCrosses = 10;

    CrossPanel() {
        setOpaque(false);
        addMouseListener(this);
        crosses = new ArrayList<Cross>();
        setLayout(new PropertionalLayoutManager());
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        Cross cross = new Cross(orderOfCross++, defaultSizeOfCrosses);

        float xPos = (float)x / (float)getWidth();
        float yPos = (float)y / (float)getHeight();

        crosses.add(cross);

        add(cross, new PropertionalConstraints(xPos, yPos));
        revalidate();
    }

    public static String format(float value) {
        return NumberFormat.getNumberInstance().format(value);
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        CrossPanel crossPane = new CrossPanel();
        f.getContentPane().add(crossPane);
        f.setSize(600, 500);
        f.setLocation(200, 200);
        f.setVisible(true);
    }

    public class Cross extends JComponent {

        private int order;
        protected Cursor draggingCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
        private volatile int draggedAtX, draggedAtY;
        int size;

        public Cross(int order, int size) {
            this.order = order;
            this.size = size;
//            this.setBounds(0, 0, 4 * size, 3 * size + 10);
            addDragListeners();
            setCursor(draggingCursor);
            Font f = new Font("Monospaced", Font.BOLD, size + 10);
            setFont(f);

        }

        @Override
        public Dimension getPreferredSize() {
            // This is dangrous, you are making assumptions about platforms
            // that you have no eviednce to support.
            FontMetrics fm = getFontMetrics(getFont());
            return new Dimension(Math.max(fm.stringWidth(String.valueOf(order)), size), size + fm.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            g2.setColor(Color.red);
            g2.setStroke(new BasicStroke(3));

            FontMetrics fm = g2.getFontMetrics();

            int width = getWidth() - 1;
            int height = getHeight() - 1;

            int x = (width - fm.stringWidth(String.valueOf(order))) / 2;
            int y = fm.getAscent();
            g2.drawString(String.valueOf(order), x, y);

            int crossSize = Math.min(width, height - fm.getHeight());
            x = (width - crossSize) / 2;
            y = fm.getHeight();
            g2.drawLine(x, y, x + crossSize, y + crossSize);
            g2.drawLine(x + crossSize, y, x, y + crossSize);
        }

        private void addDragListeners() {
            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    draggedAtX = e.getX();
                    draggedAtY = e.getY();
                }

            });
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    Point newLocation = new Point(e.getX() - draggedAtX + getLocation().x, e.getY() - draggedAtY + getLocation().y);
                    setLocation(newLocation);
                }

            });
        }

    }

    public class PropertionalConstraints {

        private float x;
        private float y;

        public PropertionalConstraints(float x, float y) {
            this.x = x;
            this.y = y;
        }

        public float getX() {
            return x;
        }

        public float getY() {
            return y;
        }

        public void setX(float x) {
            if (x > 1f) {
                x = 1f;
            } else if (x < -0f) {
                x = 0f;
            }
            this.x = x;
        }

        public void setY(float y) {
            if (y > 1f) {
                y = 1f;
            } else if (y < -0f) {
                y = 0f;
            }
            this.y = y;
        }

    }

    public class PropertionalLayoutManager implements LayoutManager2 {

        private Map<Component, PropertionalConstraints> mapConstraints;

        public PropertionalLayoutManager() {
            mapConstraints = new HashMap<>(25);
        }

        public PropertionalConstraints getConstraintsFor(Component comp) {
            return mapConstraints.get(comp);
        }

        public void setConstraintsFor(Component comp, PropertionalConstraints pc) {
            mapConstraints.put(comp, pc);
        }

        @Override
        public void addLayoutComponent(Component comp, Object constraints) {
            if (constraints instanceof PropertionalConstraints) {
                mapConstraints.put(comp, (PropertionalConstraints) constraints);
            } else {
                throw new IllegalArgumentException("Constraints must be PropertionalConstraints");
            }
        }

        @Override
        public Dimension maximumLayoutSize(Container target) {
            return preferredLayoutSize(target);
        }

        @Override
        public float getLayoutAlignmentX(Container target) {
            return 0.5f;
        }

        @Override
        public float getLayoutAlignmentY(Container target) {
            return 0.5f;
        }

        @Override
        public void invalidateLayout(Container target) {

        }

        @Override
        public void addLayoutComponent(String name, Component comp) {

        }

        @Override
        public void removeLayoutComponent(Component comp) {
            mapConstraints.remove(comp);
        }

        @Override
        public Dimension preferredLayoutSize(Container parent) {
            return parent.getSize();
        }

        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return preferredLayoutSize(parent);
        }

        @Override
        public void layoutContainer(Container parent) {
            int width = parent.getWidth();
            int height = parent.getHeight();
            for (Component comp : parent.getComponents()) {
                PropertionalConstraints con = mapConstraints.get(comp);
                if (con != null) {
                    int x = (int)(width * con.getX());
                    int y = (int)(height * con.getY());
                    comp.setSize(comp.getPreferredSize());
                    comp.setLocation(x, y);
                } else {
                    comp.setBounds(0, 0, 0, 0);
                }
            }
        }

    }

}
 类似资料:
  • 起初,我只有文本栏和状态栏,如下例所示(我不需要父容器): 这是应该的。但是,请记住状态栏的高度。现在,如果您将StatusBar类更改为下面的类,那么高度几乎会增加一倍。为什么会这样? 这种设置并不需要更多的垂直空间: 我可以让这成为一个新问题,但我觉得不值得...

  • 我对JPanel和JFrame还是个新手,可能没有按照我应该的方式使用它们。我正在尝试创建Pong游戏,在创建JFrame并将JPanel添加到它之后,我可以调整JPanel的大小,但我不知道如何调整JFrame的大小以适应它。Game类扩展了JPanel。 主: 编辑: 将setSize更改为setPreferredSize,然后为JFrame调用pack()就可以解决所有问题。

  • 问题内容: 我有一个与作为布局经理。 在南边界中,我有一个,我希望用户可以调整其大小,即用户可以单击边界的边缘并将其向上拖动以使其变大。 您是否知道我可以做到这一点? 问题答案: 为了使框架中的面板可单独调整大小,您需要将其添加到。 而不是将其放置在框架的南部,而是将其放置在中心。拆分窗格将使拆分中的底部面板看起来像在南方,而拆分中的顶部面板将位于框架的中心。 确保使用设置两个面板的方向。 然后,

  • 问题内容: 我是Java的新手,开始学习挥杆技巧,并且在JFrame中调整JPanel的大小时遇到​​问题。我正在关注本教程: http://vincentramdhanie.blogspot.com/2009/11/cardlayout-with- netbeans.html 因为最终我将学习每种不同的布局,并且现在已经进入CardLayout。在上面,有一个JPanel用于状态面板。那也是我想

  • 我是Java新手,开始学习swing,在JFrame中调整JPanel的大小时遇到问题。我将学习本教程: http://vincentramdhanie.blogspot.com/2009/11/cardlayout-with-netbeans.html 因为最终我正在学习每一种不同的布局,现在我来到了CardLayout。在上面,有一个JPanel用于状态面板。这也是我想要做的,但是当我将一个J