English 中文(简体)
Sharing state between JButtons
原标题:

I want to create two or more JButtons that share state, i.e. when the mouse button is pressed over either JButton, both are rendered as depressed (aka "armed"), or if they are checkboxes, both are checked/unchecked simultaneously etc.

To the user, it must appear as if both buttons were the same button, appearing in more than one place in the hierarchy (in reality Swing does not allow this.)

I can get half way there by creating a single ButtonModel and assigning the same model to both buttons. This synchronizes their armed/checked/selected states etc.

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

Is there a clean way to do this?

Ideally I would like it to be independent of the chosen look-and-feel.

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

最佳回答

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

Now for your problem regarding focus. The answer is No. There is no L&F agnostic way. You have to override BasicButtonUI(or whichever ButtonUI you are using) and override the focus drawing logic.

问题回答

Here s what I did:

  • Extend JButton with a new class SharedFocusButton
  • SharedFocusButton overrides hasFocus, getModel and paintBorder.
  • When either JButton.paintBorder(Graphics) or ButtonUI.update(Component, Graphics) is running, temporarily change the behaviour of hasFocus so that it returns true if any button in the group has the focus. Also temporarily change the behaviour of getModel to return a proxy ButtonModel (at other times it returns the shared ButtonModel)
  • The proxy ButtonModel behaves like the default, shared ButtonModel, except that it refuses to change the armed or pressed properties values to false whilst handling a focusLost event.
  • Handle focusGained and focusLost, forcing all buttons in the group to redraw themselves (this won t happen automatically because each button has its own UI handling focus events.)

Remaining issues:
Focus traversal should probably be modified so that the Tab key never transfers focus from one button to another in the same group.

I m assuming that you ve already got text, listeners and the like sorted out.

Going to BasicButtonUI s paint method, we can see that it actually checks whether the button has focus before doing certain painting. So unless you can have two focussed components simultaneously, the only way to do it that I can think of is to use the other button s UI to paint.

Both buttons need to be a FocusButton, and need to call setButton on each other. I haven t bothered to add any null checking, amongst 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 doesn t work too well if your buttons aren t the same size, and obviously doesn t work at all if they are supposed to have different text.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签