使用渐变绘画复制此组件需要做什么?

时间:2013-02-15 15:59:02

标签: java swing graphics gradient paintcomponent

我试图复制这个组件(在帖子的底部),但我似乎无法让它看起来不错。

enter image description here

所以我想知道,我该如何复制这种渐变涂料?或者如果它不是渐变涂料,我该怎么做才能得到类似的结果?

与此组件相比,我的尝试变得非常平坦。它还有JFrame选项(关闭,最小化等),它没有组件的“圆润”外观。我正在寻找能够改善我所拥有的东西并解释我哪里出错的人。我知道我可以简单地使用已经制作的外观,但我希望我的示例项目尽可能接近除了文本的图像中的BitDefender GUI。 (如果需要,我可以提供代码)

另请注意,我跳过了Background和'Virus Shield','Auto Scan','My BitDefender'面板之间的面板。我这样做主要是因为我想让我的SSCCE尽可能小。

另外我想要注意的是,在3 gbc.insets = new Insets(2,10,2,10);上设置TopPanels的插图使其看起来更接近BitDefender GUI的间距。 (我现在没有时间上传图片。所以我按原样保留了代码,但我确实知道它可以更新为上面的插图。

enter image description here

修改 - 更新了更多来源

这是我的代码/ SSCCE(它是3个单独的类,但我将它们合并为一个.java)

package testgui;

import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class TestGui {

    public TestGui() {
        JFrame frame = new JFrame();
        MidPanel midPanel = new MidPanel();
        TopPanel topPanel1 = new TopPanel();
        TopPanel topPanel2 = new TopPanel();
        TopPanel topPanel3 = new TopPanel();
        JLabel appName = new JLabel("MyApplication");
        JLabel verNum = new JLabel("version 1.0");
        Font verFont = new Font("Tahoma", Font.BOLD, 11);
        Font nameFont = new Font("Tahoma", Font.BOLD, 14);

        GridBagConstraints gbc = new GridBagConstraints();

        appName.setForeground(Color.WHITE);
        appName.setFont(nameFont);
        verNum.setForeground(Color.WHITE);
        verNum.setFont(verFont);

        //add program name and version number
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 5, 5);
        midPanel.add(appName, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 5, 5);
        midPanel.add(verNum, gbc);

        //add 3 example top panels to midpanel
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets = new Insets(1,2,1,2);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        midPanel.add(topPanel1, gbc);

        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.insets = new Insets(1,2,1,2);
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        midPanel.add(topPanel2, gbc);

        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets = new Insets(1,2,1,2);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        midPanel.add(topPanel3, gbc);

        //add panel to push other panels to top
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.fill = GridBagConstraints.VERTICAL;
        gbc.weighty = 1.0;
        JPanel invisPanel = new JPanel();
        invisPanel.setOpaque(false);
        midPanel.add(invisPanel, gbc);

        frame.getContentPane().add(midPanel);
        frame.pack();
        frame.setVisible(true);
    }

    //test it out
    public static void main(String[] args) {
        new TestGui();
    }

    //class for the top 3 panels
    private class TopPanel extends JPanel {

        private int maxLength;
        private boolean cyclic;


        public TopPanel() {
            initComponents();
            setOpaque(false);
            cyclic = true;
            maxLength = 0;
        }

        @Override
        public void paintComponent(Graphics g) {
            if(isOpaque()) {
                super.paintComponent(g);
                return;
            }

            int width = getWidth();
            int height = getHeight();

            GradientPaint paint = null;

            Color top = new Color(50, 50, 50);
            Color btm = new Color(19, 19, 19);

            paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);

            if(paint == null) {
                throw new RuntimeException("Invalid direction specified in GamerTagPanel");
            }

            Graphics2D g2d = (Graphics2D) g;
            Paint oldPaint = g2d.getPaint();
            g2d.setPaint(paint);
            g2d.fillRect(0, 0, width, height);
            g2d.setPaint(oldPaint);
            super.paintComponent(g);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 200);  
        }

        private void initComponents() {
            GridBagConstraints gbc;
            JLabel jLabel1 = new JLabel();
            JLabel jLabel2 = new JLabel();

            setBorder(BorderFactory.createLineBorder(new Color(204,204,204)));
            setLayout(new GridBagLayout());

            jLabel1.setFont(new Font("Tahoma", Font.BOLD, 11));
            jLabel1.setForeground(new Color(255, 255, 255));
            jLabel1.setText("Scanning...");
            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.NORTHWEST;
            gbc.insets = new Insets(5, 5, 5, 5);
            add(jLabel1, gbc);

            jLabel2.setFont(new java.awt.Font("Tahoma", Font.BOLD, 11)); 
            jLabel2.setForeground(new java.awt.Color(255, 255, 255));
            jLabel2.setText("C:\\Directory\\Folder\\SubFolder\\SpecificFolder\\File.file");
            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridwidth = 2;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.anchor = GridBagConstraints.NORTHWEST;
            gbc.weightx = 1.0;
            gbc.insets = new Insets(5, 5, 5, 5);
            add(jLabel2, gbc);
        }
    }

    public class MidPanel extends JPanel {

        private int maxLength;
        private boolean cyclic;

        public MidPanel() {
            setLayout(new GridBagLayout());
            setOpaque(false);
            maxLength = 0;
            cyclic = false;
        }

        @Override
        public void paintComponent(Graphics g) {
            if(isOpaque()) {
                super.paintComponent(g);
                return;
            }

            int width = getWidth();
            int height = getHeight();

            GradientPaint paint = null;

            Color top = new Color(75, 75, 75);
            Color btm = new Color(19, 19, 19);

            paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);

            if(paint == null) {
                throw new RuntimeException("Invalid direction specified in GamerTagPanel");
            }

            Graphics2D g2d = (Graphics2D) g;
            Paint oldPaint = g2d.getPaint();
            g2d.setPaint(paint);
            g2d.fillRect(0, 0, width, height);
            g2d.setPaint(oldPaint);
            super.paintComponent(g);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 400);
        }
    }
}

