Java Swing Scrollpane in NetBeans - java

I have Java application which adds JTextFields # runtime to JPanel. Basically user clicks a button and new JTextField is added, clicks again added again...
Each new JTextField is directly below the previous one. Obviously I run out of space pretty soon so I'm trying to use JScrollPane and thats where the hell begins, because it just doesnt work no matter what I try.
Right click on JPanel and Enclose in Scroll Pane. Didnt work.
After reading some examples I realized I must have JPanel as an argument for JScrollPane constructor. Which I did via right clicking on ScrollPane and CustomizeCode. Because apparently auto-generated code is protected in NetBeans and I cannot just change all those declarations, etc. manually. Still doesnt work.
I did try to set PreferedSize to null for JPanel and/or JScrollPane, didnt help.
JScrollPane is a child of lets call it TabJPanel (which in turn is a tab of TabbedPane). I tried to mess with their relationships, basically trying every possible way of parentship between JFrame, JPanel(holding textfields), TabJPanel and JScrollPane, but nothing worked.
I also made VerticalScrollBar "always visible" just in a case. So I see the scrollbar, it's just that populating that JPanel with JTextFields does not affect it.
When there are too many JTextFields I they go "below" the bottom border of JPanel and I cannot see them anymore.
Code for adding new JTextFields is like this, in a case it's relevant.
JTextField newField = new JTextField( columns );
Rectangle coordinates = previousTextField.getBounds();
newField.setBounds(coordinates.x , coordinates.y + 50, coordinates.width, coordinates.height);
JPanel.add(newField);
JPanel.revalidate();
JPanel.repaint();
Sorry for a long post I'm just trying to provide as much info as possible, because being newbie I dont know whats exactly relevant and whats not. Thanks in advance :)

As there is another answer now, I'm adding my suggestion too.
This sounds exactly like a problem to use a JTable with a single column. JList is not yet editable (and might never be).
JTable would handle the layout problems for you, and you can easily access the values via the table.
Use your own TableModel (a simple Vector should be sufficient in your case), and add values to it.

An option you have is to utilize a LayoutManager, instead of setting the bounds directly on the components. To test this, a simple single column GridLayout with the alignment set to vertical should prove the concept.
panel.setLayout(new GridLayout(0,1));
zero in the rows param allows for rows to be added to the layout as needed.

I do this way to add a scrollpane, create a panel and fill it with few components, then create a scrollpane in the component you want to add it, cut and paste the panel in which all your details will fall in and resize the scrollpane.Because the components take a larger space than the one visible right click on the scrollpane and select design this container, there you can increase the size of the scrollpane and add as many components as you have.

Related

GridBagLayout readd components

I created an ArrayList of JLabels of size n and placed the JLabels inside an JInternalFrame with the help of a GridBagLayout manager so that the grid fits my purpose.
Now I want to replace some of those JLabels or even remove them.
Removing the k-th JLabel does work well with
innerframe.remove( ListOfLabels.get(k) );
ListOfLabels.remove(k);
(By the way if I'm using only one of those the JLabel is not removed from the internal frame -- why ? If I remove other objects like Checkboxes, it sufficies to use only innerframe.remove(ListOfCBoxes.get(k));)
Even the other JLabels stay at their position, what did not work, when I placed the JLabels inside the surrounding JFrame.
But I'm not able to readd a JLabel after editing it's content. I'm trying
//Initialization
ArrayList<JLabel> ListOfLabels = new ArrayList<JLabel>(n);
GridBagLayout GridBLayout_innerframe = new GridBagLayout();
GridBagConstraints GridBConstraints_innerframe = new GridBagConstraints();
JInternalFrame innerframe = new JInternalFrame();
innerframe.setLayout(GridBLayout_innerframe);
// Creating components of innerframe, arranging them in a grid and adding them.
// This seems to work.
innerframe.remove( ListOfLabels.get(k) );
ListOfLabels.remove(k);
labelk = new JLabel("New content");
ListOfLabels.add(labelk);
GridBConstraints_innerframe.gridy = k ;
GridBLayout_innerframe.setConstraints(ListOfLabels.get(n-1), GridBConstraints_innerframe) ;
innerframe.add(ListOfLabels.get(n-1)) ;
Of course the same constraints were used for the k-th JLabel before and I did not
erase this information. I hoped I can overwrite it.
However the result is that the JLabels that I removed stay removed and the ones I want to
add do not appear. Even after ''refreshing'' the window. There is also no error message from Eclipse.
Can someone please find my mistake and explain how to readd components into a hopefully already existing grid :/
You are removing the JLabel without saying the Component that you did this. You need to call the revalidate() method just after adding/removing a Component when it's already visible.
So, in case innerframe is visible and you called innerframe.remove(...), you need to call:
innerframe.revalaidate();
Then innerframe notices that Components where added or removed and re-assigns the Components that are now in the Component (calling the LayoutManager, repainting, ...).
It's a bad idea to remove/add components in a complex layout. In such cases I would provide a full relayout: clear the container (use the method removeAll()) and add all the required components again. Of course you must call revalidate() and repaint() for the top changed container.

How do I create a JScrollPane within a JTabbedPane?

I am trying to create a JScrollPane within one of the tabs to my JTabbedPane. I tried what I though would work which was this:
pane.add("Main", mainGame);// These are my other tabs
pane.add("Upgrades", upgradeScreen); //the JTabbedPane
pane.add("Credits", creditsTab);
upgradeScreen.setLayout(null); //The null layout
lblMoney2.setBounds(10, 11, 277, 22);
upgradeScreen.add(lblMoney2); // A simple JLabel
scrollPane.add(upgradeScreen); //my JScrollPane
Where pane is my JTabbedPane and scrollPane is my JScrollPane. This simply got rid of my upgradesScreen tab. I kind of expected this but I did not know what else to do. If more code is needed for you to figure it out, tell me and i'll put it in, otherwise, thanks for the help!
Don't us JScrollPane#add, instead you want to use JScrollPane#setViewportView
Check out How to use ScrollPane more details.
Advise- Don't use null layouts, they limit the ability for your application to run on multiple platforms. Instead take the time to learn how layout managers work
This simply got rid of my upgradesScreen tab.'
yes, because no component can have two parents at once. You added upgradeScreen to JTabbedPane first and then again added it to a JScrollPane. The Component's add(component) function will eventually call the addImpl(component) function: which will remove the component from it's old parent and add it to the new parent.
However:
You need to add the JScrollPane to the JTabbedPane instance.
The component which you wish to scroll set it as a view to JScrollPane using the setViewportView(component) function. for your context it is the upgradeScreen

Java multiple GUI windows creation

I have made a simple GUI using a GridLayout(5,3) , it is action performed and it implements action listener as well. The are some calculation and algorithms that working according to what inputs or buttons the user provides. Everything works just fine up to this point.
At some point in my code, the user gets a pop up massage that he is correctly logged in to the system using this common method JOptionPane.showMessageDialog(....) . All i want is, after he press the OK button, is to create an additional form that pop ups, and looks similar to the one above i made with GridLayout(5,3) so that my user can store additional info about him.
I really cant get it to work, and i have no idea how to start this.
Any ideas are very welcomed! Cheers and thanks in advance :)
if add this:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = getContentPane();
GridLayout grid=new GridLayout(10,1);
pane.setLayout(grid);
it only adds more lines to my gridlayout. And all above buttons and labels remains. How can i get rid of the previous labels and buttons?
You state:
if add this:
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = getContentPane();
GridLayout grid=new GridLayout(10,1);
pane.setLayout(grid);
it only adds more lines to my gridlayout. And all above buttons and labels remains. How can i get rid of the previous labels and buttons?
You have at least three options if you want to swap "views" on the JFrame.
If you want to use the same GUI with the same JTextComponents but have the components empty of text, then you'll need to go through your text components and call setText("") on all of them. If you want to keep the same JButtons and labels but change their text, then similarly you will need to go through all of them calling setText("something else").
If you want totally new components to replace the old ones, the most straight forward way I believe is to use a CardLayout to hold your JPanel that has all your components. When you want to swap the JPanel for another, make sure that the new JPanel has been added to the CardLayout-using JPanel and then call next() on the CardLayout object.
Another way is to manually swap out JPanels held by the JFrame's contentPane by calling removeAll() on the contentPane, then add(nextJPanel) on it, then revalidate(), then repaint().

