Determining a JComponent's immediate neighbors in a FlowLayout - java

I have a JPanel that uses a FlowLayout and contains many JButtons. The buttons are in a 2-dimensional grid (by the FlowLayout). The JPanel can be resized, and, of course, when it is, the location of the buttons in the grid changes (although the order, of course, stays the same). I want the user to be able to navigate from one button to another in the grid by using the arrow keys on the keyboard.
Is there a way to tell for a given button, which button is currently directly above it, which button is directly below it, and which buttons are to its immediate left and right?
Obviously, this would be trivial if I were using a GridLayout, but I need to use a FlowLayout for other reasons.

The left and right arrow keys are not an issue. As mentioned by jzd you just add the KeyStrokes to the set of traversal keys.
For the up/down keys you will need to create a custom Action. You can use the location of the current component. Then to go up you can change the Y coordinated by say 10 pixels (5 pixels for the row gap between components pluse an extra 5). Then you can use the:
Container.getComponentAt(Point p)
to find the component at that new location.
To go down you would start with the location of the button then add on the height of the button plus 10 pixels.
Of course you would then use Key Bindings to bind the up/down KeyStroke to the Action.
Note: I'm not sure if you need to add the 5 extra pixels to find the componen above or below the component. You may just be able to use the vertical gap. I'm just not sure how the boundary checking works on the getComponentAt() method.

I think you can just use focus travel implementation that is in place as tab or shift navigates the selected buttons in a FlowLayout correctly.
I think you just need to add the arrow keys to sets like the forwardDefaultFocusTraversalKeys
More info:
http://download.oracle.com/javase/tutorial/uiswing/misc/focus.html

Related

Efficiency of mouse listener on JButton

Let say I created n JButtons and place them randomly in a JFrame and I add a mouse listener on each JButton.
My question is:
When I click on any one of the JButtons, does Java check through all JButtons to determine which button am I clicking (worst case: n checks) OR it does not need to check through all buttons (worst case: 1 check)?
The reason I ask this is because I am trying to interact with 2DGraphics and I know one of the ways to check whether I click on a particular Shape is by checking through all Shapes whether that Shape contains my current mouse coordinates. So if I draw 10 shapes, my worst case would be 10. Honestly speaking, I feel that kind of inefficient.
So I was wondering how does JComponent handles an actionEvent. By checking through all JComponents or they don't?
If they don't, how does Java determines which button was clicked?

SetVisible(false) with the space occupied

I would hide a JButton in a JApplet. I'm using setVisible() method but I've a problem: it works but my GUI is shifted because of the absence of the component. Is there a way to hide a component and make its space occupied???
I know that is possible in Android, but in Java?
ps. To insert component in my JPanel I'm using GridBagLayout!
There are several ways to achieve this in general.
Most proper way is to layout other components in a way that they remain correctly attached at their current positions.
Since for complex layouts the proper way can be hard to get and especially hard to change afterwards, you can apply some layout 'hacks'. For example, instead of adding the button to the panel directly, you could add the button to a separate panel of its own (let's name it buttonPanel), and then add that panel together with the button to the panel containing the other components. That way when you remove the button, buttonPanel will stay to fill the gap.
However, depending on the way how you specified constraints, buttonPanel may shrink when you remove the button. To prevent this, just before removing the button, take the buttonPanel's width and set it as its minimum/preferred width; most LayoutManagers will respect this property.
Of course, you can always resort to hardcoding dimensions to avoid dynamic size calculations, but keep in mind issues with L&F and i18n.
Try using the setOpaque() method. Just do button.setOpaque(false); and that should do the trick. Does that work?

how to expand a jScrollPane in all four directions?

I am working on a very simple mind mapping application, and I use a JPanel to draw the structure of the mind map on. The nodes of the mind map are circles, and if you write in a node, the structure expands in that direction. I put my JPanel in a JScrollPane, but my problem is, that I can only expand it downwards, or to the right, but it should be expandable to the left and upwards as well. When my JScrollPane should expand in "negative directions" so upwards or to the left, I tried calculating how many coordinates I shift, and than redrawing the whole graphic, changing the x and y coordinates of everything respectively. But it still did not work, it drew the part that is visible correctly, but then when I scrolled down, the rest of my drawing disappeared.
I hope there is a solution for this, because I've searched for hours and found nothing useful, and because I can't think of any other way to solve this. Thank you for your help! :)
When my JScrollPane should expand in "negative directions" so upwards or to the left
You can't have negative coordinates, so you need to translate all the indexes to positive values.
and if not, I resize the JPanel.
This is the key. You need to override the getPreferredSize(...) method of your custom panel to return the appropriate size of the panel after all nodes have been translated to positive values.
Then you invoke:
revalidate();
repaint();
on the panel to make sure the layout manager is invoked and the nodes are repainted.

