简体   繁体   English

如何更改焦点JComboBox的突出显示颜色

[英]How can I change the highlight color of a focused JComboBox

Let me first explain what I'm looking to achieve. 首先让我解释一下我要实现的目标。 I'm creating a data entry form in Swing, made up of a number of JComboBoxes & JTextFields. 我正在Swing中创建一个数据输入表单,该表单由许多JComboBoxes和JTextField组成。 A validation routine iterates over those components and determines if the values specified for each control are 'valid' (the details of the validation are irrelevant for the purposes of this example). 验证例程对那些组件进行迭代,并确定为每个控件指定的值是否为“有效”(就本示例而言,验证的细节无关紧要)。

When the routine identifies that a component contains an invalid value, I want to change the background color of that field, and also the foreground/text color of that field - to make it clear to the user that there is a problem with that field. 当例程识别出一个组件包含无效值时,我想更改该字段的背景颜色,以及该字段的前景色/文本颜色,以使用户清楚该字段存在问题。

Where a field is deemed 'valid', I want to set the background of the control to be white - and the foreground/text to be black. 在某个字段被视为“有效”的情况下,我想将控件的背景设置为白色-并将前景/文本设置为黑色。

All pretty straightforward so far, and all achievable within the attached demo code below. 到目前为止,所有操作都非常简单明了,并且都可以在下面的附加演示代码中实现。

When a Combo Box contains a valid value, and is focused - the background of the editor within the combo is set to a bluish color, which I'm perfectly happy with. 当组合框包含有效值并被聚焦时,组合框中的编辑器背景将设置为蓝色,我对此非常满意。

However, what I'm trying to achieve is to change the color that is used to highlight a focused combo box when that combo box contains an invalid value. 但是,我要实现的是更改当组合框包含无效值时用于突出显示焦点组合框的颜色。 Despite having changed the background color of the combo box to be pink, if the control is focused, it still uses the blue color to indicate that it is focused. 尽管已将组合框的背景颜色更改为粉红色,但是如果控件已聚焦,则它仍使用蓝色来表示它已聚焦。

Example of invalid field that is focused: http://postimg.org/image/ne9xgjch3/ 重点关注的无效字段示例: http : //postimg.org/image/ne9xgjch3/

Though I appreciate that this is perfectly normal behaviour, what I would like to do, is change the color that is used to highlight one of the 'invalid' fields to a darker shade of the color that a non-focused & invalid control would have - so that the user can still see which control is focused, and it still be pink all over. 尽管我很欣赏这是完全正常的行为,但我想做的是将用于突出显示“无效”字段之一的颜色更改为较暗的阴影,使非集中和无效控件具有该颜色-这样,用户仍可以看到焦点对准哪个控件,并且整个控件仍为粉红色。 I appreciate that this might seem petty, but my end user is insistant that the whole field remains pink (or rather, a different shade of pink) when focused. 我很欣赏这看似微不足道,但是我的最终用户坚持认为,整个领域在聚焦时仍保持粉红色(或更确切地说,是另一种粉红色的阴影)。 This is what my eutopia, a focused and 'invalid' field, would look like: 这就是我的理想国(一个专注且“无效”的领域)的样子:

http://postimg.org/image/9793bqcfj/ http://postimg.org/image/9793bqcfj/

I've tried extending the DefaultListCellRenderer & BasicComboBoxEditor classes, and setting those against the combo box as the renderer and editor respectively. 我试过扩展DefaultListCellRenderer和BasicComboBoxEditor类,并将它们分别针对组合框设置为渲染器和编辑器。 I was under the impression that the Editor would be where I needed to focus my attentions, so within the getEditorComponent method of the class, I would return a label with an appropriate background and foreground - however from within that method, I have no way of knowing whether or not the control has focus, so have no way of determining how I should format the returned label. 我的印象是编辑器将是我需要集中精力的地方,因此在类的getEditorComponent方法中,我将返回带有适当背景和前景的标签-但是,从该方法中,我无法知道控件是否具有焦点,因此无法确定如何格式化返回的标签。 Additionally, as soon as I started setting an Editor against the combobox, I seemed to lose the ability to focus the control at all - though that may have been my lack of knowledge on how to implement the editor. 此外,一旦我开始对组合框设置编辑器,我似乎就根本失去了集中控件的能力-尽管这可能是我缺乏如何实现编辑器的知识。

