0

堆栈溢出!

我正在做一个关于制作导航系统的项目,我们正处于开始阶段,绘制地图并自行导航。我们有一个功能,您应该能够在已经绘制的当前数据之上绘制一个正方形。我想避免在每个 mouseDragged 动作事件中重新绘制道路的所有数据。为此,我发现使用玻璃窗格将是最佳选择。

问题在于玻璃板的尺寸和它读取的坐标。当我单击 JPanel 上的某个位置(我们用来绘制)时,它知道如何以及在何处正确放大,但是当我绘制正方形时,它会在鼠标位置上方绘制特定数量的像素。这似乎是因为我的玻璃窗格尺寸与我的 JPanel 尺寸不对应。玻璃窗格似乎也覆盖了我的菜单栏,而 JPanel 本身不会读取菜单栏上发生的点击。

我想以某种方式在我的 JPanel 上安装一个玻璃板,并且我尝试了一些不同的东西。我尝试过的一件事是绘制 JR​​ootPane 而不是 JPanel,但这似乎是不可能的。然后我试图从我的 JPanel(它也有自己的类)中检索“MyGlassPane”类,并将其称为 repaint 方法,但这就是问题的根源。最近,我检索了 JPanel 本身使用或属于其中的 JRootPane,然后检索了此 JRootPane 的玻璃窗格,但似乎我添加到 JFrame 的菜单栏也是此 JRootPane 的一部分,这意味着glasspane 也覆盖了菜单栏。

这是一些非常简化的代码,涵盖了这个问题,但不包括鼠标侦听和数据绘图方面。但是,它确实显示了在菜单栏顶部绘制矩形很烦人的事实。

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

public class TestForRootPaneStuff {
    JFrame frame = new JFrame();
    JRootPane root;
    JPanel panel = new JPanel();
    JLabel label = new JLabel("Hello there!");

    public void rootPanePls()
    {
        frame.add(panel);
        panel.add(label);

        root = panel.getRootPane();

        JMenuBar menubar = new JMenuBar();
        JMenu prettyMenu = new JMenu("Pretty");
        menubar.add(prettyMenu);
        frame.setJMenuBar(menubar);

        MyGlassPane gp = new MyGlassPane();
        root.setGlassPane(gp);

        gp.setVisible(true);
        gp.setEnabled(true);
        gp.repaint();


        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(250, 250));

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        TestForRootPaneStuff derp = new TestForRootPaneStuff();
        derp.rootPanePls();
    }

    private class MyGlassPane extends JComponent implements ItemListener
    {
        //React to change button clicks.
        @Override
        public void itemStateChanged(ItemEvent e) {
            setVisible(e.getStateChange() == ItemEvent.SELECTED);
        }

        //Draw the square for zoomToSquare
        @Override
        protected void paintComponent(Graphics g) {
            g.setColor(Color.BLUE);
            g.drawRect(10, 10, 100, 100);
        }
    }
}

这是运行此代码后的相应屏幕截图。(由于此处没有活动,我无法发布直接图片)

我希望我的解释至少有点道理。我知道我的解释对于实际解决问题可能有点过于深入,但我觉得有必要让你们更多地了解我的情况,以及我需要解决方案的原因.

TL;DR:我需要一种方法来使 glassPane(从某处检索/设置)完全适合特定 JPanel 的尺寸,以便我可以为 JPanel 和 glasspane 接收相同的鼠标事件坐标。有关问题的可视化,请参见上面的代码。有没有聪明的方法来解决这个问题?设置 RootPane 玻璃窗格是我的最终想法......

提前感谢,如果有人有任何见解的话!

基鲁~

4

1 回答 1

2

不是更长的评论,只是根据此处发布的错误/不完整代码进行猜测

  1. 使用 JLabel 代替 JComponent,JComponent 在 API 中没有任何 LayoutManager,当然也有 JLabel,但它是非常简单的容器,就像 contianer,是透明的,paintComponent 中的任何内容都可以(半)透明

  2. 你的代码不完整为什么有ItemListener,不要将JComponents作为contianer放入JComponent,而是使用JPanel,或者提到不透明的JLabel是GlassPane最简单的方法,第一行代码应该是paintComponent中的super.paintComponent,dispose()所有自定义为放置/放置在 GlassPane 中的任何东西绘画

  3. JLabel 可以很容易地从 JPanel 复制坐标,使用添加到 JPanel 的 ComponentListener,使用 Swing Timer 从 ComponentListener 延迟(350-600)事件(每一个像素一个事件),EDIT如果调整大小继续调用 timer.restart() </EDIT,如果调整大小结束,然后 Swing Action/ActionListener 将为放置在 GlassPane 中的 JLabel(无论什么)触发 setBounds

  4. 为 GlassPane 中的动画搜索简单的 RepaintManager(仅通过覆盖 GlassPane 中的 JLabels 边界)

于 2014-03-24T13:04:17.693 回答