【问题标题】:Showing JFrame in realtime as it changes实时显示 JFrame 的变化
【发布时间】:2013-06-21 16:11:11
【问题描述】:

所以我想要完成的是创建两个 JFrame。一个将覆盖整个屏幕,当用户单击该屏幕时,当用户单击并拖动鼠标时会显示一个新的 JFrame。用户第一次点击的地方是新 JFrame 的左上角,而用户释放鼠标的地方是 JFrame 的右下角。单击并释放鼠标时,制作两个 JFrame 并显示第二个 JFrame 没有问题。问题是我希望新的 JFrame 在用户移动鼠标时实时显示,以便在释放鼠标之前。我试过了

public void mouseDragged(MouseEvent e) {

            FrontWindow f = new FrontWindow();

            while (true) {          
                f.setBounds(Shared.xPressed, Shared.yPressed, (Utils.getXPosition() - Shared.xPressed) , (Utils.getYPosition() - Shared.yPressed));
                f.setVisible(true);
            }

        }

但这没有用。

【问题讨论】:

  • 您希望 JFrame 本身出现还是它的轮廓就足够了?
  • 欢迎来到阻塞事件调度线程的精彩世界。您的代码不仅会阻止您的应用程序处理任何新事件,还会阻止它执行任何更新/重绘
  • @MonadNewb 只要形状随着鼠标移动而变化,JFrame 的轮廓就足够了。
  • @MadProgrammer 你能解释一下我的代码有什么问题吗?
  • 这一切应该为最终用户实现什么?向我描述它,就好像我是潜在用户一样,这是我“必须具备”的应用程序功能。

标签: java swing jframe mouseevent


【解决方案1】:

不需要while循环。将生成多个 mouseDragged() 事件。

您应该在 mousePressed() 事件上创建新框架。然后当每个 mouseDragged() 事件产生时,你改变框架的大小。

当然这看起来不会很好,因为拖动不会与框架的大小同步。更好的方法是在移动鼠标时只绘制一个矩形。然后在 mouseReleased 上创建并以绘制矩形的大小显示框架。

请参阅Custom Paint Approaches 了解使用鼠标绘制矩形的基础知识。在您的情况下,您可能希望使用 Glass Pane 来处理鼠标事件和矩形的绘制。

【讨论】:

  • 我为您提供了一个工作示例。这两个示例都动态绘制矩形。在 mouseReleased 上,然后保存矩形。在您的情况下,您可以使用 Rectangle 的当前边界创建框架,而不是保存 Rectangle。看看代码,尝试一下,然后提出问题。
【解决方案2】:

mouseDragged() 事件处理程序中的while (true) 会阻塞 Swing 的事件调度程序线程 (EDT)。这意味着您的程序将不会收到任何其他事件。所以当用户第一次开始拖动鼠标时,你就开始了这个无限循环。但是操作系统无法通知您鼠标在用户拖动时继续移动,因为您已阻止它这样做。

【讨论】:

    【解决方案3】:

    Swing 是一个单线程框架。也就是说,它使用单个线程将它的所有事件分派给它的所有相关方。

    如果有任何东西阻塞了这个线程(比如一个无限的while-loop),那么这个线程就不能处理任何进入应用程序的新事件,包括重绘请求。这将使您的应用程序看起来像挂起(在您的情况下,它实际上已经挂起)。

    查看Concurrency in Swing了解更多详情。

    以下示例允许用户在窗口表面单击/拖动,它将呈现一个表示拖动过程的矩形。

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class DrawRectangle {
    
        public static void main(String[] args) {
            new DrawRectangle();
        }
    
        public DrawRectangle() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private Rectangle dragRect;
    
            public TestPane() {
    
                MouseHandler handler = new MouseHandler();
                addMouseListener(handler);
                addMouseMotionListener(handler);
    
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                if (dragRect != null) {
                    g2d.setColor(Color.DARK_GRAY);
                    g2d.draw(dragRect);
                }
                g2d.dispose();
            }
    
            public class MouseHandler extends MouseAdapter {
    
                private Point clicked;
    
                @Override
                public void mousePressed(MouseEvent e) {
                    clicked = e.getPoint();
                }
    
                @Override
                public void mouseReleased(MouseEvent e) {
                }
    
                @Override
                public void mouseDragged(MouseEvent e) {
    
                    Point p = e.getPoint();
    
                    int x = Math.min(p.x, clicked.x);
                    int y = Math.min(p.y, clicked.y);
    
                    int width = Math.max(p.x, clicked.x) - x;
                    int height = Math.max(p.y, clicked.y) - y;
    
                    dragRect = new Rectangle(x, y, width, height);
                    repaint();
    
                }
    
            }
    
        }
    }
    

    【讨论】:

    • 感谢您,也感谢其他用户提出画正方形的想法。去看看代码并将其添加到我的程序中。
    【解决方案4】:

    尝试在单独的线程中运行MouseInfo.getPointerInfo().getLocation(),使用SwingUtilities.invokeLater()

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            Point mp = MouseInfo.getPointerInfo().getLocation();
            f.setBounds(Shared.xPress, Shared.yPress, mp.x - Shared.xPress, mp.y - Shared.yPressed);
        }
    }
    

    注意invokeLater() 没有启动单独的线程。您应该创建一个新线程并在其run() 方法中调用invokeLater()

    【讨论】:

      猜你喜欢
      • 2015-05-11
      • 2011-07-15
      • 1970-01-01
      • 2022-11-02
      • 1970-01-01
      • 2012-10-15
      • 2019-12-19
      • 2013-08-07
      • 1970-01-01
      相关资源
      最近更新 更多