Passing Color object between two views to be used in JButton background

廉价感情. 提交于 2019-12-14 03:26:54

问题


I am trying to make a three tab desktop app where tab1: add/del button for adding/deleting 0-20 JButtons with tab2: user selectable color (JColorChooser) and tab3 for showing the statistics such as count of buttons in tab1 and the latest color. My problem: with good hint I received here (thanks to Hovercraft Full of Eels!) I managed to add a PropertyChangeListener, and actually that color is now showable background for the panel - whereas I'd want to use it for new JButtons. Also same way it would be needed for Tab3... Better to show both the full Main and Colors.java:

package com.company;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

public class Main extends JComponent{

    public Dimension getPreferredSize() {
        return new Dimension(700, 500);
    }
    static int value = 0;

    private static void showGUI() {

        Colors colors = new Colors();  //a new instance of class (JColorchooser)

        JButton[] jbn = new JButton[20];  //Array of 20 buttons (to be added/removed 1 by 1)

        JFrame window = new JFrame("Panels JG");
        window.add(new Main());
        window.pack();
        window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        window.setLocationRelativeTo(null);
        window.setVisible(true);

            /* Creating the needed JPanels and their layouts */
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(4, 4, 10, 10));
        JPanel bottom = new JPanel();
        bottom.setLayout(new FlowLayout());
        JPanel frontPg = new JPanel(new GridLayout(2, 1 , 25, 25));
        JPanel stats = new JPanel();

        /* Need to get two panels in the first view */
        frontPg.add(panel, BorderLayout.NORTH);
        frontPg.add(bottom, BorderLayout.SOUTH);

        /* Adding tabs to JFrame   */
        JTabbedPane tabs = new JTabbedPane();
        window.add(tabs);
        tabs.addTab("Boxes", frontPg);
        tabs.addTab("Color Select", colors);
        tabs.addTab("Details", stats);

        /* Add and del button for adding and removing boxes (JButtons) in the first tab */
        JButton a = new JButton("Add");
        JButton d = new JButton("Del");

        // Alternative for placing the buttons to the right place:
        a.setBounds(300, 650, 80, 25);
        d.setBounds(400, 650, 80, 25);
        bottom.add(a);
        bottom.add(d);

        window.setVisible(true);
        a.setVisible(true);
        d.setVisible(true);

        // add a PropertyChangeListener to our Colors isntance.
        colors.addPropertyChangeListener(Colors.NEW_COLOR,
                new PropertyChangeListener() {

                    @Override
                    public void propertyChange(PropertyChangeEvent evt) {
                        Color col = (Color) evt.getNewValue();
                        panel.setBackground(col);
                        System.out.println("BGcolor = " + col);
                        //this "test" above shows it is the right 'col' needed elsewhere too
                    }
                });
        // eof listener

        JLabel label1 = new JLabel();
        JLabel label2 = new JLabel();
        JLabel label3 = new JLabel();

        a.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Click add");
                Color col = null;  //how should this Color object be initiated really...

                if (value < 20) {

                    jbn[value] = new JButton(String.valueOf(value));
                    col = Color.getColor(Colors.NEW_COLOR);
                    System.out.println("jb1 color = " + col);

                    // CAN IT BE RESIZED? YES IT CAN WHILE GENERALLY NOT RECOMMENDED...
                    Dimension d;
                    d = new Dimension(30, 50);
                    jbn[value].setMinimumSize(d);
                    d = new Dimension(100, 50);
                    jbn[value].setMaximumSize(d);
                    d = new Dimension(40, 50);
                    jbn[value].setPreferredSize(d);
                    jbn[value].setOpaque(true);
                    panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

                    //HERE IS THE PROBLEM - col is always null... It just paints w/ WHITE.
                    if(col!=null){
                        jbn[value].setBackground(col);
                        jbn[value].addActionListener(this);
                        panel.add(jbn[value]);
                        panel.setVisible(true);
                    }
                    else {
                        jbn[value].setBackground(Color.WHITE);
                        panel.add(jbn[value]);
                        panel.setVisible(true);
                    }
                    window.pack();

                    d = new Dimension(700, 500);
                    window.setSize(d);

                    value++;
                    label1.setText("        Count of boxes ");
                    label2.setText("        " + (String.valueOf(value)));
                    label3.setText("        Current Color");

                    label1.setFont(label1.getFont().deriveFont(16.0f));
                    label2.setFont(label2.getFont().deriveFont(20.0f));
                    label3.setFont(label1.getFont().deriveFont(16.0f));

                    stats.setLayout(new GridLayout(4, 1, 10, 100));
                    stats.add(label1);
                    stats.add(label2);
                    stats.add(label3);

                    // ADDING FILLRECT OR SIMILAR TO LAST TAB for showing the latest color
                    label1.repaint();
                    label2.repaint();
                    label3.repaint();
                }

