【问题标题】:Listen to JFrame resize events as the user drags their mouse?在用户拖动鼠标时收听 JFrame 调整大小事件?
【发布时间】:2011-01-07 13:28:00
【问题描述】:

当用户单击 JFrame 的角以调整大小并拖动鼠标时,JFrame 在用户拖动时根据鼠标的当前位置重绘。你怎么能听到这些事件?

以下是我目前尝试过的:

public final class TestFrame extends JFrame {
    public TestFrame() {
        this.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                // This is only called when the user releases the mouse button.
                System.out.println("componentResized");
            }
        });
    }

    // These methods do not appear to be called at all when a JFrame
    // is being resized.
    @Override
    public void setSize(int width, int height) {
        System.out.println("setSize");
    }

    @Override
    public void setBounds(Rectangle r) {
        System.out.println("setBounds A");
    }

    @Override
    public void setBounds(int x, int y, int width, int height) {
        System.out.println("setBounds B");
    }
}

当用户在鼠标周围拖动时,如何确定和限制用户如何调整窗口大小(基于窗口的当前纵横比)?

【问题讨论】:

  • @finnw 你能澄清你赏金的原因吗,因为我看到Java_1.4Java_1.5 之间的区别,但我找不到Java_6note 的区别,但没有深入检查NestedInherits Method
  • @mKorbel,我尝试了这两种方法(JPanel 上的 ComponentListener;覆盖验证。)代码在两个 Java 版本下编译和运行,但在 Java 1.6 中,布局会不断重新计算,但在 Java 1.5 中,仅当我松开鼠标。
  • @finnw 你是在调整 JComponent 还是 JFrame
  • @mKorbel,我正在用鼠标调整 JFrame 的大小,因为它有一个 BorderLayout,组件(带有 BorderLayout.CENTER)应该跟随。
  • ComponentResizer by @camickr tips4java.wordpress.com/2009/09/13/resizing-components 来自 Java5 时代,

标签: java swing user-interface mouse


【解决方案1】:

你可以添加一个组件监听器并像这样实现 componentResized 函数:

JFrame component = new JFrame("My Frame");

component.addComponentListener(new ComponentAdapter() 
{  
        public void componentResized(ComponentEvent evt) {
            Component c = (Component)evt.getSource();
            //........
        }
});

编辑: 显然,对于 JFrame,componentResized 事件与 mouseReleased 事件挂钩。这就是释放鼠标按钮时调用该方法的原因。

实现您想要的一种方法是添加一个 JPanel,它将覆盖您的 JFrame 的整个区域。然后将 componentListener 添加到 JPanel(即使您的鼠标仍在拖动,也会调用 JPanel 的 componentResized)。当您的框架调整大小时,您的面板也将调整大小。

我知道,这不是最优雅的解决方案,但它确实有效!

【讨论】:

  • 感谢您的及时回复。但是,componentResized 似乎只在用户释放鼠标按钮时被调用。是否可以在用户拖动鼠标时监听调整大小事件
  • @Clinton 真的!抱歉,我没有仔细阅读您的问题!
  • @Clinton 我很好奇如何做到这一点,我发现的唯一方法是在 JFrame 中添加一个 JPanel。我不知道这是否对你有帮助。我已经更新了我的答案。
  • 感谢您修改后的解决方案。我试了一下,效果很好。但是,在我的情况下,验证选项更加简洁。
  • +1 因为我不必在单独的类中重写该函数! :) 这个答案即使在 5 年后也有帮助。
【解决方案2】:
public class MouseDrag extends Component implements MouseListener,
    MouseMotionListener {
  /** The Image we are to paint */
  Image curImage;

  /** Kludge for showStatus */
  static Label status;

  /** true if we are in drag */
  boolean inDrag = false;

  /** starting location of a drag */
  int startX = -1, startY = -1;

  /** current location of a drag */
  int curX = -1, curY = -1;

  // "main" method
  public static void main(String[] av) {
    JFrame f = new JFrame("Mouse Dragger");
    Container cp = f.getContentPane();

    if (av.length < 1) {
      System.err.println("Usage: MouseDrag imagefile");
      System.exit(1);
    }
    Image im = Toolkit.getDefaultToolkit().getImage(av[0]);

    // create a MouseDrag object
    MouseDrag j = new MouseDrag(im);

    cp.setLayout(new BorderLayout());
    cp.add(BorderLayout.NORTH, new Label(
        "Hello, and welcome to the world of Java"));
    cp.add(BorderLayout.CENTER, j);
    cp.add(BorderLayout.SOUTH, status = new Label());
    status.setSize(f.getSize().width, status.getSize().height);
    f.pack();
    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  // "Constructor" - creates the object
  public MouseDrag(Image i) {
    super();
    curImage = i;
    setSize(300, 200);
    addMouseListener(this);
    addMouseMotionListener(this);
  }

  public void showStatus(String s) {
    status.setText(s);
  }

  // Five methods from MouseListener:
  /** Called when the mouse has been clicked on a component. */
  public void mouseClicked(MouseEvent e) {
  }

  /** Called when the mouse enters a component. */
  public void mouseEntered(MouseEvent e) {
  }

  /** Called when the mouse exits a component. */
  public void mouseExited(MouseEvent e) {
  }


  // And two methods from MouseMotionListener:
  public void mouseDragged(MouseEvent e) {
    Point p = e.getPoint();
    // System.err.println("mouse drag to " + p);
    showStatus("mouse Dragged to " + p);
    curX = p.x;
    curY = p.y;
    if (inDrag) {
      repaint();
    }
  }

  public void paint(Graphics g) {
    int w = curX - startX, h = curY - startY;
    Dimension d = getSize();
    g.drawImage(curImage, 0, 0, d.width, d.height, this);
    if (startX < 0 || startY < 0)
      return;
    System.err.println("paint:drawRect @[" + startX + "," + startY
        + "] size " + w + "x" + h);
    g.setColor(Color.red);
    g.fillRect(startX, startY, w, h);
  }

}

【讨论】:

  • -1。这基本上是问题中代码的副本(我们已经知道它不能解决问题。)
【解决方案3】:

另一种解决方法(与 Alex 的非常相似,但更简单一点)是从 JFrame 的根窗格中监​​听事件:

public final class TestFrame extends JFrame {
    public TestFrame() {
        this.getRootPane().addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent e) {
                // This is only called when the user releases the mouse button.
                System.out.println("componentResized");
            }
        });
    }
}

根据其他实现细节,根窗格可能会更改。如果这是一种可能性,那么您可以覆盖 setRootPane() 并处理它。由于setRootPane() 受到保护并且只能从构造函数中调用,因此您不太可能需要这样做。

【讨论】:

  • 不应该是public void TestFrame() {...吗?
  • @AnnonomusPenguin,不,那是构造函数声明,构造函数没有指定返回类型如void
  • "// 仅在用户释放鼠标按钮时调用。" - 似乎不仅仅是释放鼠标按钮时。当我使用这段代码时,它会不断被调用,这将支持动态调整大小;释放鼠标后有什么方法可以调整大小?
  • 复制@MAXdB:释放鼠标后有什么方法可以调整大小?
【解决方案4】:

您可能需要覆盖 validate 之类的内容(不要忘记调用 super)。当然,如果您使用窗口系统配置为拖动轮廓,这仍然可能不起作用。

【讨论】:

  • 我怎么会为此打电话给超级?我以为你只能在构造函数中调用 super?
猜你喜欢
  • 1970-01-01
  • 2021-06-29
  • 2013-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 2013-05-31
相关资源
最近更新 更多