Link to home
Start Free TrialLog in
Avatar of msmolyak
msmolyak

asked on

Changing checkbox appearance

I am trying to create a tree (JTree) where each node is a checkbox (JCheckBox class) which can be in one of three states: unselected, selected along with all the children and selected along with some children. I am trying to change the color of the box to depict the third state (the box is light gray instead of white and checked) but unable to do so.

Any suggestions?
Avatar of msmolyak
msmolyak

ASKER

Edited text of question
Even experts need to ask some question sometimes eh? Hehehe.

In your tree cell renderer, check the state of the current item.
If the tree leaf is expanded, then you should set the color to
the third state.

I believe the getTreeCellRendererComponent have the following arguments:
JTree tree, Object value, boolean selected, boolean expanded, boolean leaf,
int row, boolean hasFocus.

So just check to see whether it's expanded or not and change the color accordingly

Or a more complicated way is to add a tree expansion listener, and manually
change it when a tree is expanded.





My question is actually about physically changing the color of the box. I know when to change it, I don't know how.

Sorry for the confusion.
In the tree renderer, can't you just do:

if(expanded)
      myCheckBox.setBackground(Color.white);
else if(selected)
      myCheckBox.setBackground(Color.lightGray);
else
      myCheckBox.setBackground(Color.white);

return myCheckBox;
     
That changes the background color of the entire field, but not the little box itself. I need to change the color of the box but not the rest of the field.
Oh... I see what you're saying....

I ran a coupla tests with a checkbox on a JPanel.
Here's what I came up with:

background color of checkbox is the entire selection's color
foreground color is the color of the text.

Sorry, after reviewing the release notes, I don't see how you can just
change the color of the box itself. Unless you want to write a custom
checkbox of your own....
No, I'd rather not rewrite a checkbox. Thanks for trying.
BTW, when you click on checkbox the color of the little box does change (to light gray) while you are holding your mouse down. That is the effect I am trying to achieve.
Yeah I see it too. I'm wondering if it's done with their
custom paint look and feel.
ASKER CERTIFIED SOLUTION
Avatar of diakov
diakov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Spasibo za pomosch', Nikolai.

I ended up stealing the code from WindowsIconFactory class where checkbox icon gets generated. I modified this code slightly to take a new state into account. And in the renderer I do set up new icon as

new FolderCheckBoxIcon()

    private class FolderCheckBoxIcon implements Icon, Serializable
    {
        FolderTreeNode node;

        FolderCheckBoxIcon(FolderTreeNode node)
        {
            this.node = node;
        }

          final int csize = 13;
          public void paintIcon(Component c, Graphics g, int x, int y)
          {
              AbstractButton b = (AbstractButton) c;
              ButtonModel model = b.getModel();

              // outer bevel
              g.setColor(BasicGraphicsUtils.control);
              g.fill3DRect(x, y, csize, csize, false);

              // inner bevel
              g.setColor(BasicGraphicsUtils.controlShadow);
              g.fill3DRect(x+1, y+1, csize-2, csize-2, false);

                // inside box
              if((model.isPressed() && model.isArmed()) || !model.isEnabled() || node.getState() == node.SOME_SELECTED)  // ******This is the line I modified
              {
                    g.setColor(BasicGraphicsUtils.control);
              }
              else
              {
                    g.setColor(BasicGraphicsUtils.controlWhite);
              }
              g.fillRect(x+2, y+2, csize-4, csize-4);

              if(model.isEnabled()) {
                g.setColor(BasicGraphicsUtils.controlBlack);
              } else {
                g.setColor(BasicGraphicsUtils.controlShadow);
              }

              // paint check
              if (model.isSelected()) {
                g.drawLine(x+9, y+3, x+9, y+3);
                g.drawLine(x+8, y+4, x+9, y+4);
                g.drawLine(x+7, y+5, x+9, y+5);
                g.drawLine(x+6, y+6, x+8, y+6);
                g.drawLine(x+3, y+7, x+7, y+7);
                g.drawLine(x+4, y+8, x+6, y+8);
                g.drawLine(x+5, y+9, x+5, y+9);
                g.drawLine(x+3, y+5, x+3, y+5);
                g.drawLine(x+3, y+6, x+4, y+6);
              }
          }

          public int getIconWidth()
          {
              return csize;
          }

          public int getIconHeight()
          {
              return csize;
          }
    }

The problem now is that I lost the tree icon (open/closed folder or leaf symbol). Any idea how can I get those back?
Hi 'msmolyak',

Forgive my bad Russian, but 'Ne za chem'.

I don't know how to get the tree Icon. Are you sure it is not constructed together with the checkbox icon and put in the checkbox? It this is the case you need to write a lot more code :-)

As for the JCheckBox, there are some methods for getting the state Icons. I believe it is getIcon() but there are also some other for the other states. Once you find the appropriate getIcon methods, you might want to store the Icons somewhere.
I see two ways.
- You can store all the icons you need once, in some static members.
- You can store them in every call the the getCellRendererComponent. Appropriate place for the storage is your model structure. Just put a member for each Icon you want to be stored.

Success,
  Nikolay

------------------------------------
diakov@theoffice.net
------------------------------------

Actually it's a bit more complicated than that. The getIcon() method will return null unless you set your own icon. The icon drawn by the Basic checkbox renderer is not aceessable to the checkbox user. Moreover, it is not a gif file, the icon gets drawn on the fly.

I found a solution to my problem (it is clumsy but works). In my FoderCheckBoxIcon class I simply draw a composite icon (in paintIcon() method), that is, first I draw a node icon, and then the checkbox icon.
I thought so.

CU around.
I mentioned my e-mail above. E-mail me if you feel like socializing :-)