我需要如何使用渐变色来复制这个组件?

6

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

enter image description here

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

我的尝试与这个组件相比非常平淡黑色。而且它有JFrame选项(关闭、最小化等),并且组件看起来没有“圆角”。我正在寻找一个可以改进我已有内容并解释我哪里错了的人。我知道我可以简单地使用已经制作好的外观,但我想让我的示例项目尽可能接近BitDefender GUI中的图像,不包括文本。(如果需要,我可以提供代码)

还请注意,我跳过了背景和“病毒防护盾”、“自动扫描”、“我的BitDefender”面板之间的面板。主要是因为我想尽可能保持我的SSCCE尽可能小。

另外,我想指出,在3个上设置insets为gbc.insets = new Insets(2,10,2,10);使其看起来更接近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。


4
如果需要的话,我可以提供代码,请发布它。 - Guillaume Polet
@GuillaumePolet 我用我的 paintComponent() 进行了编辑。 - WilliamShatner
1
为了更快地获得更好的帮助,请发布一个SSCCE。通过将渐变绘制到“BufferedImage”中,是否如预期的问题可能更容易解决。 - Andrew Thompson
颜色分量19和27之间的区别实际上无法被识别,“黑色”从0到80(在我看来)。尝试使用19和90。 - Joop Eggen
@AndrewThompson 和其他所有人,我添加了我的 SSCCE 以及当前结果的图片。希望这有助于获得一些回复 :) - WilliamShatner
显示剩余3条评论
2个回答

5

首先我们来进行一些逆向工程。在这个过程中可以进行一些简化。此外,我认为还可以增强应用程序的外观,因为第一印象远非十分积极。

enter image description here

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

  • 渐变
  • 恰当选择的颜色
  • 圆角
  • 轮廓线

enter image description here

请注意,圆角和轮廓线很重要。顺便说一下,一些渐变可以进行优化,以提供干净简洁的设计。请查看扁平设计与拟物化之间的战斗获取额外的动力。
您的示例已经修改,并且看起来如下所示(这只是一个视觉结果):

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);
        }
    }
}

最佳方式实现此UI

我认为唯一正确的方法是实现新的外观和感觉子集。请查看项目海玻璃

enter image description here

我使用了什么

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


很好的分析! 离题 你是怎么把BitDefender面板拆分成那样的?你用了什么软件? 正题 我看到你覆盖了drawBorder方法以获得圆角边缘,如果我想对一个JFrame进行类似的圆角处理(在将其设置为无装饰后),该怎么做呢?--感谢您有关拟物主义的有趣阅读。我会检查一下是否可以添加另一个赏金,因为您很好地为我解释了这个问题。 编辑 它只允许我在此帖子上开始200的赏金:/也许我将不得不在其他答案上开始100的赏金给你。 - WilliamShatner
+1 @WilliamShatner:我认为你可以添加另一个赏金,但不能少于第一个。编辑:更多信息请参见此处:http://meta.stackexchange.com/questions/16065/how-does-the-bounty-system-work。 - trashgod
先生们,非常感谢,不需要开始任何事情 :) 这不是关于得分,而是有趣和有趣的答案。请查看包含所请求细节的更新答案。 - Renat Gilmanov
在阅读了这两个答案之后,我觉得你的回答更直接地回答了问题。我计划查看一些你其他的答案,并点赞那些有帮助的答案。我曾考虑过使用外观和感觉,但其中许多并没有我感兴趣的“外观”。谢谢你的回答! - WilliamShatner

4
按照我最好的理解,以下是我能提供的最佳解答。 GradientPanels 备注:
1. 根据我所知,线条边框颜色为74,74,74。我使用了圆角边框,但它的半径比原来的例子要小。
2. 顶部颜色通过代码中定义的“偏移量”进行亮度增强(主要是为了使差异更加明显!)。将其减少到0以获得更接近实际颜色的效果,并使线条更加明显。
3. 文本的颜色似乎是249,249,249(#F9F9F9),但我使用了#B9B9B9作为顶部文本的颜色,其余文本颜色则为白色。
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

我的第一个示例中的边框仍然远离所需的截图中看到的那样。在这个答案中,我创建了一个带有更圆角的自定义边框(“气泡对话框”)。

speech bubble

不幸的是,该示例仅适用于完全透明的组件,例如JLabel。我还没有时间研究如何将其适应不透明的组件。

请参阅具有圆角和透明度的边框以进行进一步讨论。


哇,你做得太棒了!我实际上比BitDefender版本更喜欢你的实现。唯一需要改变的是设置JFrame不装饰和圆形边框。你甚至为得到答案付出了额外的努力!我会关注这个问题和你链接的那个(mKorbel的回答链接已经消失了,所以我没看到)。非常感谢 :) - WilliamShatner
抱歉发第二条信息,但我有几个问题(你回答完后我可以删除这条消息):1. 为什么你选择了 BoxLayout 而不是 GridBag2. 为什么使用 JOptionPane 而不是 JFrame?我的假设只是这是一个例子,但如果有其他原因,我很想听听。 - WilliamShatner
  1. "为什么使用 BoxLayout?" 懒惰。我从来没有认真学习过 GBL,而且我觉得 BoxLayout 很适合这个场景。
  2. "为什么使用选项面板?" 再次是因为懒惰。一旦你在一个面板中有了 GUI,只需要一行代码就可以在选项面板上显示它。-- 这只是一个例子而已 ;) 顺便说一句 - 不需要道歉。质疑答案中使用的策略是很健康的。我在我的评论中包含了你的问题背景。请随意发表或删除你的评论(无论你认为哪种方式更好)。
- Andrew Thompson
哦,很高兴你喜欢结果。:)个人而言,我从未对BitDefender窗口印象深刻——渐变如此微妙,以至于我不得不编写Java代码来告诉我它们之间的区别!;) - Andrew Thompson
虽然我觉得Renat的回答更好地回答了我的问题,但我感觉你的回答让我意识到我同意你的观点,即BitDefender GUI并不像我想象的那么好。我实际上计划在我的项目中使用你的例子(我可能也会在另一个部分使用Renat的圆形面板)。感谢Andrew一直以来的帮助! - WilliamShatner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接