感谢JoopEggen在GradientPaint上指出我的颜色问题。它帮了很多忙。我仍然在寻找一个人来组织一个更好/更近看的例子。这是我第一次以这种方式覆盖paintComponent。

2 个答案:

答案 0 :(得分:5)

让我们先做一些逆向工程。在此过程中,可以使用几种简化方式。此外,我想说也可以增强应用程序外观,因为第一印象远非积极。

enter image description here

基本上可以在该设计背后找到以下元素:

  • 梯度
  • 选择正确的颜色
  • 圆角
  • 轮廓

enter image description here

请注意,圆角,轮廓很重要。顺便说一句,一些渐变可以进行优化,以提供简洁的设计。请检查The Battle Between Flat Design And Skeuomorphism以获得更多动力。

您的示例已修改,看起来如下(它只是一个直观结果):

enter image description here

我使用了以下颜色:

enter image description here

代码:

public class TestGui {

    public TestGui() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MidPanel midPanel = new MidPanel();
        TopPanel topPanel1 = new TopPanel();
        TopPanel topPanel2 = new TopPanel();
        TopPanel topPanel3 = new TopPanel();

        JLabel appName = new JLabel("MyApplication");
        JLabel verNum = new JLabel("version 1.0");
        Font verFont = new Font("Tahoma", Font.BOLD, 11);
        Font nameFont = new Font("Tahoma", Font.BOLD, 14);

        GridBagConstraints gbc = new GridBagConstraints();

        appName.setForeground(Color.WHITE);
        appName.setFont(nameFont);
        verNum.setForeground(new Color(0xFF9f9f9f));
        verNum.setFont(verFont);