I've been reading about the BasicComboBoxUI too, but nothing I've come across has stood out as the solution. 我也一直在阅读有关BasicComboBoxUI的信息,但我遇到的任何解决方案都脱颖而出。

Please can someone kindly point me in the right direction, I've spent days tinkering with this, and it's really starting to bug me. 请有人帮我指出正确的方向,我花了好几天的时间对此进行修补,这真的开始困扰我。 Please excuse the netbeans generated demo code, it was just to allow me to knock together a demo quickly. 请原谅netbeans生成的演示代码,这只是为了让我快速完成演示。

package com.test;

import java.awt.*;

public class TestForm extends javax.swing.JFrame {

    public TestForm()
    {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        cboOne = new javax.swing.JComboBox();
        txtOne = new javax.swing.JTextField();
        txtTwo = new javax.swing.JTextField();
        btnValidate = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        cboOne.setBackground(new java.awt.Color(255, 255, 255));
        cboOne.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Valid Value", "Invalid Value", "Another Invalid Value" }));

        txtOne.setText("123");

        txtTwo.setText("123");

        btnValidate.setText("Validate");
        btnValidate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnValidateActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(cboOne, 0, 376, Short.MAX_VALUE)
                    .addComponent(txtOne)
                    .addComponent(txtTwo)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(btnValidate)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(cboOne, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtOne, javax.swing.GroupLayout.PREFERRED_SIZE, 51, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(txtTwo, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(btnValidate)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btnValidateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnValidateActionPerformed

        //Check if the selection in the ComboBox is valid...
        if (((String)cboOne.getSelectedItem()).equals("Valid Value"))
        {
            //Selected Value is Valid.
            //We want the combo box to appear with a white background
            //and black text.
            cboOne.setBackground(Color.white);
            cboOne.setForeground(Color.black);
        }
        else
        {
            //The value specified is invalid.
            //We want to highlight the field in pink to identify an issue,
            //and change the color of the text to red too:
            cboOne.setBackground(Color.pink);
            cboOne.setForeground(Color.red);
        }

        //Check if the value entered into the first Text Field is valid...
        if (txtOne.getText().equals("123"))
        {
            //Selected Value is Valid.
            //We want the text box to appear with a white background
            //and black text.            
            txtOne.setBackground(Color.white);
            txtOne.setForeground(Color.black);
        }
        else
        {
            //Selected Value is invalid.
            //We want the text box to appear with a pink background
            //and red text. 
            txtOne.setBackground(Color.pink);
            txtOne.setForeground(Color.red);
        }

        //Check if the value entered into the second Text Field is valid...
        if (txtTwo.getText().equals("123"))
        {
            //Selected Value is Valid.
            //We want the text box to appear with a white background
            //and black text. 
            txtTwo.setBackground(Color.white);
            txtTwo.setForeground(Color.black);
        }
        else
        {
            //Selected Value is invalid.
            //We want the text box to appear with a pink background
            //and red text. 
            txtTwo.setBackground(Color.pink);
            txtTwo.setForeground(Color.red);
        }

    }//GEN-LAST:event_btnValidateActionPerformed

    public static void main(String args[]) {


        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestForm().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnValidate;
    private javax.swing.JComboBox cboOne;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JComboBox jComboBox2;
    private javax.swing.JTextField txtOne;
    private javax.swing.JTextField txtTwo;
    // End of variables declaration//GEN-END:variables
}

Update 更新资料

Forget to mention. 忘了提。 The reason you're having problems with the coloring of your combobox is because the color you are seeing is the selection color. 您在组合框的颜色方面遇到问题的原因是,您看到的颜色是选择颜色。 The color is defined within the look and feel defaults, there is no way to change these colors for a single component without writing your own look and feel delegate, which I, personally wouldn't 颜色是在外观默认设置中定义的,如果没有编写自己的外观委托,则无法更改单个组件的这些颜色,我个人不会这样

This is an example of providing highlighting to invalid fields using JXLayer (now JLayer , but I've not had the time to convert it), while this example does use the InputVerifer API, there is no reason it has to, it's just used for part of the example. 这是一个使用JXLayer (现在为JLayer ,但我没有时间转换它)为无效字段提供突出显示的示例,尽管该示例确实使用了InputVerifer API,但没有JLayer ,它仅用于示例的一部分。 It would be quite easy to do post validation highlighting as well, the focus is on the highlighting functionality - not the method of validation ;). 验证后突出显示也很容易,重点是突出显示功能-而不是验证方法;)。

This is based on the idea presented by Kirill Grouchnikov on his Pushing Pixels blog, Validation overlays using JXLayer 这是基于Kirill Grouchnikov在他的Pushing Pixels博客上提出的想法,即使用JXLayer进行验证叠加

This is a prototype of an idea I did some time ago, the code still needs some tweaking to improve performance, but is otherwise quite functional...I'd prefer better in built support for real time validation...but that's just me ;) 这是我前一段时间做过的一个想法的原型,代码仍然需要进行一些调整以提高性能,但在其他方面还是很有功能的……我希望更好地构建对实时验证的支持……但这就是我;)

