Long time lurker, second time poster (it's got that desperate)
I have a frame that needs to display twelve components next to each other (as if each component is its own column). The first component is a list of attribute names, the second component shows the default attribute, and the next ten are all pulled in from a database. I would like for my Scroll Bar to effectively "freeze" the first two components (i.e. it always shows the first two components) and the scroll bar allows you to look through the rest of the entries. This is similar to Excel where we freeze columns, a la here.
I've looked into using tables, but the problem is that my components are not just text. They've got images and the like too.
Here's some of the code I'm using
JPanel info = new JPanel(); // this is the main component (holds the other 12)
info.setLayout(new GridBagLayout()); // GridBag Layoout
info.add(attNames); // add in the attribute names component
info.add(currentCase); // add in the default values
JPanel rets = new JPanel(); // add in the ten retrieved cases
rets.setLayout(new GridLayout(1,10));
for (int i=0;i<maxCases;i++)
{
rets.add(retCase[i]);
}
info.add(rets); // add the return cases to the info component
JScrollPane scrollBar2=new JScrollPane(rets,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); // surround the return cases with a scroll bar
info.add(scrollBar2); // add the scrollbar
//add the info comp to the content pane along with other necessary components
this.getContentPane().add(casesPanel, BorderLayout.NORTH);
this.getContentPane().add(info, BorderLayout.CENTER);
this.getContentPane().add(buttons, BorderLayout.SOUTH);
//finally, add the overall scrollbars and set the size
this.pack();
JScrollPane scrollBar=new JScrollPane(info,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.setSize(this.getWidth(), 750);
this.setResizable(true);
this.add(scrollBar);
The problem is that the scroll bar for the returned case doesn't think it's needed and I have to use the big scroll bar, meaning I can move away from the first two components.
Any help would be greatly appreciated!!
Here's the problem
Cheers,
K
Place the frozen section into the scroll panes row header. Check how to use scroll panes for more info and examples
Related
So firstly, I added the text fields and their labels into separate panels as I wanted them to be in line with each other, I added them via Flow layout;
//add them in Flow Layout
panel.add(label_1);panel.add(file_name);
pane2.add(label_2);pane2.add(h_link);
pane3.add(label_3);pane3.add(pages);
What i wanted to do next is to add them using BorderLayout in a way that all of them will be in the center of the window. Additionally, I wanted to add submit button of the details;
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.getContentPane().add(BorderLayout.CENTER, pane2);
frame.getContentPane().add(BorderLayout.CENTER, pane3);
frame.getContentPane().add(BorderLayout.SOUTH, submit);
frame.setVisible(true);
As I am writing this post, I did not achived the result that i wanted , the screenshot attached shows the resulting frame which is not I wanted.
By all means, if you have also any suggestions for how to do it more efficiently please do share.
The key to solving this is to nest JPanels, each using its own layout, thereby allowing you to effectively nest layouts:
Place a JPanel in the BorderLayout.CENTER position
Give the JPanel a GridLayout, one allowing multiple rows and one column, e.g., new GridLayout(0, 1)
Add your JTextFields to the JPanel
Another approach is to simply use a JTable, one with a single column and multiple rows.
Another approach -- if you're trying to gain input from a user in a JLabel/JTextField grid -- is to use GridBagLayout to space the components nicely together
I have created a GUI in Java which looks as shown below -
'panel_mid' is the white panel in the middle. I have added it to a scrollpane called 'panel_mid_scrollpane'.
Apart from 'panel_mid' there are more panels -
panel_left (containing 'back' button)
panel_right (visible on right hand side)
Revelant code for this gui is -
panel_mid.setBorder(grayborder);
panel_mid.setBounds(0, 0, 1100, 1060);
panel_mid.setBackground(Color.white);
panel_mid.add(obj.create_test_add_section);
panel_mid_scrollpane = new JScrollPane(panel_mid);
panel_mid_scrollpane.setLocation(150, 20);
panel_mid_scrollpane.setSize(1000, 660);
panel_mid_scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
The Add Section button shown in panel_mid, adds a section to the middle panel, every time it is clicked. When this button is clicked multiple times, the gui looks like -
As you could see, the scrollbar does not appear automatically as panels are added, the last panel is thus only half visible. What could be causing this problem ?
Thanks !
Scrollbars appear automatically when the preferred size of the component added to the scrollpane is greater than the size of the scroll pane.
You appear to be using a null layout.
//panel_mid.setBounds(0, 0, 1100, 1060);
panel_mid.setBackground(Color.white);
panel_mid.add(obj.create_test_add_section);
panel_mid_scrollpane = new JScrollPane(panel_mid);
//panel_mid_scrollpane.setLocation(150, 20);
//panel_mid_scrollpane.setSize(1000, 660);
Don't use a null layout with setSize() and setLocation. Swing was designed to be used with layout managers. If you use layout managers then the scrollbar will work automatically and the size and location will be calculated automatically for you.
Read the Swing tutorial on Layout Mangers.
You must tell the GUI to refresh, so that the containers are laid out again. This will show the container that it also has to show a scrollbar.
So in the ActionListener or whatever you use to add a section, add code like:
container_with_sections.validate();
container_with_sections.repaint();
where container_with_sections is the container (JContainer) which contains the JScrollPane, or a container which contains a container which contains the JScrollPane, and so on.
I am attempting to create panel, PluginListPanel (extending JPanel), which will show a list of plugin panels which will respect the preferred height of the plugin's panel, but will force the width. I have a solution, but it is slow and has a weird bug. In the screenshot, there are two such panels, one to the left and one to the right:
I don't know different layout manager systems very well, but I know that the TOP field in the BorderLayout does what I want. So, I came up with this 'recursive' solution:
public PluginListPanel(List<PanelContainer> items) {
JPanel body = this;
for (PanelContainer item : items) {
body.setLayout(new BorderLayout(0, 0));
JPanel panel = new PluginOnePanel(item);
body.add(panel, BorderLayout.NORTH);
JPanel newBody = new JPanel();
body.add(newBody, BorderLayout.CENTER);
body = newBody;
}
}
The problem I encounter is when I scroll, the system responds somewhat slowly, and the colour of the SamplePluginPanels is different (see picture below), even if the number of SamplePluginPanels is as low as 8.
The question is, how can I make this more elegant, not slow down the program and not miscolour the panels?
Any insights are highly appreciated.
I think a vertical Box is the answer (actually 2, on both columns):
Box leftBox = Box.createVerticalBox();
Box rightBox = Box.createVerticalBox();
/* put them together */
setLayout(new GridLayout(2,1));
add(leftBox);
add(rightBox);
Also make sure, that the content of the scroll pane implements Scrollable and returns true, to scrollableTracksViewportWidth(). This will force equal widths.
I am trying to create a JScrollPane that contains a JPanel that will be increasing and decreasing in height. When it becomes larger than the size of the JScrollPane, it should create a vertical scroll bar which will allow me to scroll through the entire JPanel. However, I am having difficulty achieving this. Yes, I know I am not using LayoutManagers. No, I will not be using them, and I need a solution that does not involve their usage.
Here are the two button's AbstractActions that add and subtract from the JPanel:
class AddACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
info.setSize(420,info.getHeight() + 40);
info.add(new SubPanel); // Adds another JPanel into the main JPanel (for content input)
gui.repaint();
infoS.validate();
}
}
class RemoveACT extends AbstractAction
{
public void actionPerformed(ActionEvent e)
{
info.remove(subPanel()); // This would remove the last JPanel added to the main JPanel
info.setSize(420,info.getHeight() - 40);
gui.repaint();
infoS.validate();
}
And here is the code for the main JPanel and the JScrollPane:
final JPanel info = new JPanel();
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
info.setLayout(null);
info.setSize(420,600);
infoS.setLocation(10,80);
infoS.setSize(420,490);
gui.add(infoS); // gui is the frame's content pane (the overall JPanel)
This is the second project I've been trying to learn GUI by doing. I am a complete novice in Swing and am only intermediate in Java. Sorry if I am making a blindingly obvious mistake.
1) Use LayoutManagers (+1 to #kleopatra and #GagandeepBali comments)
The absence of LayoutManagers only guarantees your GUI's will look very trashy (especially when run on other OSes/builds) and being a Novice you should rather learn the correct way than learn the wrong way and get into bad habits like calling setSize() etc.
Have a read on these links to get you started:
A Visual Guide to Layout Managers
Concurrency in Swing
2) See this example for how to use a JScrollPane, it simply adds a JPanel with buttons to a JScrollPane which in-turn is added to the JFrame.
3) Also see this example for how to make the JScrollPane vertically scroll-able only.
4) For more on JScrollPanes have a look here: How to Use Scroll Panes.
5) As for how it interacts with LayoutManager, if you do not explicitly set its size via setPreferredSize(Dimension d) the scroll pane computes it based on the preferred size of its nine components (the viewport, and, if present, the two scroll bars, the row and column headers, and the four corners)
6) On your usage of validate():
validate() is used when new JComponents are added to a visible component
revalidate() is used when JComponent is removed/added from a visible component
revalidate() covers validate() too
Thus always use this:
//add or remove component(s)
revalidate();
repaint();
References:
http://www.daniweb.com/software-development/java/threads/405568/validate-vs-revalidate
LayoutManager is not required to solve the problem. The problem in Thrfoot's example is in these lines:
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
info.setLayout(null);
info.setSize(420,600);
The program appears to recognize there is a need for scroll bars (it would show the scroll bar if your setting was VERTICAL_SCROLLBAR_AS_NEEDED), but the actual scrolling does not work (the scroll bar slider is not there).
To fix this, first set the preferred size of info, then construct the infoS.
Example:
info.setPreferredSize(420,600);
final JScrollPane infoS = new JScrollPane(info, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
The idea is to set the preferred size of the info panel before it is used for the scroll pane. This is the same reason to set the size and location of infoS before adding to the gui:
infoS.setLocation(10,80);
infoS.setSize(420,490);
gui.add(infoS); // gui is the frame's content pane (the overall JPanel)
I am trying to add components to a jpanel dynamically from a database, one after the other, however they extend beyond the limits of the form (and even the screen) horizontally. I am using a panel with BoxLayout which positions inner components on the x-axis. What I would like to do is limit the addition of components on the x-axis at the border of the form (or the border of the container panel) .
What I tried so far is:
To set the maximum size (width) of the
container jpanel but that did not
work.
To set the layout manager to
flowlayout, but it also expands
infinitely on the x-axis.
To position the container panel inside a
scrollpane. That makes a huge
horizontal scrollbar, which means that
it does not limit the components to
the border of the form.
Should I make a custom layout? Any ideas simpler than that?
My code looks like:
jpanelCases.setLayout(new BoxLayout(this.jpanelCases, BoxLayout.X_AXIS));
db = Database.getInstance();
List<Category> cats = db.getCategories();
for(Category c : cats){
JPanel jp = new JPanel();
//addition of other components to the newly created panel here
jpanelCases.add(jp);
}
however they extend beyond the limits of the form (and even the screen) horizontally.
So what do you want to do in this case:
a) just ignore the components and not add them to the frame
b) display the components on a new line
If the answer is "b", the try the WrapLayout.
Try to put 2 glues, one at first one at last:
jpanelCases.setLayout(new BoxLayout(this.jpanelCases, BoxLayout.X_AXIS));
jpanelCases.add(Box.createHorizontalGlue());
db = Database.getInstance();
List<Category> cats = db.getCategories();
for(Category c : cats){
JPanel jp = new JPanel();
//addition of other components to the newly created panel here
jpanelCases.add(jp);
}
jpanelCases.add(Box.createHorizontalGlue());
What about using JScrollPane on the JPanel? This will contain the elements within the panel without exceeding its physical boundaries. Otherwise, if you do not like the scroll idea I suggest that you somehow keep track of the total sum of width of elements added to the panel with respect to the panel physical width, and stop adding elements when the next element width added to the sum exceeds the panel width.
I hope this helps!