Java: Can't get JButton to be horizontally snug around text

I have a JButton that is much wider than the text I put into it. I've researched this, and I keep finding the suggestion that I use Jbutton.setMargin(new Insets(0,0,0,0)); But this just does not seem to work. Also, setMaximumSize has no effect, although if I also set a minimum size, it does change the size of the button. But I don't want to set the size manually. I just want it to be less wide. What am I missing?
Here's my code to create the button:
plusminus = new JButton("+");
plusminus.setMargin(new Insets(0,0,0,0));
And here's what it looks like:
Thanks.
I'm manually making my GUI. In this case, the layout is GroupLayout
Then that may be part of your problem. Your JButton's size is constrained by the layout of the container that holds it. One possible solution if you absolutely need to use GroupLayout (which I hate by the way), is to place your JButton inside of a JPanel that uses FlowLayout or some other layout that allows flexible sized components, and place this JPanel into the container that's currently holding your button. Beware though if your button's bigger than the JPanel.
On a lark i tried negative left & right insets & unbelievably it worked. I did not then need to mess w/ the min/max/pref sizes. Btw my buttons are in one column of a JTable.

How do I force JScrollPane to only scroll vertical?

Guys, I need to put some buttons in a jscrollpanel, but the JScrollPane won't create a scroll vertically. I'm using a JPanel inside the JScrollPane which is using the simple FlowLayout layout. How can I make the JScrollPanel to scroll only in the vertical??
Problem:
Desired Solution:
Check out the Wrap Layout
The fact you use a JScrollPane changes quite a few things concerning the internal FlowLayout. indeed, when the FlowLayout tries to layout contained JButtons, it use for that the available space. In your case, you don't have limits to the space in the "scrollable client" of your JScrollPane. As a consequence, considering your FlowLayout has infinite space, it uses this space to display items according to it.
So the solution would be to change your scrollable client in order to limit its viewable area to the same than your JScrollPane's JViewport.
However, you would not even in this case have your line returns, as FlowLayout don't really well handle this case.
Were I to be you, I would of course choose an other layout. As GridLayout don't really well handles borders, i think the only reasonible standard layout you can use is GridBagLayout, althgough I fear your dynamic content constraints may require you something even more customizable.
JTextArea c = new JTextArea();
c.setLineWrap(true);
c.setWrapStyleWord(false);
This will wrap anything in a text area to the next line without creating a Horizontal Scroll.
Use the modified Flow Layout that I posted in this answer: How can I let JToolBars wrap to the next line (FlowLayout) without them being hidden ty the JPanel below them?
It will wrap to the next line and your scrollbar should scroll vertically.
scrollbar = new Scrollbar(Scrollbar.VERTICAL);
Or you could use a JList.
See this site for more info: http://docs.oracle.com/javase/tutorial/uiswing/components/list.html
the example class: ListDialog uses only a vertical scrollbar, when the window is resized or the elements don't fit the view.

Categories