Separation state between JButtons

I want to create two or more JButton that share state, that is, when the mouse button is pressed on JButton , both of them appear as pressed (or "armed"), or if they are flags, both are checked / not checked at the same time, etc. .

For the user, it should look as if both buttons were the same button appearing in more than one place in the hierarchy (in fact, Swing does not allow this.)

I can get half way by creating one ButtonModel and assigning the same model to both buttons. This synchronizes their status with enabled / checked / selected, etc.

However, one noticeable effect that is not shared between the buttons is focus - clicking on one button gives the button focus (indicated by the box inside the button) and removes it from the other button. I would like to display both buttons as if they were focused whenever the button really has focus.

Is there a clean way to do this?

Ideally, I would like it to not depend on the selected appearance.

Edit: I discovered another issue with ButtonModel . When one of the buttons loses focus, it sets the properties of the armed and pressed models to false . This happens after processing mousePressed , so if you press the second button when the first button has focus, it will not enter the pressed state until you press it a second time.

+4
source share
3 answers

You made a really good move using the same ButtonModel for two buttons.

Now for your focus problem. Answer: No. There is no agnostic L&F method. You must override the BasicButtonUI (or depending on which ButtonUI you are using) and override the focus drawing logic.

+3
source

Here is what I did:

  • Extend JButton new SharedFocusButton class
  • SharedFocusButton overrides hasFocus , getModel and paintBorder .
  • When starting JButton.paintBorder(Graphics) or ButtonUI.update(Component, Graphics) temporarily change the behavior of hasFocus so that it returns true if any button in the group has focus. Also temporarily change the behavior of getModel to return the ButtonModel (at another time, it returns a common ButtonModel )
  • The ButtonModel proxy behaves like the default, shared ButtonModel , except that it refuses to change the values โ€‹โ€‹of the armed or pressed properties to false during the processing of the focusLost event.
  • Handle focusGained and focusLost , forcing all buttons in the group to redraw (this will not happen automatically because each button has its own focus events for processing the user interface.)

The remaining problems:
It is likely that the focus change should be changed, so that the Tab key never transfers focus from one button to another in the same group.

+3
source

I assume that you already have text, listeners and the like.

Moving on to the PaintBase method, we see that it actually checks to see if the button has focus before making a specific picture. Therefore, if you cannot use two lumped components at the same time, the only way I can think of this is to use a different button UI for drawing.

Both buttons must be FocusButton, and you need to call setButton on top of each other. I didn't even bother to add a zero check, among other things.

 public class FocusButton extends JButton { private JButton btn; public FocusButton() { addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { // Other button seems to repaint when focus is gained anyway } public void focusLost(FocusEvent e) { btn.repaint(); } }); } public void setButton(JButton btn) { this.btn = btn; } public void paint(Graphics g) { if (!btn.hasFocus()) { super.paint(g); } else { btn.paint(g); } } } 

EDIT: This does not work too well if your buttons do not have the same size and obviously do not work at all if they should have different text.

+1
source

Source: https://habr.com/ru/post/1300100/


All Articles