【问题标题】:What do I need to do to replicate this component with gradient paint?我需要做什么才能用渐变色复制这个组件?
【发布时间】:2013-01-31 15:39:03
【问题描述】:

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

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

与这个组件相比,我的尝试变成了非常平坦的黑色。它还具有 JFrame 选项(关闭、最小化等),并且对组件没有“圆形”外观。我正在寻找可以改善我所拥有的并解释我哪里出错的人。我知道我可以简单地使用已经制作的外观和感觉,但我想让我的示例项目尽可能接近图像中的 BitDefender GUI,不包括文本。 (如果需要我可以提供代码)

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

我还想指出,在 3 TopPanels 上将插图设置为 gbc.insets = new Insets(2,10,2,10); 使其看起来更接近 BitDefender GUI 的间距。 (我只是暂时没有时间上传图片。所以我保留了代码,但我确实意识到它可以更新到上面的插图。

编辑 - 更新了更多来源

这是我的代码/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。

【问题讨论】:

  • 如果需要我可以提供代码请发布。
  • @GuillaumePolet 我用我的paintComponent()编辑了它
  • 为了尽快获得更好的帮助,请发布 SSCCE。通过将渐变绘制到“BufferedImage”,可以更轻松地对渐变是否符合预期进行排序。
  • 无法真正识别颜色分量 19 和 27 之间的差异,“黑色”从 0 到 80(恕我直言)。试试 19 和 90。
  • @JoopEggen 感谢您提供的信息,对于最外层的面板而言,50 似乎相对接近。 75 似乎接近中间面板。不过,我仍然对线条边框有疑问。对那条线边界有什么建议吗?我的假设是它是一个深灰色的 1px 线条边框。

标签: java swing graphics gradient paintcomponent


【解决方案1】:

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

注意事项:

  1. 据我所知,线条边框颜色为 74、74、74。我使用了圆形边框,但它的半径比原始示例中显示的要小。
  2. 顶部颜色由代码中定义的offset 加亮(主要是为了让我看到有所不同!)将其减小到 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

我的第一个示例中的边框与所需屏幕截图中的边框仍然相去甚远。在this answer 中,我创建了一个带有更多圆角的自定义边框(“语音气泡”)。

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

更多讨论请见Border with rounded corners & transparency

【讨论】:

  • 哇,你做得很好!我实际上比 BitDefender 版本更喜欢你的实现。我唯一要改变的就是将 JFrame 设置为未装饰并舍入框架,您甚至不遗余力地得到答案!我会检查这个问题以及您链接到的问题。 (mKorbel 对链接的回复已经消失,所以我没有看到)。非常感谢:)
  • 抱歉第二条消息,但我有几个问题(我可以在您回答完后删除):1.您选择@有什么具体原因987654330@ 超过GridBag2. 为什么是JOptionPane 而不是JFrame?我的假设只是这只是一个例子,但如果有其他原因,我很想听听。
  • 1) “为什么是BoxLayout?” 懒惰。我从来没有费心正确地学习 GBL,并且可以看到这很适合 BoxLayout。 2) “为什么选择选项窗格?” 又是懒惰。在面板中拥有 GUI 后,只需一行代码即可在选项窗格中将其显示在屏幕上。 -- 两者都被 “只是这只是一个例子” 所证明;)顺便说一句 - 不需要道歉。质疑答案中使用的策略是健康的。我在评论中包含了你问题的背景。留下您的评论或删除它(您认为最好的)。
  • 哦,很高兴你喜欢这个结果。 :) 就我个人而言,BitDefender 窗口从未给我留下深刻的印象——渐变是如此微妙,我不得不编写 Java 代码来告诉我其中的区别! ;)
  • 虽然我觉得 Renat 的回答更好地回答了我的问题;我觉得您的回复让我意识到我同意您的观点,即 BitDefender GUI 并不像我想象的那么好。我实际上计划在我的项目中使用您的示例(我可能还会在它的单独部分使用 Renat 的圆形面板)。感谢安德鲁总是乐于助人!
【解决方案2】:

让我们先做一些逆向工程。在此过程中可以进行一些简化。此外,我会说还可以增强应用程序的外观,因为第一印象远不是非常积极的。

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

  • 渐变
  • 正确选择颜色
  • 圆角
  • 大纲

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

您的示例已修改,如下所示(这只是一个视觉结果):

我使用了以下颜色:

代码:

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

我用了什么

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

【讨论】:

  • 大崩溃! 题外话 您是如何将 BitDefender 面板分解成这样的?你用的是什么软件? 关于主题 我看到您使用 drawBorder 方法来获得圆角边缘,您将如何做类似于舍入 JFrame 的事情(在将其设置为未装饰之后)? - 感谢您阅读有关拟物化的有趣读物。我要检查是否可以添加另一个赏金,因为您做得很好,为我打破了这一点。 编辑它只允许我在这篇文章上开始 200 的赏金:/也许我必须为你的不同答案开始 100。
  • +1 @WilliamShatner:我认为您可以添加另一个赏金,但不能少于第一个。编辑:更多here.
  • 先生们,非常感谢,无需开始任何事情:) 这不是关于分数,而是关于有趣和有趣的答案。请查看更新后的答案以及要求的详细信息。
  • 看完这两个答案后,我觉得你的回答更直接地回答了这个问题。我计划审查你们中的一些其他答案,并对那些有帮助的答案进行投票。我曾考虑使用外观,但其中许多没有我感兴趣的“外观”。感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 2010-12-31
  • 2012-07-13
  • 2014-06-22
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
相关资源
最近更新 更多