2

我即将开始一个 Java 项目,我实际上是在制作一个简单的 iTunes 克隆。我将使用 Swing 来制作 GUI,但我想知道以类似于 iTunes 的方式对其进行样式设置的最佳方式,而不仅仅是更改颜色/字体/边框。我已经研究过将 CSS 与 Java Swing 一起使用,但我发现的任何资源都已过时。有什么新方法可以解决这个问题吗?还是我应该研究 CSS 以外的东西?

这是我希望通过 Swing 实现的设计(至少是基础): 在此处输入图像描述

4

2 回答 2

6

Swing 没有 CSS 样式。但是,如果您使用 JavaFx2,它是 Swing 的继承者,您确实可以使用 CSS 样式。

如果您对 Swing 还不是很熟悉,我建议您考虑 JavaFX。最新的 1.7 版本的 Java 内置了 JavaFX 2.2。它支持 CSS 和媒体播放器

当然也可以在 Swing 中进行。您可以使用许多不同的方法,但为了给您一个起点,这里是我将如何创建按钮。这种方法需要 Java 7,但如果您改用 JXLayer,您也可以在以前的 Java 版本中运行它。这些按钮是 2D 绘画和​​我可以访问的一些图标的组合。只需使用您拥有的图标进行更改即可。圆圈的大小会自行调整大小,具体取决于您使用的图像。

当您单击按钮时,您将在此处发出哔声,并将相应的文本打印到控制台。一般来说,JLayer 对 Swing 应用程序的样式非常有用。

媒体播放器示例

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.net.URL;
import java.util.logging.Logger;

import javax.swing.*;
import javax.swing.plaf.LayerUI;

/**
 */
public class MediaPlayer {

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Media Clone");
                MediaController mediaController = new MediaController();
                frame.getContentPane().add(new MediaView(mediaController));
                frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                frame.setMinimumSize(new Dimension(800, 450));
                frame.setLocationRelativeTo(null); // Center
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    static class MediaView extends JPanel {

        private MediaList mediaList;
        private ButtonView buttonView;
        private MediaController controller;

        MediaView(MediaController controller) {
            this.controller = controller;
            createComponents();
            makeLayout();
        }

        public void createComponents() {
            mediaList = new MediaList();
            buttonView = new ButtonView(controller);
        }

        public void makeLayout() {
            setLayout(new BorderLayout());
            add(mediaList);
            add(new JLayer<>(buttonView, new GradientUI()), BorderLayout.NORTH);
        }
    }

    static class MediaList extends JPanel {

        private JTable mediaTable;

        MediaList() {
            createComponents();
            makeLayout();
        }

        public void createComponents() {
            String[] header = new String[]{"Song", "Artist"};
            String[][] model = new String[2][2];
            model[0][0] = "Hello";
            model[0][1] = "World";
            model[1][0] = "Goodbye";
            model[1][1] = "Sunshine";
            mediaTable = new JTable(model, header);
        }

        public void makeLayout() {
            setLayout(new BorderLayout());
            add(new JScrollPane(mediaTable));
        }
    }