        //add program name and version number
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 5, 5);
        midPanel.add(appName, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.anchor = GridBagConstraints.WEST;
        gbc.insets = new Insets(5, 5, 5, 5);
        midPanel.add(verNum, gbc);

        //add 3 example top panels to midpanel
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets = new Insets(1,2,1,2);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        midPanel.add(topPanel1, gbc);

        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.insets = new Insets(1,2,1,2);
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        midPanel.add(topPanel2, gbc);

        gbc.gridx = 0;
        gbc.gridy = 4;
        gbc.anchor = GridBagConstraints.NORTHWEST;
        gbc.insets = new Insets(1,2,1,2);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0;
        midPanel.add(topPanel3, gbc);

        //add panel to push other panels to top
        gbc.gridx = 0;
        gbc.gridy = 5;
        gbc.fill = GridBagConstraints.VERTICAL;
        gbc.weighty = 1.0;
        JPanel invisPanel = new JPanel();
        invisPanel.setOpaque(false);
        midPanel.add(invisPanel, gbc);

        frame.getContentPane().add(midPanel);
        frame.pack();
        frame.setVisible(true);
    }

    //test it out
    public static void main(String[] args) {
        new TestGui();
    }

    //class for the top 3 panels
    private class TopPanel extends JPanel {

        private int maxLength;
        private boolean cyclic;


        public TopPanel() {
            super(true);
            initComponents();
            setOpaque(false);
            cyclic = true;
            maxLength = 0;
        }


        @Override
        public void paintComponent(Graphics g) {
            if(isOpaque()) {
                super.paintComponent(g);
                return;
            }

            int width = getWidth();
            int height = getHeight();

            GradientPaint paint = null;

            //Color top = new Color(50, 50, 50);
            //Color btm = new Color(19, 19, 19);

            Color top = new Color(0xFF222222);
            Color btm = new Color(0xFF0c0c0c);

            paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);

            if(paint == null) {
                throw new RuntimeException("Invalid direction specified in GamerTagPanel");
            }

            Graphics2D g2d = (Graphics2D) g;
            Paint oldPaint = g2d.getPaint();
            g2d.setPaint(paint);
            g2d.fillRect(0, 0, width, height);
            g2d.setPaint(oldPaint);

            super.paintComponent(g);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 200);
        }

        @Override
        public void paintBorder(Graphics g) {
            Dimension d = getSize();

            g.setColor(new Color(0xFF484848));
            g.drawRoundRect(1, 1, d.width-3, d.height-3, 10, 10);

            g.setColor(Color.BLACK);
            g.drawRoundRect(0, 0, d.width-1, d.height-1, 10, 10);
        }        

        private void initComponents() {
            GridBagConstraints gbc;
            JLabel jLabel1 = new JLabel();
            JLabel jLabel2 = new JLabel();

            setBorder(BorderFactory.createLineBorder(new Color(204,204,204)));
            setLayout(new GridBagLayout());

            jLabel1.setFont(new Font("Tahoma", Font.BOLD, 11));
            jLabel1.setForeground(new Color(255, 255, 255));
            jLabel1.setText("Scanning...");
            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.NORTHWEST;
            gbc.insets = new Insets(5, 5, 5, 5);
            add(jLabel1, gbc);

            jLabel2.setFont(new java.awt.Font("Tahoma", Font.BOLD, 11));
            jLabel2.setForeground(new Color(0xFF9f9f9f));
            jLabel2.setText("C:\\Directory\\Folder\\SubFolder\\SpecificFolder\\File.file");
            gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridwidth = 2;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.anchor = GridBagConstraints.NORTHWEST;
            gbc.weightx = 1.0;
            gbc.insets = new Insets(5, 5, 5, 5);
            add(jLabel2, gbc);
        }
    }

    public class MidPanel extends JPanel {

        private int maxLength;
        private boolean cyclic;

        public MidPanel() {
            setLayout(new GridBagLayout());
            setOpaque(false);
            maxLength = 0;
            cyclic = false;
        }


//        public void paintBorder(Graphics g) {
//            g.setColor(Color.RED);
//            Rectangle bounds = getBounds();
//            g.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 10, 10);
//        }

        @Override
        public void paintComponent(Graphics g) {
            if(isOpaque()) {
                super.paintComponent(g);
                return;
            }

            int width = getWidth();
            int height = getHeight();

            GradientPaint paint = null;

            Color top = new Color(0xFF282828);
            Color btm = new Color(0xFF0e0e0e);

            paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);

            if(paint == null) {
                throw new RuntimeException("Invalid direction specified in GamerTagPanel");
            }

            Graphics2D g2d = (Graphics2D) g;
            Paint oldPaint = g2d.getPaint();
            g2d.setPaint(paint);
            g2d.fillRect(0, 0, width, height);
            g2d.setPaint(oldPaint);
            super.paintComponent(g);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 400);
        }
    }
}

