Java Swing中的JFrame如何仅在鼠标释放时输出x,y,w,h?

问题描述 投票:0回答:1

我下面有一个示例 Java Swing 应用程序,现在只要 JFrame 移动或调整大小,它就会输出 X、Y、W、H。我想要的是在释放鼠标时仅输出 X,Y,W,H,所以我的意思是:我需要在新的 JFrame 位置和大小最终确定后进行一些处理,而不是在调整大小过程中,我想保存最终的 X,Y,W,H。

但是现在如果我将 JFrame 从 [X=100,Y=200] 移动到 [X=150,Y=200],它将保存 50 次,因为在移动过程中,X 值从 100 更改为 150 ,所以每次改变X都会保存,这是不必要的,我只想保存鼠标释放后的最终结果[ X=150,Y=200 ],如何实现?

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

public class MouseMotionEventDemo extends JPanel
{
  static JFrame frame=new JFrame();
  
  public MouseMotionEventDemo()
  {
    setPreferredSize(new Dimension(500,300));
    
    frame.addComponentListener(new ComponentListener()
    {
      public void componentResized(ComponentEvent e) { saveXYWH(frame); }
      public void componentMoved(ComponentEvent e) { saveXYWH(frame); }
      public void componentShown(ComponentEvent e) { }
      public void componentHidden(ComponentEvent e) { }
    });
  }
  
  void saveXYWH(JFrame frame)
  {
    System.out.println("Demo [ X = "+frame.getLocation().x+" , Y = "+frame.getLocation().y+" | W = "+frame.getSize().width+" , H = "+frame.getSize().height+" ]");
  }

  public static void main(String[] args)
  {
    javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } });
  }

  private static void createAndShowGUI()
  {
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    MouseMotionEventDemo demo=new MouseMotionEventDemo();
    frame.setContentPane(demo);
    frame.setLocationRelativeTo(null);
    frame.pack();
    frame.setVisible(true);
  }
}
java swing
1个回答
0
投票

我在这里给你一个答案,但它使用 JNativeHook,它使用 JNI:

所以这里是中心类:

package gui.windows.mousedraghelper;

import java.awt.Component;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.function.Consumer;

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.github.kwhat.jnativehook.mouse.NativeMouseEvent;
import com.github.kwhat.jnativehook.mouse.NativeMouseListener;


public class MouseDragHelper implements AutoCloseable {

    private final Consumer<ComponentEvent> mLambda;

    ComponentEvent mLastDragEvent;

    public MouseDragHelper(final Component pWindow, final Consumer<ComponentEvent> pLambda) throws NativeHookException {
        mLambda = pLambda;

        GlobalScreen.addNativeMouseListener(new NativeMouseListener() {
            @Override public void nativeMousePressed(final NativeMouseEvent pNativeMouseEvent) {
                mLastDragEvent = null;
            }
            @Override public void nativeMouseReleased(final NativeMouseEvent pNativeMouseEvent) {
                checkRaiseEvent();
            }
        });
        pWindow.addComponentListener(new ComponentAdapter() {
            @Override public void componentMoved(final ComponentEvent pE) {
                mLastDragEvent = pE;
            }
        });
        GlobalScreen.registerNativeHook();
    }

    protected void checkRaiseEvent() {
        final ComponentEvent lde = mLastDragEvent;
        if (lde != null) mLambda.accept(lde);
    }

    @Override public void close() {
        try {
            GlobalScreen.unregisterNativeHook();
        } catch (final NativeHookException e) {
            e.printStackTrace();
            /* we could actually simply ignore this */
        }
    }

}

连同外部示例(从外部控制窗口):

package gui.windows.mousedraghelper;

import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

import com.github.kwhat.jnativehook.NativeHookException;


public class Test_MouseDragHelper_External {



    static class TestFrame extends JFrame {
        private static final long serialVersionUID = -7239078731343703120L;

        public TestFrame() {
            setTitle("MouseDragHelper - External Test");
            setBounds(400, 300, 400, 300);
        }
    }



    public static void main(final String[] args) throws NativeHookException {
        final TestFrame window = new TestFrame();

        // we need this to catch the addWindowListener->WindowAdapter->windowClosed event
        // we do NOT need this when WindowConstants.EXIT_ON_CLOSE is specified
        window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        window.setVisible(true);

        @SuppressWarnings("resource") final MouseDragHelper mdh = new MouseDragHelper(window, e -> handleWindowDragDone(e));
        window.addWindowListener(new WindowAdapter() {
            @Override public void windowClosed(final WindowEvent pE) {
                mdh.close();
            }
        });

    }

    static private void handleWindowDragDone(final ComponentEvent pE) {
        System.out.println("The window was just dragged and released: " + pE);
    }



}

以及内部示例(从内部控制窗口,您可能会在代码中使用它):

package gui.windows.mousedraghelper;

import java.awt.event.ComponentEvent;

import javax.swing.JFrame;

import com.github.kwhat.jnativehook.NativeHookException;


public class Test_MouseDragHelper_Internal {



    static class TestFrame extends JFrame {
        private static final long serialVersionUID = 3161758860296277990L;

        private final MouseDragHelper mMouseDragHelper;

        public TestFrame() throws NativeHookException {
            mMouseDragHelper = new MouseDragHelper(this, e -> dragDone(e));
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            setTitle("MouseDragHelper - Internal Test");
            setBounds(400, 300, 400, 300);
        }

        @Override public void dispose() {
            mMouseDragHelper.close();
            super.dispose();
        }

        @SuppressWarnings("static-method") private void dragDone(final ComponentEvent pE) {
            System.out.println("MouseDragHelper.TestFrame.dragDone() " + pE);
        }
    }



    public static void main(final String[] args) throws NativeHookException {
        final TestFrame window = new TestFrame();
        window.setVisible(true);
    }



}

在内部和外部示例中,我都确保再次取消注册本机挂钩,因为该库使用的线程不是守护线程。所以 JVM 不会自行关闭,除非你使用

System.exit()
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
,但这相当不干净。

© www.soinside.com 2019 - 2024. All rights reserved.