                else {
                    System.out.println("Max box count reached");
                }

            }
        });


        d.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("Click del");
                //HOW TO REMOVE THE LATEST ADDED PANEL?
                value = value-1;

            }
        });
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(new Color(35, 45, 55));
        g2d.fillRect(200, 500, 35, 35);
    }

    public static void main(String[] args) {

        showGUI();
    }
}

And the latest version of Colors.java follows:

package com.company;
import java.awt.event.*;
import javax.swing.colorchooser.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

@SuppressWarnings("serial")
class Colors extends JPanel implements ChangeListener {
    public static final String NEW_COLOR = "new color";
    private JColorChooser jcc = null;
    protected JLabel title;
    private Color newColor = null;

    public Colors() {
        super(new BorderLayout());

        // Set up the banner at the top of the window
        title = new JLabel("  ", SwingConstants.CENTER);

        // Set up color chooser for setting text color
        jcc = new JColorChooser(title.getForeground());
        jcc.getSelectionModel().addChangeListener(this);
        jcc.setBorder(BorderFactory.createTitledBorder("Choose New Color"));

        AbstractColorChooserPanel[] panels=jcc.getChooserPanels();
        for(AbstractColorChooserPanel p:panels) {
            String displayName = p.getDisplayName();
            switch (displayName) {
                case "HSV":
                    jcc.removeChooserPanel(p);
                    break;
                case "HSL":
                    jcc.removeChooserPanel(p);
                    break;
                case "CMYK":
                    jcc.removeChooserPanel(p);
                    break;
                case "RGB":
                    jcc.removeChooserPanel(p);
                    break;
            }
        }

        add(jcc, BorderLayout.CENTER);
        add(title, BorderLayout.PAGE_START);
    }

    public void stateChanged(ChangeEvent e) {
        // Color newColor = jcc.getColor();
        Color oldValue = newColor;
        newColor = jcc.getColor();

        // fire a notification to the Colors JPanel's property change support
        // object. Any listeners will be notified of the color change
        firePropertyChange(NEW_COLOR, oldValue, newColor);
        title.setForeground(newColor);
    }

    public Color getNewCol() {
        System.out.println("this now =" + newColor);
        return newColor;
    }


    public static Component createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("Color Selector");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new Colors();
        return newContentPane;



    }
}

There are also comments (open questions) inline... to point out the problematic areas (for me that is!)


回答1:


Your problem in my view is less how to get color values but when to get them. Since you want the user to select a new color when a button is created, then in the creation ActionListener, why not display the color panel in a modal JDialog such as a JOptionPane and get the selection that way. For example...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class SelectButtonColor extends JPanel {
    private static final int PREF_W = 600;
    private static final int PREF_H = 400;
    private static final int COLUMNS = 4;
    private List<AbstractButton> buttonList = new ArrayList<>();
    private JPanel buttonPanel = new JPanel(new GridLayout(0, COLUMNS, 5, 5));
    private int buttonCount = 0;
    private Colors colors = new Colors();

    public SelectButtonColor() {
        JButton addButton = new JButton(new AddAction("Add"));

        JPanel southPanel = new JPanel();
        southPanel.add(addButton);

        JPanel innerBorderPanel = new JPanel(new BorderLayout());
        innerBorderPanel.add(buttonPanel, BorderLayout.PAGE_START);
        JScrollPane scrollPane = new JScrollPane(innerBorderPanel);

        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
        add(southPanel, BorderLayout.PAGE_END);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private class AddAction extends AbstractAction {
        public AddAction(String name) {
            super(name);
            int mnenonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnenonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Component parent = SelectButtonColor.this;
            Object message = colors;
            String title = "Select a Button Color";
            int optionType = JOptionPane.OK_CANCEL_OPTION;
            int response = JOptionPane.showConfirmDialog(parent, message, title, optionType);
            if (response == JOptionPane.OK_OPTION) {
                Color color = colors.getNewCol();
                String text = "" + buttonCount;
                JButton button = new JButton(text);
                button.setBackground(color);
                buttonPanel.add(button);
                buttonList.add(button);
                buttonCount++;
                buttonPanel.revalidate();
                buttonPanel.repaint();
            }
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("SelectButtonColor");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new SelectButtonColor());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

As an aside, try to use more concise code for your examples posted here as that will make it easier for all to understand and help. Also, you almost never want to override the paint method but rather the paintComponent method.



来源:https://stackoverflow.com/questions/32975232/passing-color-object-between-two-views-to-be-used-in-jbutton-background

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!