突出

Main test class... 主要考试班...

import com.jhlabs.image.GaussianFilter;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import javax.swing.InputVerifier;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;

public class FormValidationExample {

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

    public FormValidationExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JXLayer<JPanel> layer;

        private javax.swing.JComboBox cboOne;
        private javax.swing.JTextField txtOne;
        private javax.swing.JTextField txtTwo;

        private DefaultValidationHighlightModel validationModel;
        private boolean ignoreValidationRequest;

        public TestPane() {
            setLayout(new BorderLayout());
            JPanel content = new JPanel(new GridBagLayout());

            ValidationUI ui = new ValidationUI();
            validationModel = new DefaultValidationHighlightModel(ui);

            layer = new JXLayer<>(content, ui);
            add(layer);

            cboOne = new javax.swing.JComboBox();
            cboOne.setInputVerifier(new AbstractValidationInputVerifier(validationModel) {
                @Override
                public boolean verify(JComponent input) {
                    boolean valid = false;
                    JComboBox cb = (JComboBox) input;
                    String textOfOne = txtOne.getText();
                    String textOfTwo = txtTwo.getText();
                    if (cb.getSelectedIndex() == 2) {
                        valid = true;
                    } else if (cb.getSelectedIndex() == 0
                            && "123".equals(textOfOne)
                            && "456".equals(textOfTwo)) {
                        valid = true;
                    } else if (cb.getSelectedIndex() == 1
                            && "456".equals(textOfOne)
                            && "789".equals(textOfTwo)) {
                        valid = true;
                    }
                    return valid;
                }
            });
            txtOne = new javax.swing.JTextField("123", 10);
            txtOne.setInputVerifier(new AbstractValidationInputVerifier(validationModel) {
                @Override
                public boolean verify(JComponent input) {
                    JTextField field = (JTextField) input;
                    String text = field.getText();
                    return "123".equals(text) || "456".equals(text);
                }
            });
            txtTwo = new javax.swing.JTextField("123", 10);
            txtTwo.setInputVerifier(new AbstractValidationInputVerifier(validationModel) {
                @Override
                public boolean verify(JComponent input) {
                    JTextField field = (JTextField) input;
                    String text = field.getText();
                    return "456".equals(text) || "789".equals(text);
                }
            });

            cboOne.setModel(new javax.swing.DefaultComboBoxModel(new String[]{"Only works with 123, 456", "Only works with 456, 789", "Works with everybody"}));

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.fill = GridBagConstraints.HORIZONTAL;
            gbc.insets = new Insets(4, 4, 4, 4);

            content.add(cboOne, gbc);
            content.add(txtOne, gbc);
            content.add(txtTwo, gbc);

            validateFields();

        }

