Dropshadow на качелях JFrame с помощью меню - PullRequest
1 голос
/ 13 октября 2019

Я пытаюсь смоделировать тень, используя недорогие прямоугольники рисования, вокруг JFrame, у которого есть строка меню, но тень отображается вокруг нижней части, исключая строку меню.

Есть идеи, как добиться эффекта на все окно?

enter image description here

package com.dropshadow;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.border.EmptyBorder;

import org.nuiton.jaxx.runtime.swing.ComponentMover;
import org.nuiton.jaxx.runtime.swing.ComponentResizer;

public class DropShadowMenu {

    public static void main(String[] args) {
        initFrame();
    }

    private static void initFrame() {
        final DropShadowTool shadow = new DropShadowTool();
        JFrame frame = new JFrame() {
            private static final long serialVersionUID = -512601712971605848L;

            @Override
            public void paint(Graphics g) {
                super.paint(g);             
                shadow.applyShadow(this, (Graphics2D) g);
            }
        };

        frame.setUndecorated(true);
        frame.setBackground(new Color(255, 255, 255, 0));
        frame.setPreferredSize(new Dimension(400, 600));

        JPanel contentPane = new JPanel() {
            private static final long serialVersionUID = -4799881378955761842L;
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                shadow.applyShadow(this, (Graphics2D) g);
            }

        };

        contentPane.setBorder(new EmptyBorder(20, 20, 20, 20));
        contentPane.setLayout(new BorderLayout());
        frame.setContentPane(contentPane);
        contentPane.setBackground(new Color(0,0,0,0));
        JPanel content = new JPanel();
        contentPane.add(content);
        JMenuBar menuBar = new JMenuBar();
        menuBar.setBorder(new EmptyBorder(0,20,0,20));
        menuBar.setBackground(new Color(255, 0, 255, 255));
        frame.setJMenuBar(menuBar);

        JPanel menuPanel = new JPanel();

        menuPanel.setBorder(BorderFactory.createLineBorder(Color.red));
        menuPanel.setLayout(new BorderLayout());
        JMenu file = new JMenu("File");
        file.setMnemonic('f');
        JMenuItem exit = new JMenuItem("Exit");
        exit.setMnemonic('x');
        exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,InputEvent.ALT_DOWN_MASK));
        menuBar.add(file);
        file.add(exit);
        exit.addActionListener(e ->
        {
            System.out.println("Exiting - Bye!");
            System.exit(0);
        } );
        JMenu menu = new JMenu("Menu 1");
        menuBar.add(menu);
        menu.add(new JMenuItem("Item 1"));
        menu.add(new JMenuItem("Item 2"));
        JMenu subMenu = new JMenu("SubMenu 1");
        subMenu.add(new JMenuItem("Item 3"));
        subMenu.add(new JMenuItem("Item 4"));
        menuBar.add(Box.createHorizontalGlue());
        JButton x = new JButton("X");
        x.setBorder(null);
        x.setBackground(new Color(0,0,0,0));
        menuBar.add(x);
        x.addActionListener(e -> System.exit(0));
        menu.add(subMenu);
        content.setLayout(new BorderLayout());
        JButton button = new JButton("bla blah");
        button.addActionListener(e->System.out.println("bla bla button"));
        content.add(button, BorderLayout.SOUTH);
        content.setBackground(new Color(255,255,255));
        JButton jx = new JButton(".   X   .");
        jx.setBackground(new Color(255,255,255));
        menuPanel.add(jx, BorderLayout.EAST);
        jx.addActionListener(e -> System.exit(0));
        ComponentMover cm = new ComponentMover();
        cm.registerComponent(frame);
        ComponentResizer cr = new ComponentResizer();
        cr.registerComponent(frame);

        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private static List<Color> colors = new ArrayList<Color>();
    static {

        for (int i=0;i<20;i++) {
            colors.add(new Color(0, 0, 0, 5*i));
        }
    }

    private static class DropShadowTool {
        private void applyShadow(Container c, Graphics2D g) {
            if(c.getName().equals("Charbel"))
            System.out.println(c);
            Insets insets = c.getInsets();
            System.out.println(insets);

            Dimension size = c.getSize();
            int x0 = 0;
            int xi = insets.left;
            int y0 = 0;
            int yi = insets.top;
            int width0 = size.width;
            int widthi = size.width - xi - insets.right;
            int height0 = size.height;
            int heighti = size.height - yi - insets.bottom;

            int last = 0;
            for (int i = 0; i < insets.left; i++) {
                last = i;
                drawLines(g, x0, y0, width0, height0, i);
            }
            drawLines(g, x0, y0, width0, height0, last);
        }

        private void drawLines(Graphics2D g, int x0, int y0, int width0, int height0, int i) {
            int x = x0 + i;
            int y = y0 + i;
            int width = width0 - i - i;
            int height = height0 - i - i;
            g.setColor(colors.get(i % colors.size()));
            g.drawRect(x, y, width, height);
        }
    }
}

1 Ответ

1 голос
/ 13 октября 2019

Я бы сказал, что ваша тень - это просто пользовательская граница и должна быть реализована как таковая.

Тогда вы сможете добавить DropShadowBorder к любому компоненту Swing, не выполняя никакого пользовательского рисования для компонента.

Тогда я бы посоветовал вам установить Border для JRootPane. Корневая панель управляет как строкой меню, так и панелью содержимого на более высоком уровне, поэтому граница должна быть вокруг обоих компонентов.

Прочтите раздел из учебного пособия по Swing на Корневая панель .

...