How to hide other panels or panes during coding

Using Eclipse Juno for Java & WindowBuilder
I have three panels of the same size that lay on top of each other - they have different widgets. During coding, they all display and clutter up what I'm doing.
I can show and hide them in runtime as needed but, I want to display only the one I'm working on while doing drag and drop of widgets. I've tried using different panels and pane types (tabbed, layered...) and selecting opaque but, nothing hides them.
How do I hide the other (panes, panels...etc) during coding?
I have the same issue. Among other reasons, my solution was to create separate classes per view. So my frame would be its own class, it would maybe have a TabbedPanel (or whatever it's called), and then I would have a new class for each tab on that tabbed panel. Each class would extend JPanel so I could plop it right in there. That way not only is your gui design not cluttered up, but your code logic is separated into separate files, where it might belong anyway.
[SOLVED] Answering my own question.
It may not be perfect or the best/correct way, but it works!
WindowBuilder wants to Surround other panels/widgets that are within it's bounds so, you have to trick it by using opaque, Order>forward/backward then setting the desired bounds (all panel sizes and bounds can be equal and will overlay nicely both during widget drag&drop and runtime).
Here's how to do it with a 3-Panel example (NOTE: WindowBuilder is buggy/in-consistent and often I needed to select the items from the gui, not in the Components tree).
Create your first panel. Add your widgets and border to it.
Create your second panel (the one you want to overlay on top of the first one). This second panel MUST not be completely inside the first panel - it MUST extend beyond the edges of the first panel (parts of it can be inside the first panel). This takes a bit of trial because of the 'surround', mentioned above. Use the shift-key to stop the snapping.
Select the top panel in the gui, NOT from the Components tree, and toggle the Opaque property. The top panel (first or second) in the tree is the one you set to opaque and work on.
Add another panel and repeat the process.
Once you get your widgets/etc as you want them, use the property Bounds to set them all the same or as desired. After that, as long as you don't move a panel by dragging it, it will remain un-surrounded by the other panels. If you move by dragging, it may get set to surround...
I've done this a dozen times now and it works consistently.
Below is a shot of 3 panels overlayed, un-surrounded and not opaque, thus showing widget clutter
Below is a shot after the bounds are set (and not surounded). Opaque and order not yet set:
Below is a shot with bounds set and panel 3 moved forward and opaque set:
Below is a shot with bounds set and panel 2 moved forward and opaque set:
... etc, etc... Now you can work on a panel that's ordered to the front and, naturally, use the setVisible in your code...

How do I make a Swing JComponent a bigger mouse target?

I have a JPanel that contains a bunch of Swing JComponents, including some JSeparators that may be only one or two pixels wide. I want to let my users drag the items around, but it can be rather difficult to hit a one or two pixel wide line. Is there a way that I can give those JSeparators a wider "target" region for mouse clicks? The only thing I've been able to think of is to have my mouse handler listen for clicks on the JPanel, and if it gets any, run through the list of JSeparators, looking to see if any of them are within a couple of pixels of the mouse click.
Should that work? Is there a better way?
Add a fat EmptyBorder to the component.
If it already has a border, you can set a compound border using the current border then the empty border, or simpler, add the empty border (and listener) to a panel that contains the component. The latter will work better for components such as JButton, which have borders that change according to state and focus.

Categories

Resources