        protected void validateFields() {
            if (!ignoreValidationRequest) {
                ignoreValidationRequest = true;
                try {
                    cboOne.getInputVerifier().shouldYieldFocus(cboOne);
                    txtOne.getInputVerifier().shouldYieldFocus(txtOne);
                    txtTwo.getInputVerifier().shouldYieldFocus(txtTwo);
                } finally {
                    ignoreValidationRequest = false;
                }
            }
        }

        public abstract class AbstractValidationInputVerifier extends InputVerifier {

            private IValidationHighlightModel model;

            public AbstractValidationInputVerifier(IValidationHighlightModel model) {
                this.model = model;
            }

            public IValidationHighlightModel getModel() {
                return model;
            }

            @Override
            public boolean shouldYieldFocus(JComponent input) {
                if (verify(input)) {
                    getModel().removeInvalidField(input);
                } else {
                    getModel().addInvalidField(input);
                }
                validateFields();
                return true;
            }

        }

    }
}

JXLayer related, highlight UI layers... JXLayer相关,突出显示UI层...

public class ValidationUI extends HighlightComponentUI {

    public ValidationUI() {
        super(Color.RED);
    }

}

public class HighlightComponentUI extends AbstractLayerUI<JPanel> {

    private List<WeakReference<Component>> lstHighlights;
    private Color highlightColor;

    public HighlightComponentUI(Color highlight) {
        highlightColor = highlight;
        lstHighlights = new ArrayList<WeakReference<Component>>(25);
    }

    protected void cleanReferences() {
        if (lstHighlights.size() > 0) {
            List<WeakReference<Component>> removed = new ArrayList<WeakReference<Component>>(lstHighlights.size());
            for (WeakReference<Component> wr : lstHighlights) {
                Component weak = wr.get();
                if (weak == null) {
                    removed.add(wr);
                }
            }
            lstHighlights.removeAll(removed);
            setDirty(true);
        }
    }

    protected boolean contains(Component comp) {
        boolean contains = false;
        cleanReferences();
        for (WeakReference<Component> wr : lstHighlights) {
            Component weak = wr.get();
            if (weak.equals(comp)) {
                contains = true;
                break;
            }
        }
        return contains;
    }

    protected void clearHighlights() {
        lstHighlights.clear();
        setDirty(true);
    }

    protected void addHighlight(Component comp) {
        if (comp != null) {
            if (!contains(comp)) {
                lstHighlights.add(new WeakReference<Component>(comp));
                setDirty(true);
            }
        }
    }

    public Component[] getHighlightedComponents() {
        List<Component> comps = new ArrayList<>(lstHighlights.size());
        for (WeakReference<Component> wr : lstHighlights) {
            Component comp = wr.get();
            if (comp != null) {
                comps.add(comp);
            }
        }
        return comps.toArray(new Component[comps.size()]);
    }

    protected void removeHighlight(Component comp) {
        cleanReferences();
        WeakReference<Component> toRemove = null;
        for (WeakReference<Component> wr : lstHighlights) {
            Component weak = wr.get();
            if (weak.equals(comp)) {
                toRemove = wr;
                break;
            }
        }
        if (toRemove != null) {
            lstHighlights.remove(toRemove);
            setDirty(true);
        }
    }

    public Color getHighlight() {
        return highlightColor;
    }