实施此用户界面的最佳方式

我认为唯一正确的方法是实现新的Look& Feel子集。看看project seaglass

enter image description here

我使用了什么

所有这些示例都是使用Inkscape - 一个开源矢量图形编辑器准备的。 您可以下载我的SVG source

答案 1 :(得分:4)

在紧要关头,这是我能想到的最好的。

GradientPanels

注意:

  1. 我可以说,线条边框的颜色是74,74,74。我使用了圆角边框,但它的半径小于原始示例中显示的半径。
  2. 顶部的颜色由代码中定义的offset增亮(大多数情况下我可以差异!)将颜色减少到0,使颜色更接近显示的颜色并制作线条更明显。
  3. 文字的颜色似乎是249,249,249(#F9F9F9),但我使用#B9B9B9作为顶部文字,白部作为其他文字。

  4. import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    
    class GradientPanels {
    
        /** An 'offset' to make gradients more obvious. 
         * Reduce to 0 for more subtle effect.  */
        static final int o = 50;
        static final Color borderColor = new Color(74,74,74);
    
        public static void main(String[] args) {
            Runnable r = new Runnable() {
    
                @Override
                public void run() {
                    JPanel gui = new JPanel(new BorderLayout());
    
                    JPanel main = new GradientPanel(o + 40, 22);
                    main.setLayout(new BorderLayout(4, 4));
                    JLabel lTop = new JLabel("<html><body><h1 style='color: #B9B9B9'>Up<br>Here");
                    main.add(lTop, BorderLayout.PAGE_START);
                    main.setBorder(new EmptyBorder(4, 4, 4, 4));
    
                    JPanel center = new GradientPanel(o + 40, 17);
                    AbstractBorder b = new CompoundBorder(
                            new LineBorder(borderColor, 1, true),
                            new EmptyBorder(6, 6, 6, 6));
                    center.setBorder(b);
                    LayoutManager lm = new BoxLayout(center, BoxLayout.Y_AXIS);
                    center.setLayout(lm);
                    main.add(center, BorderLayout.CENTER);
    
                    addPanel(center, "Virus Shield", o);
                    center.add(Box.createRigidArea(new Dimension(10, 10)));
                    addPanel(center, "Auto Scan", o);
                    center.add(Box.createRigidArea(new Dimension(10, 10)));
                    addPanel(center, "My BitDefender", o);
                    center.add(Box.createRigidArea(new Dimension(10, 50)));
    
                    gui.add(main, BorderLayout.CENTER);
    
                    JOptionPane.showMessageDialog(null, gui);
                }
            };
            // Swing GUIs should be created and updated on the EDT
            // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
            SwingUtilities.invokeLater(r);
        }
    
        public static void addPanel(JPanel p, String text, int offset) {
            JPanel t = new GradientPanel(offset + 28, 20);
            AbstractBorder b = new CompoundBorder(
                    new LineBorder(borderColor, 1, true),
                    new EmptyBorder(6, 6, 6, 6));
            t.setBorder(b);
            t.add(new JLabel("<html><body><h2 style='color: #FFFFFF'>" + text));
    
            p.add(t);
        }
    }
    
    class GradientPanel extends JPanel {
    
        Color top;
        Color btm;
    
        GradientPanel(int t, int b) {
            top = new Color(t, t, t);
            btm = new Color(b, b, b);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            GradientPaint gp = new GradientPaint(0f, 0f, top,
                    0f, (float) getHeight(), btm);
            g2.setPaint(gp);
            g2.fillRect(0, 0, getWidth(), getHeight());
        }
    }
    

    编辑1

    我的第一个例子中的边界与所需截图中的边界相差甚远。在this answer中,我创建了一个带有更圆角的自定义边框(“讲话气泡”)。

    speech bubble

    不幸的是,该示例更适用于完全透明的组件,例如JLabel。我没有时间考虑将其用于不透明组件。

    有关进一步的讨论,请参阅Border with rounded corners & transparency