Adding a child component to a JButton - java

Is it possible to place a child component inside a JButton and make it transparent to a subset of mouse events so that:
The child component receives MouseMotionEvents (so it can respond by modifying a displayed image)
Clicking still depresses the JButton "behind" the child component
If you add the child component to the button but make no other changes, clicking in the area occupied by the child does not activate the button.
I know this can be achieved by creating a new class that extends JButton but I would prefer to use a child component which has already been written.
Note: this is purely for cosmetic reasons. The child component only changes its own appearance. It does not perform any other actions in response to clicks. There is just one Action, triggered by the button in the normal way.

Yes, it is possible but probably there are better ways to change the appearance of a JButton on mouse over. You can extend a ButtonUI to do that. However, if you want to drop a component over a JButton, you should pass other mouse events (e.g clicks) to the underlying JButton.

JXLayer is just the thing you need. Check out https://jxlayer.dev.java.net/
The project site has several good articles about JXLayer's usage for many different use cases.

Related

How to "Unclick" a JButton without releasing the left mouse button?

I have set up a mouse dragged listener. I trying to set it up where you can click one button then drag your mouse over others to click the other ones. The problem I am having is when you click the first button it turns grey like its waiting for you to release the mouse button. When you move your mouse off the button (still holding the left mouse button) it returns back to its normal color but you cant highlight anything until you let go. Is there anyway to simulated letting the mouse go and "unclicking" the button so you can highlight other things?
What you observe is the typical behavior of the ButtonModel used by Swing buttons. A complete example is examined here, but note how the effect depends on the chosen Look & Feel's ButtonUI delegate.
To get the effect you want, you would have to create buttons using your own variation of BasicButtonUI and a custom ButtonModel that uses isRollover() to add buttons to your program's notion of a selection model.
As an alternative, consider JList, which contains a ListSelectionModel that allows MULTIPLE_INTERVAL_SELECTION. A compete example is shown here.

Custom JButton with JTextArea component inside

I extended JButton so it would fit my needs. I have one JTextArea and two JLabel components inside of my new class. The problem is, that I cannot click through JTextArea. So, when mouse is in JTextArea bounds, the button is not responding. There is no problem with labels.
As on screen. There are four buttons. Each one is a separate yellowish rectangle. When mouse is over JTextArea's gray rectangle, I cannot press the button. I need JTextArea because it supports multiple lines. Is there any option to make it not intercept the mouse?
It would be ok if I could attach ActionListener to JTextArea, but I can't. It cannot have this kind of listener.
You look to be trying to use a JButton in a very non-button way, including having it hold a JTextArea, and not looking at all like a button. If you want a clickable area that is not an identifiable JButton, then consider using a MouseListener instead. You would likely have to add the same MouseListener to the container JPanel and the JTextArea.
Take a look at Concepts: Editors and Renderers to understand the difference between a renderer and an editor.
A renderer is a "rubber stamp" of the component, it is simply "painted" onto the surface of the JTable and is not a real life component
You would need to implement a custom editor, which could translate the trigger event (in your case the MouseEvent) into a local context.
Take a look at TableCellEditor#isCellEdtiable which is probably the closest you will get to the source of the event which might trigger the cell to become editable.
JButton could be seeded with a HTML String (`"This is some text"), which would be capable of supporting multiple lines and line wrapping as well
Having said all that, you might want to seriously reconsider your design...

How to determine which child JPanel is selected inside a JPanel (java)

I have a problem where I have several similar JPanels, that are contained vertically in a main JPanel. My issue comes where I will have buttons that will only interact with the child JPanel that is currently selected (clicked on).
I have a controller that takes the main JPanel, how can I have a method that will return only the selected JPanel?
This is very difficult. By default, JPanels are not focusable (they can't receive keyboard focus).
You could try ascertain the current panel that contains the current focusable component by using KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); and using the resulting Component's getParent method, but this is no guarantee, as the focused component may be contained in another container, contained within the container your interested in...
A better idea might be to have some kind of model that connected the buttons or actions to the child panels...?

Drag component to create another one

In all major Java IDEs, there is a GUI designer.
When we select a component (A Jbutton, for example) and move it to a JPanel or JFrame, how is it done?
Is it a copy of the dragged component that is created on the other container?
On a project I'm working on, I have some JButton I would like to be able to drag to a panel. Theses JButton represent some actions, like "copy file", "move file", etc...
When one of those JButton is dragged, some options of the action will be displayed.
I checked TransferHandler but I don't know if it's the way to go. Is it?
It's certainly possible. You'll need to study the Drag and Drop tutorial. In particular, you may want to implement Drop Location Rendering, discussed here, to symbolize the action.
By encapsulating a button's name, icon, listener, etc. in an Action instance, your importData() implementation can easily use setAction() to change the target button's behavior dynamically.
An alternative approach might be to add your buttons to a JToolBar. In normal mode, clicking the button evokes the Action; in editor mode , clicking the button changes the Action, again via setAction(), to one chosen from a list.

Refresh Panel on CardLayout Swap

How do you refresh a JPanel on the panel change from container CardLayout?
Use the show() method. From the Java API:
Flips to the component that was added to this layout with the specified name, using addLayoutComponent. If no such component exists, then nothing happens.
CardLayout#first(), next(), and previous() do something similar.
Sometimes, when I've made a panel swap like this (though not that I can remember on CardLayout, but it's been a while since I used it), I've also needed to pack the frame again. If that doesn't work, you can call revalidate(), which lets Swing know that the component needs to be redrawn.
You may also want to consider using a tabbed pane, as it does a lot of this for you; I started out a project trying to use CardLayout and decided to use a the tabbed pane instead. Depends on what you want to do, of course.
Is there an actionlistener or something that I can have it reload/refresh my data on that screen?
Assuming you have a model that supplies data to your view (panel), two approaches are common:
Arrange for your model to extend Observable and your view to register as an Observer.
Arrange for your model to manage an EventListenerList, in effect creating you own analog of ActionEvent.
In either approach, use the listener of the control that switches views tell the model to update its registered observers/listeners. The example in How to Use CardLayout uses a JComboBox and itemStateChanged(). There's additional discussion here.
Is there an actionlistener or
something that I can have it
reload/refresh my data on that screen?
You can use an AncestorListener. It fires when a component is added to a Container. So when you swap cards the event is fired. You would need to add the listener to each panel you add to the CardLayout:
Another problem with the CardLayout is that the panel doesn't gain focus when it is swapped. I use this approach to set focus on the panel. Check out Card Layout Focus.
panel.addAncestorListener(...);
The show() method does the trick of switching panels, but it doesn't "refresh" the data. Is there an actionlistener or something that I can have it reload/refresh my data on that screen?

Categories