0

I want to create a grid of squares in my Java Swing GUI. I need to toggle their state so I'm thinking a JToggleButton is appropriate for each of the squares.

The problem that I have is that I want to partially colour each toggle button according to given percentages. e.g. if 50% and 50% I want the left half of the button to be green and the right to be red. If 25%,25%,50% I'd need 3 colours. I also need to use the button Text field so hiding that isn't allowed in the solution. Is it possible to do something like this with a JToggleButton? Is there a better element to use? Or how might I go about it?

I apologise for not posting my work so far but I can't find anything close to an example of this type of thing.

I want to end up with something like this where each square is a button. enter image description here

Steve W
  • 1,108
  • 3
  • 13
  • 35
  • You could combine multiple components and treat them as a single button. – akuzminykh Mar 09 '21 at 17:16
  • 3
    Use a custom Icon that paints itself based on the percentages passed to the Icon. – camickr Mar 09 '21 at 18:24
  • It's hard to say without knowing what you're trying to accomplish, but you can combine a JButton with a color bar. There's no point trying to make one Swing component display too much information. It leads to a confusing GUI. – Gilbert Le Blanc Mar 09 '21 at 21:05
  • I've added an image of something like what I'm trying to achieve. Hopefully this helps. Camickr, your comment sounds promising. Would you be able to show an example? I think perhaps we should be looking to extend JToggleButton class to achieve this? – Steve W Mar 10 '21 at 15:08

1 Answers1

1

You can construct a button with changeable 2-color background as required by overriding paintComponent:

import java.awt.*;
import javax.swing.*;

public class TwoColorsButton extends JButton{

    private final Color leftColor, rightColor;
    private int percentOfLeftColor;

    public TwoColorsButton(String text) {
        this(text,Color.RED, Color.GREEN, 50);
    }

    public TwoColorsButton(String text, Color leftColor,Color rightColor, int percentOfLeftColor) {
        super(text);
        this.leftColor = leftColor;
        this.rightColor = rightColor;
        this.percentOfLeftColor = percentOfLeftColor;
        //make button transparent
        setOpaque(false);
        setContentAreaFilled(false);
        setBorderPainted(false);
    }

    @Override
    protected void paintComponent(Graphics g) {
      Graphics2D g2 = (Graphics2D) g.create();
      int leftWidth = getWidth() * percentOfLeftColor/100;
      g2.setColor(leftColor);
      g2.fillRect(0, 0, leftWidth , getHeight());
      g2.setColor(rightColor);
      g2.fillRect(leftWidth, 0, getWidth() -leftWidth, getHeight());
      g2.setPaint(Color.BLACK);

      super.paintComponent(g2); //button is transparent so super paints text only
      g2.dispose();
    }

    public void setPercentOfLeftColor(int percentOfLeftColor) {
        this.percentOfLeftColor = percentOfLeftColor;
        repaint();
    }

    public int getPercentOfLeftColor() {
        return percentOfLeftColor;
    }

    public static void main(String[] args) {
        //run button test

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        JPanel topPanel = new JPanel();
        TwoColorsButton twoColorBtn = new TwoColorsButton("Some Text");
        topPanel.add(twoColorBtn);
        frame.add(topPanel, BorderLayout.PAGE_START);

        JPanel bottomPanel = new JPanel();
        JButton runTestBtn = new JButton("Run test");
        runTestBtn.addActionListener(e->{
            runTestBtn.setEnabled(false);
            new Timer(1000, e1 ->{
                int percent = twoColorBtn.getPercentOfLeftColor() +25;
                percent = percent > 100 ? 0 : percent;
                twoColorBtn.setPercentOfLeftColor(percent);
            }).start();
        });
        bottomPanel.add(runTestBtn);
        frame.add(bottomPanel, BorderLayout.PAGE_END);

        frame.pack();
        frame.setVisible(true);
    }
}

The code can easily be modified to allow 3 colors, if needed.
(Test it online here)
(See a basic 3 colors toggle button here)


enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65
  • Thanks for this. Looks great at first glance. Will it work for JToggleButton? I'll defo need the 3 colours option. I'll get back to you once I've had time to test it out in my app. – Steve W Mar 11 '21 at 16:04
  • See a basic 3 colors toggle button here : https://repl.it/@c0derrepo/TriColorToggleButton#Main.java – c0der Mar 12 '21 at 06:41
  • Is it possible to color the button rather than make it transparent and color the background? I'd prefer to keep the shape and feel of the individual buttons with their borders. – Steve W Mar 15 '21 at 15:58
  • If you make the button non transparent you'll have to start with `super.paintComponent(g2);` and then paint over it the 2 or 3 colors and the text. It would be easier to use a custom icon as @camickr proposed. – c0der Mar 16 '21 at 04:32