Создание стеклопакета в соответствии с размерами JPanel

Переполнение стека!

Я работаю над проектом, касающимся создания навигационной системы, и мы находимся на начальных этапах, работая над рисованием карты и навигацией по ней. У нас есть функция, в которой вы сможете нарисовать квадрат поверх уже отрисованных текущих данных. Я хочу избежать повторной перерисовки всех данных для дорог с каждым событием действия mouseDragged. Для этого я обнаружил, что оптимальным выбором будет использование стеклянной панели.

Проблема повторяется с размерами стеклянной панели и координатами, которые она читает. Когда я нажимаю на определенную точку на нашей JPanel (которую мы используем для рисования), она знает, как и где правильно увеличить масштаб, но когда я рисую свой квадрат, он рисуется на определенное количество пикселей выше положения моей мыши. Похоже, это связано с тем, что размер моей стеклянной панели не соответствует размерам моего JPanel. Стеклянная панель, кажется, также покрывает мою строку меню, тогда как сама JPanel не считывает щелчки, которые появляются на панели меню.

Я хочу как-то подогнать стеклянную панель к моей JPanel, и я попробовал несколько разных вещей. Одна вещь, которую я попробовал, состояла в том, чтобы нарисовать JRootPane вместо JPanel, но это не представляется возможным. Затем я попытался просто извлечь класс "MyGlassPane" из моего JPanel (который также имеет свой собственный класс) и вызвать его метод перекраски, но именно здесь возникла проблема. Совсем недавно я получил JRootPane, который сам JPanel использует или является его частью, а затем получил стеклянную панель этого JRootPane, но кажется, что моя панель инструментов, добавленная в JFrame, также является частью этой JRootPane, что означает, что Стеклянное стекло также покрывает менубар.

Вот некоторый очень упрощенный код, который охватывает проблему, но не аспекты прослушивания мыши или рисования данных. Это, однако, демонстрирует тот факт, что раздражает то, что прямоугольник рисуется поверх меню.

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: мне нужен способ, чтобы стеклянная панель (извлеченная / установленная откуда-то) полностью соответствовала размерам конкретной JPanel, чтобы я мог получать одинаковые координаты события мыши как для JPanel, так и для стеклянной панели. Посмотрите код выше для визуализации проблемы. Есть ли умный способ сделать это? Установка стекла RootPane была моей последней идеей...

Спасибо заранее, если у кого-нибудь есть понимание, чтобы принести!

Kirluu ~

1 ответ

Не более длинный комментарий, просто предположение, основанное на неправильном / неполном коде, размещенном здесь

  1. используйте JLabel вместо JComponent, JComponent не имеет LayoutManager в API, конечно же, JLabel, но он должен быть очень простым как контейнер, как contianer, прозрачен, все в paintComponent может быть (полу) прозрачным

  2. ваш код не завершен, почему существует ItemListener, не помещайте JComponents в JComponent в качестве константы, используйте вместо этого JPanel или упоминайте, что непрозрачный JLabel - самый простой способ для GlassPane, 1-я строка кода должна быть super.paintComponent в paintComponent, dispose() - все пользовательские покраска для всего помещенного / уложенного в GlassPane

  3. JLabel может легко скопировать координаты из JPanel, использовать ComponentListener, добавленный в JPanel, с задержкой (350-600) событий из ComponentListener (одно событие на один пиксель) с помощью таймера Swing, EDIT если изменить размер, продолжайте вызывать timer.restart () </EDIT, если изменение размера завершено, то Swing Action/ActionListener будет запускать setBounds для JLabel (что угодно), помещенного в GlassPane

  4. искать простой RepaintManager (просто покрывая границы JLabels в GlassPane) для анимации в GlassPane

Другие вопросы по тегам