    /**
     * Does a recursive search of all the child components of the supplied
     * parent looking for the supplied child
     *
     * @param parent
     * @param child
     * @return true if the child resides within the parent's hierarchy,
     * otherwise false
     */
    public boolean contains(Container parent, Component child) {

        boolean contains = false;
        if (child.getParent() != null) {
            if (child.getParent().equals(parent)) {
                contains = true;
            } else {
                for (Component comp : parent.getComponents()) {
                    if (comp instanceof Container) {
                        if (contains((Container) comp, child)) {
                            contains = true;
                            break;
                        }
                    }
                }
            }
        }

        return contains;
    }

    @Override
    protected void paintLayer(Graphics2D g2, JXLayer<? extends JPanel> l) {
        super.paintLayer(g2, l);
        Graphics2D c = (Graphics2D) g2.create();
        JComponent view = l.getView();
        while (view instanceof JXLayer) {
            view = (JComponent) ((JXLayer) view).getView();
        }
        for (WeakReference<Component> wr : lstHighlights) {

            Component comp = wr.get();
            if (comp != null && contains(view, comp)) {

                // A cache here would be VERY useful, would need to be mainatined
                // against the component instance as well as the component
                // size properties...
                BufferedImage img = new BufferedImage(comp.getWidth(), comp.getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = img.createGraphics();
                g2d.setComposite(AlphaComposite.Clear);
                g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
                g2d.setComposite(AlphaComposite.SrcOver);
                comp.printAll(g2d);
                g2d.dispose();

                BufferedImage glow = GlowEffectFactory.generateGlow(img, 8, getHighlight(), 0.75f);

                Point point = comp.getLocation();
                point = SwingUtilities.convertPoint(comp.getParent(), point, view);

                int x = point.x - ((glow.getWidth() - comp.getWidth()) / 2);
                int y = point.y - ((glow.getHeight() - comp.getHeight()) / 2);
                c.drawImage(glow, x, y, l);

            }
        }
        c.dispose();
    }
}

Validation model related class (I like to use interfaces and abstract implementations to provide flexibility to the API and reduce the coupling where I can). 与验证模型相关的类(我喜欢使用interfacesabstract实现来为API提供灵活性并在可能的地方减少耦合)。 My original prototype had the UI layer and model separated and updated via the ChangeListener support, but I combined them here for simplicity... 我的原始原型通过ChangeListener支持分离并更新了UI层和模型,但是为了简单起见,在这里将它们组合在一起...

public class DefaultValidationHighlightModel extends AbstractValidationHighlightModel {

    private HighlightComponentUI ui;

    public DefaultValidationHighlightModel(HighlightComponentUI ui) {
        this.ui = ui;
    }

    @Override
    public void addInvalidField(Component comp) {
        if (!ui.contains(comp)) {
            ui.addHighlight(comp);
            fireStateChanged();
        }
    }

    @Override
    public void removeInvalidField(Component comp) {
        if (ui.contains(comp)) {
            ui.removeHighlight(comp);
            fireStateChanged();
        }
    }

    @Override
    public Component[] getInvalidFields() {
        return ui.getHighlightedComponents();
    }

}

public abstract class AbstractValidationHighlightModel implements IValidationHighlightModel {

    private EventListenerList listenerList;

    public EventListenerList getListenerList() {

        if (listenerList == null) {

            listenerList = new EventListenerList();

        }

        return listenerList;

    }

    @Override
    public void addChangeListener(ChangeListener listener) {

        getListenerList().add(ChangeListener.class, listener);

    }

    @Override
    public void removeChangeListener(ChangeListener listener) {

        getListenerList().remove(ChangeListener.class, listener);

    }

    protected ChangeListener[] getChangeListeners() {

        return getListenerList().getListeners(ChangeListener.class);

    }

    protected void fireStateChanged() {

        ChangeListener[] listeners = getChangeListeners();
        if (listeners != null && listeners.length > 0) {

            ChangeEvent evt = new ChangeEvent(this);
            for (ChangeListener listener : listeners) {

                listener.stateChanged(evt);

            }

        }

    }

}

public interface IValidationHighlightModel {
    public void addInvalidField(Component comp);
    public void removeInvalidField(Component comp);
    public Component[] getInvalidFields();
    public void addChangeListener(ChangeListener listener);
    public void removeChangeListener(ChangeListener listener);
}


public static class GlowEffectFactory {