    static class GradientUI extends LayerUI<JComponent> {

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            int height = c.getHeight();
            int width = c.getWidth();
            g2.setPaint(new GradientPaint(0, 0, new Color(136, 146, 155), 0, height, new Color(101, 108, 116)));
            Rectangle2D area = new Rectangle(0, 0, width, height);
            g2.fill(area);
            super.paint(g2, c);
        }
    }

    enum MediaAction {
        PLAY, NEXT, PREVIOUS
    }

    static class MediaController {

        private Toolkit toolkit = Toolkit.getDefaultToolkit();

        public void execute(MediaAction mediaAction) {
            toolkit.beep();
            System.out.println(mediaAction.name());
        }
    }

    static class ButtonView extends JPanel {

        private static Logger log = Logger.getLogger(ButtonView.class.getName());

        private JButton play;
        private JButton next;
        private JButton previous;
        private RoundButtonUI playUI;
        private ActionListener playActionListener;
        private ActionListener nextActionListener;
        private ActionListener previousActionListener;
        private MediaController controller;

        ButtonView(MediaController controller) {
            this.controller = controller;
            createComponents();
            makeLayout();
            createHandlers();
            registerHandlers();
            initComponent();
        }

        public void createComponents() {
            play = new JButton();
            next = new JButton();
            previous = new JButton();
            playUI = new RoundButtonUI();
        }

        public void createHandlers() {
            playActionListener = createMediaAction(MediaAction.PLAY);
            nextActionListener = createMediaAction(MediaAction.NEXT);
            previousActionListener = createMediaAction(MediaAction.PREVIOUS);
        }

        private ActionListener createMediaAction(final MediaAction mediaAction) {
            return new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            controller.execute(mediaAction);
                        }
                    });
                }
            };
        }

        public void registerHandlers() {
            play.addActionListener(playActionListener);
            next.addActionListener(nextActionListener);
            previous.addActionListener(previousActionListener);
        }

        public void makeLayout() {
            setLayout(new FlowLayout(FlowLayout.LEADING));
            makeButtonRound(previous, "<<", "bullet_triangle_grey_shadow.png", "bullet_triangle_grey.png");
            makeButtonRound(play, ">", "bullet_triangle_glass_grey128x128.png", "bullet_triangle_glass_grey128x128.png");
            makeButtonRound(next, ">>", "bullet_triangle_grey_shadow.png", "bullet_triangle_grey.png");
            add(new JLayer<>(previous, playUI));
            add(new JLayer<>(play, playUI));
            add(new JLayer<>(next, playUI));
        }

        public void initComponent() {
            setOpaque(false);
        }

        private void makeButtonRound(final JButton toBeRounded, String fallback, String imageNormal, String imagePressed) {
            toBeRounded.setOpaque(false);
            toBeRounded.setFocusPainted(false);
            toBeRounded.setBorderPainted(false);
            toBeRounded.setContentAreaFilled(false);
            toBeRounded.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 5));
            URL normalURL = getClass().getClassLoader().getResource(imageNormal);
            URL pressedURL = getClass().getClassLoader().getResource(imagePressed);
            if (normalURL != null || pressedURL != null) {
                final ImageIcon released = new ImageIcon(normalURL);
                final ImageIcon pressed = new ImageIcon(pressedURL);
                toBeRounded.setIcon(released);
                toBeRounded.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        toBeRounded.setIcon(pressed);
                    }

                    @Override
                    public void mouseReleased(MouseEvent e) {
                        toBeRounded.setIcon(released);
                    }
                });
            } else {
                toBeRounded.setText(fallback);
                log.severe("Missing resources: " + imageNormal + " and " + imagePressed);
            }
        }
    }

    /**
     * Shifts the image so it looks pressed down.
     * Creates a circle around the icon, that varies in size depending on the supplied icon.
     */
    static class RoundButtonUI extends LayerUI<JComponent> {

        private static final int STROKE_WIDTH = 5;

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            ButtonModel buttonModel;
            JButton b;

            if (((JLayer) c).getView() instanceof JButton) {
                b = (JButton) ((JLayer) c).getView();
                buttonModel = b.getModel();
            } else {
                super.paint(g, c);
                return;
            }

            int iconHeight = b.getIcon() != null ? b.getIcon().getIconHeight() : 60;
            int iconWidth = b.getIcon() != null ? b.getIcon().getIconWidth() : 60;

            Shape circle = new Ellipse2D.Double(STROKE_WIDTH, STROKE_WIDTH, iconHeight, iconWidth);

            g2.setPaint(new GradientPaint(5, 5, new Color(222, 224, 230), 30, 55, new Color(187, 189, 199)));
            g2.fill(circle);

            g2.setPaint(new GradientPaint(15, 0, new Color(90, 97, 105), 15, 30, new Color(132, 142, 152)));
            g2.setStroke(new BasicStroke(5));
            g2.draw(circle);

            if (buttonModel.isPressed()) {
                g2.translate(1, 1);
            }

            super.paint(g2, c);
            g2.dispose();
        }
    }
}
于 2012-11-09T00:02:50.570 回答
2

用挥杆打造你想要的外观将是一个真正的挑战。可以做到,但不能使用 CSS,也不能不做大量工作。由于 JavaFX 支持 CSS 并具有媒体播放器,因此我将研究这个新框架。你可以从这里开始。

我最近构建了一个小型 JavaFX 应用程序,并且有机会使用场景构建器,该图形工具现在与 Netbeans 集成以帮助开发人员创建 UI。当您修改 CSS 文件时,UI 会在场景构建器中更新。我们设计的实际元素与我们在 HTML 中使用的元素不同。下面是我用于我的应用程序的 CSS 文件;您可以在mathteamhosting.com查看和运行我的应用程序

请记住,如果您使用的是 32 位浏览器,则需要 32 位版本的 Java 才能将其作为小程序运行。

.root { 
    display: block;
}

.text-input {
    -fx-font-size: 18px;
    -fx-font-weight: bold;
}

.text-field {
    -fx-font-size: 18px;
    -fx-font-weight: bold;
}

.label {
    -fx-font-size: 18px;   
}

.button {
    -fx-font-size: 15px;   
    -fx-font-weight: bold;
    -fx-text-fill: black;
    -fx-background-color: linear-gradient(#0000ff, #ffeeff);
}
#note {
    -fx-font-size: 15px;  
}

#heading {
    -fx-text-fill: #000099;
    -fx-font-size: 18px;
    -fx-font-weight: bold;
}
于 2012-11-09T00:48:44.713 回答