使glassPane适合JPanel的尺寸

时间:2014-03-24 12:40:00

标签: java swing paintcomponent jcomponent glasspane

的StackOverflow!

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

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

我想以某种方式为我的JPanel配上玻璃窗,我尝试了一些不同的东西。 我试过的一件事是在JRootPane而不是JPanel上绘图,但这似乎不可能。然后我尝试从我的JPanel(它也有自己的类)中检索“MyGlassPane”类,并调用它的重绘方法,但这就是问题的起源。 最近,我已经检索了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);
        }
    }
}

这是corresponding screenshot, as a result of running this code.(由于此处缺乏活动,我无法发布直接图片)

我希望我的解释至少有点意义。我知道我的解释可能有点过于深入,无法真正解决这个问题,但我觉得有必要让你们更多地了解我的情况,以及我需要解决这个问题的原因

TL; DR: 我需要一种方法来使glassPane(从某处检索/设置)完全适合特定JPanel的尺寸,这样我就可以获得JPanel和glasspane的相同鼠标事件坐标。请参阅上面的代码以查看问题。 有一个明智的方法可以解决这个问题吗?设置RootPane玻璃板是我最后的想法......

如果有人有任何见解,请提前致谢!

Kirluu〜

1 个答案:

答案 0 :(得分:2)

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

  1. 使用JLabel代替JComponent,JComponent没有API中的任何LayoutManager,肯定也是JLabel,但它容器非常简单,就像contianer一样,是透明​​的,paintComponent中的任何东西都可以(半)透明

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

  3. JLabel可以轻松地从JPanel复制坐标,使用添加到JPanel的ComponentListener,使用来自ComponentListener的delaing(350-600)事件(每个像素一个事件),使用Swing Timer,EDIT如果调整大小继续调用timer.restart()</EDIT,如果调整大小结束,则Swing Action / ActionListener将触发放置在GlassPane中的JLabel(无论如何)的setBounds

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