    public static BufferedImage createCompatibleImage(int width, int height) {

        return createCompatibleImage(width, height, Transparency.TRANSLUCENT);

    }

    public static BufferedImage createCompatibleImage(Dimension size) {

        return createCompatibleImage(size.width, size.height);

    }

    public static BufferedImage createCompatibleImage(int width, int height, int transparency) {

        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();

        BufferedImage image = gc.createCompatibleImage(width, height, transparency);
        image.coerceData(true);
        return image;

    }

    public static BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {

        BufferedImage maskedImage = null;
        if (sourceImage != null) {

            int width = maskImage.getWidth(null);
            int height = maskImage.getHeight(null);

            maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D mg = maskedImage.createGraphics();

            int x = (width - sourceImage.getWidth(null)) / 2;
            int y = (height - sourceImage.getHeight(null)) / 2;

            mg.drawImage(sourceImage, x, y, null);
            mg.setComposite(AlphaComposite.getInstance(method));

            mg.drawImage(maskImage, 0, 0, null);

            mg.dispose();

        }

        return maskedImage;

    }

    public static BufferedImage generateBlur(BufferedImage imgSource, int size, Color color, float alpha) {

        GaussianFilter filter = new GaussianFilter(size);

        int imgWidth = imgSource.getWidth();
        int imgHeight = imgSource.getHeight();

        BufferedImage imgBlur = createCompatibleImage(imgWidth, imgHeight);
        Graphics2D g2 = imgBlur.createGraphics();

        g2.drawImage(imgSource, 0, 0, null);
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha));
        g2.setColor(color);

        g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight());
        g2.dispose();

        imgBlur = filter.filter(imgBlur, null);

        return imgBlur;

    }

    public static BufferedImage generateBlur(BufferedImage imgSource, int size) {

        GaussianFilter filter = new GaussianFilter(size);

        int imgWidth = imgSource.getWidth();
        int imgHeight = imgSource.getHeight();

        BufferedImage imgBlur = createCompatibleImage(imgWidth, imgHeight);
        Graphics2D g2 = imgBlur.createGraphics();

        g2.drawImage(imgSource, 0, 0, null);
        g2.dispose();

        imgBlur = filter.filter(imgBlur, null);

        return imgBlur;

    }

    public static BufferedImage generateGlow(BufferedImage imgSource, int size, Color color, float alpha) {

        int imgWidth = imgSource.getWidth() + (size * 2);
        int imgHeight = imgSource.getHeight() + (size * 2);

        BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight);
        Graphics2D g2 = imgMask.createGraphics();

        int x = Math.round((imgWidth - imgSource.getWidth()) / 2f);
        int y = Math.round((imgHeight - imgSource.getHeight()) / 2f);
        g2.drawImage(imgSource, x, y, null);
        g2.dispose();

        // ---- Blur here ---
        BufferedImage imgGlow = generateBlur(imgMask, size, color, alpha);

        // ---- Blur here ----
        imgGlow = applyMask(imgGlow, imgMask, AlphaComposite.DST_OUT);

        return imgGlow;

    }

}

Caveats 注意事项

This requires JXLayer (I was using version 3) (which no longer seem to be available on the net...) and SwingX (I was using version 1.6.4) 这需要JXLayer (我正在使用版本3)(似乎在网络上不再可用...)和SwingX (我正在使用版本1.6.4)

I've put all the source code of JXLayer (version 3) and Piet's examples into a single zip and I would suggest, if you are interested, you grab a copy and store it some where safe. 我已经将JXLayer(第3版)的所有源代码和Piet的示例放在一个单独的zip中 ,我建议,如果您有兴趣,可以抓取一份副本并将其存储在安全的地方。

You will also need JHLabs filters 您还将需要JHLabs过滤器

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM