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.
Related
Is there any thing I can do to make my JPanel pack like a JFrame, or do something like that. I want to do this instead of giving it dimensions. Please comment if any addition info is needed. Thanks.
Please try JPanel.updateUI and let me know if that helps.
You should make GUI calls in the Event Dispatcher Thread:
EventQueue.invokeLater(() -> {
someJPanel.updateUI();
});
If I understand you correctly, your JPanel is not being automatically (re)sized, correct? In that case, you can use Component.validate (or JComponent.revalidate())
Let me explain my use case, so that my answer will make sense.
I have a game board G on which I am absolutely positioning tiles Ts and some other property panels say P, Q and R.
Only the Game board G doesn't use a layout. However, for all the tiles and other panels, I do want to use layout management. For the
tiles, I want to calculate and set both position and size based on how many tiles are there. So, the setBounds method works great.
The problem is with the other panels like P where I know the x and y where I want to place them, however, I would like it if they figured out their own preferred sizes. This becomes a problem because setBounds insists on setting both position and size, and setLocation doesn't seem to work.
The solution which worked for me is putting a slightly oversized panel Outer-P and setting opaque to false and then placing P inside it. Note that Outer-P has a layout manager which allows P to be its preferred size. Personally, I used new MigLayout("insets 0","[]","[]") which lets the child take its preferred width and height.
As far as the user is concerned, P is in the top left, and looks packed. The wrapper panel is invisible.
I just recently started using Swing to create GUIs for programs, and it's been pretty fun to mess around with so far. However, I'm having an issue with a JPanel with the layout set to gridLayout. Right now it looks like this:
The grid on the right is a JPanel set to a GridLayout, with each cell being a bordered JLabel. The options on the left are also inside a JPanel, and the left JPanel and right JPanel are nested in a GridBagLayout set on a JFrame.
Essentially, my problem is that I want to "scale" the grid on the right so that each cell is a certain height and width. The grid itself will have a variable number of rows and columns, which are set when the program first starts up. Eventually, I plan to have the right JPanel in a JScrollPane (if that's how that works...), so I'm not really concerned about whether or not all of the grid shows up onScreen.
I tried setting the fill value for the gridLayout to "BOTH" and it gave me the following result:
This is closer to my intention, but I wanted the actual ImageIcon in the JLabels to fill the entire JLabel. Additionally, I would want the JLabels to be the same height and width. However, I don't know exactly how to do that. I've been messing around with it for a while now, and I'm not sure if I'm just too much of a noob with Swing, or if I'm missing something in the documentation.
In the end, I'd like the grid cells to be a fixed height and width, no matter the number of cells, and no matter whether it goes offscreen or doesn't fill it.
(Also, I just thought, maybe it's not the best idea to code this and then shove it in a JScrollPane later and expect it to perform the same.... I guess I'll just see what happens.)
but I wanted the actual ImageIcon in the JLabels to fill the entire JLabel.
Check out Darryl's Stretch Icon which will allow the icon to resize to file the space available for the JLabel.
I have a JSplitPane with a vertical split. The top component is a table which is in a JScrollPane, and the bottom component is a detailed description of a row. The bottom component always have the same number of elements, so essentially it stays the same height.
Right now, I am using setDividerLocation to position where the pane is being split. If I put 100 into it, the top portion will be 100px, if 500 then the top will be 500px. But if I re-size the JFrame, then the top component is still 100px and the bottom component is really big.
I was wondering if there is a way to set the divider location based on the bottom component instead of the top component?
Sorry if I didn't explain it well, if what I said is still confusing, please let me know and I can try to explain it better.
------ EDIT ------
Thanks to ControlAltDel for figuring it out. This is what my code looks kinda looks like now:
JSplitPane splitPane = new JSplitPane();
splitPane.setTopComponenet(new JTable());
splitPane.setBottomComponent(new JPanel());
splitPane.setResizeWeight(1); // This gives the top component priority when the window is resized
http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html#setResizeWeight(double)
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
Been developing a game for a while, and currently re working the GUI, or at least trying to. Had the massive problem of not being able to resize the frame (without issues), as I didn't understand layout managers very well. A few projects later, and time to come back and do some more on the game, and I hit a problem...
The basic layout of the main frame is, mainPane, containing one gameScrollPane and one controlPanel. The scroll pane is a scroll pane, and the control panel a normal panel. The scroll pane contains the main game panel.
As I wanted the scroll pane to take up most of the screen, with the control panel taking up a small lower area, much the same as many Sim like games, so chose the Border layout for the mainPane. I added the scroll pane and set the constraints CENTER and the control panel added and constriants SOUTH. This didn't show the scroll pane, so I played around trying different constraints, and it seems that only when I set the scroll pane constraint to North, does it display at all.
To demonstrate this, I have created a quick video...
http://screenjel.ly/q5RjczwZjH8
As you can see, when I change the value of NORTH to CENTER and re run, it's like its not there!
Bonus points for anyone who can see a clear second problem which I may start another question for after this issue is solved!
I thank you for your time to read this.
Thanks in advance for any ideas or thoughts :)
Rel
If you'd posted some code to start with then you might have gotten a really quick answer. Luckily, you posted a link in the comments to the other response.
The setContentPane() stuff is weird, especially after doing some things to it that will then get wiped out. However, that's not your problem.
The issue is that you are adding levelMaker and personMover right to mainPane without any constraints. These will then be blowing away anything you set for CENTER... in this case the previously set gameScrollPane.
That's why you see it for NORTH and not for CENTER.
I can't get the video to show. It's been buffering for ages.
My guess would be that the scrollpane is in fact filling the center; it's just your game panel that's not being shown.
Your game panel needs to return reasonable values for getPreferredSize().
Update
Another thing you may want to do is have your game panel implement the Scrollable interface. You can then override getScrollableTracksViewportWidth and ...height to return true so your panel will be forced to the scrollpane's dimensions.