My JPanels doesn't show as i want them - java

Im trying to make the look of my application to look something like this:
But when i try to make this i get something like this:
Here is the code i use to create my two JPanels and how i add the buttons and soo on..
//This is the panel that shows the image
appletRunningPanel = new ImagePanel();
appletRunningPanel.setSize(600, 300);
appletRunningPanel.validate();
//This is the panels that shows the 3 buttons
appletRunningPanel2 = new Panel(new GridLayout(1, 3));
appletRunningPanel2.setSize(600, 300);
appletRunningPanel2.add(test1);
appletRunningPanel2.add(test2);
appletRunningPanel2.add(test3);
appletRunningPanel2.validate();
//Then i add them to the applet with this:
add(appletRunningPanel);
add(appletRunningPanel2);
Here is the code for ImagePanel
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
setSize(600, 300);
try {
image = ImageIO.read(getClass().getResourceAsStream("/res/TCHLogo.png"));
} catch (IOException ex) {
// handle exception...
System.out.println(ex);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
}

GridLayout will stretch the component in each cell to fit the size of the cell, if you want to avoid this stretching then add the Buttons to another Panel and add that panel to the GridLayout.
Laying out a user interface in Java, in my experience, is all about mixing and matching Layout managers to achieve your overall goal. There are some simplified managers out there like Mig Layout
For you example I'd do something like this:
+----------------------------------------+
| panel1 |
|+--------------------------------------+|
|| panel2 ||
|+--------------------------------------+|
+----------------------------------------+
+----------------------------------------+
| panel3 |
|+-----------++-----------++------------+|
|| panel4 || panel5 || panel6 ||
|+-----------++-----------++------------+|
+----------------------------------------+
panel1 has a BorderLayout
panel2 is your ImagePanel and added to panel1 via panel1.add(panel2, BorderLayout.CENTER);
panel3 is your GridLayout.
panel4, panel5, and panel6 are all default (FlowLayout) and each of these JPanels will contain one of your three buttons.
You can then add this to the Content Pane by setting it's Layout to BorderLayout and adding panel1 via getContentPane().add(panel1, BorderLayout.NORTH); and panel3 via getContentPane().add(panel3, BorderLayout.SOUTH);
It's not perfect, but it'll achieve a cleaner look for you. There is a lot more that you can add to make things appear nicer. One of my favorite layout managers is BoxLayout.

You need to better understand Layout Managers. Have a look through this handy guide and pick a layout manager that suits your need.
On the bottom panel, GridLayout doesn't respect the preferred size of the components (JButtons), it uses all the space available in the grid section.
You may need to use different layout managers for each panel, and another one again for your applet frame.

Try to add an intermediate JPanel
i.e
JPanel appletRunningPanel2Wrapper = new JPanel();
appletRunningPanel2Wrapper.add(appletRunningPanel2);
add(appletRunningPanel2Wrapper);

Related

Best practice to resize JScrollPane

I read some answered questions in this forum (this one for example) where it is strictly recommended to avoid the use of setXXXSize() methods to resize components in swing applications.
So, coming to my problem, i would like to know how to best resize a JScrollPane in order to avoid its parent panel to increase its size without any control.
Before writing some code, i want to describe the real situation, since i will post a "toy example".
In my JFrame i'm currently using a border layout for my content pane. At BorderLayout.CENTER there is a JPanel where i do some custom painting.
At BorderLayout.EAST there is a JPanel (say eastPanel) containing some components inside another panel (this panel will be added to eastPanel at BorderLayout.NORTH), and a JScrollPane which contains a JTable (added to eastPanel at BorderLayout.CENTER). This table will have a lot of rows.
Since i want eastPanel's height to be the same as centerPanel's height, i need some way to avoid the JScrollPane to increase its size in order to try to display as much rows as possible.
For now i wasn't be able to find another solution apart from calling setPreferredSize on the eastPanel containing the scrollpane, but i have to admit that i hate this kind of solution.
Sample Code
In this code sample i added some random labels at the north of eastPanel and inside the JScrollPane, since my purpose was to post a short sample of code.
However, the situation is very similar to the one i have described above.
I wasn't be able to solve my problem without using this "terrible" line of code :
eastPanel.setPreferredSize(new Dimension(eastPanel.getPreferredSize().width, centerPanel.getPreferredSize().height));
I would like to avoid a more complex layout for a simple situation like this. Am i missing something ? Also, is setting that empty border an acceptable way to set the size of the panel where i will do some custom painting?
Code :
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class Test
{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
new TestFrame().setVisible(true);
}
catch(Exception exception) {
JOptionPane.showMessageDialog(null, "Fatal error while initialiing application", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
}
}
class TestFrame extends JFrame
{
public TestFrame() {
super("Test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel pane = new JPanel(new BorderLayout(20, 0));
pane.setBorder(new EmptyBorder(20, 20, 20, 20));
JPanel centerPanel = new JPanel();
centerPanel.setBackground(Color.WHITE);
centerPanel.setBorder(new EmptyBorder(400, 400, 0, 0));
// centerPanel.setPreferredSize(new Dimension(400, 400));
JPanel eastPanel = new JPanel(new BorderLayout(0, 20));
JPanel labelsContainer = new JPanel(new GridLayout(0, 1));
for(int i=0;i<7;i++) labelsContainer.add(new JLabel(String.valueOf(i)));
eastPanel.add(labelsContainer, BorderLayout.NORTH);
JPanel moreLabelsContainer = new JPanel(new GridLayout(0, 1));
for(int i=7;i<70;i++) moreLabelsContainer.add(new JLabel(String.valueOf(i)));
JScrollPane scroll = new JScrollPane(moreLabelsContainer, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
eastPanel.add(scroll, BorderLayout.CENTER);
eastPanel.setPreferredSize(new Dimension(eastPanel.getPreferredSize().width, centerPanel.getPreferredSize().height));
pane.add(centerPanel, BorderLayout.CENTER);
pane.add(eastPanel, BorderLayout.EAST);
setContentPane(pane);
pack();
setLocationRelativeTo(null);
}
}
Thanks for your help !
I am not aware of a layout manager that restricts the height of the panel based on the height of a specific component in the panel.
One way is to customize the behaviour of the parent panel that contains the two child components.
The code might be something like:
#Override
public Dimension getPreferredSize()
{
Dimension d = super.getPreferredSize();
BorderLayout layout = (BorderLayout)getLayout();
Component center = layout.getLayoutComponent(BorderLayout.CENTER);
int centerHeight = center.getPreferreidSize().height;
if (d.height > centerHeight)
d.height = centerHeight;
return d;
}
This approach will allow for dynamic calculation of the height based on the component in the center.
Another option is to write you own layout manager. Then you can control this type of logic from within the layout manager.
Also, is setting that empty border an acceptable way to set the size of the panel where i will do some custom painting?
I override the getPreferredSize() to return the appropriate dimension.
By using the EmptyBorder you lose the ability to add a true Border to the panel, so I wouldn't recommend it.

Insert a JPanel with null layout into a JScroll

I have a JPanel (myPanel) with a lot of button inside (this panel is contained in another panel that contain other components). I would insert this JPanel (myPanel) into a scroll to control better the button.
This is a part of my code:
JPanel firstPanel = new JPanel(null);
......
......
JPanel myPanel = new JPanel(null);
myPanel.setBounds(0, position+22, 400, 500);
for (int i=0; i<size; i++) {
JButton button = new JButton(myList.get(i));
if (counter%4 == 0) {
button.setBounds(270, 0+(4*i), 90, 18);
} else if (counter%3 == 0) {
button.setBounds(180, 4+(4*i), 90, 18);
} else if (counter%2 == 0) {
button.setBounds(90, 8+(4*i), 90, 18);
} else {
button.setBounds(0, 12+(4*i), 90, 18);
}
myPanel.add(bottone);
}
......
......
firstPanel.add(myPanel);
So, how can i do to insert it into a scroll?
Your question appears to ask about how to add a JPanel to a JScrollPane when the JPanel uses null layout, and the answer is easy:
First and foremost DON'T use a null layout. Use of null layouts almost guarantees that the component held by the JScrollPane won't scroll appropriately since the JScrollPane mechanics require the use of this.
Either this or you will be required to create a class that extends JPanel and implements the Scrollable interface, and this will require far more work, and completely unnecessary work.
Instead you really are forced to learn how to use and then use an appropriate mix of layout managers to have your JPanels hold and display their components. Note that you can nest JPanels, each using its own layout, thereby easily creating complex but easy to maintain GUI's. Please check the layout manager tutorial for more on this.
Adding a JPanel to a JScrollPane is easy. Either pass the JPanel into the JScrollPane's constructor: JScrollPane scrollpane = new JScrollPane(myPanel); or else pass the JPanel into the JScrollPane's viewport view via setViewportView(myPanel). Here's the JScrollPane tutorial for more on this, and the general Swing tutorials.

How do I change a JButton height if I'm using the seaglass look and feel?

I'm using the seaglass look and feel in my application. How do I set the height for a JButton?
It seems like there is no way to have a custom height. I took a look at the documentation:
http://seaglass.googlecode.com/svn/doc/client-properties.html
and I tought I had to use JComponent.sizeVariant = scale to solve the problem, but it doesn't work.
How can I solve this?
Thanks trashgod, I tried this:
try {
UIManager.setLookAndFeel("com.seaglasslookandfeel.SeaGlassLookAndFeel");
} catch(Exception e) {
e.printStackTrace();
}
JButton button = new JButton("Test");
button.putClientProperty("JComponent.sizeVariant", "scale");
JPanel panel = new JPanel(new BorderLayout());
panel.add(button);
panel.setPreferredSize(new Dimension(500, 400));
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
but doesn't seem to work either. Thanks anyway for your effort.
As shown here, here and here, the JComponent.sizeVariant property value is a String, e.g. "mini", "small", "regular" and "large". For "scale" to work, the enclosing panel's layout must allow the component to resize. In the variation below, GridLayout is used:
f.add(variantPanel("scale"));
…
private static JPanel variantPanel(String size) {
JPanel variantPanel = new JPanel(new GridLayout());
…
return variantPanel;
}
Your frame contains one panel. When you pack the frame the panel will be sized at 500x400, i.e., its preferred size. Your panel uses a BorderLayout. BorderLayout does not use the button preferred size. It will expand the button to fill the entire panel size. Try using a layout for your panel that respects the preferred size of its components, e.g., FlowLayout. If you want to change the button size you can then set the button's preferred size.

Java Layout for scrollable panels

I am trying to create a JPanel that is resizable & scrollable and contains x smaller inner panels. Each inner panel can be as wide as it wants/needs. BUT the depth should be a preferred size.
Like:
So far my code is:
public class TestSize {
public static void main(String[] args) {
JFrame F = new JFrame();
F.setVisible(true);
JPanel P = new JPanel();
P.setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(P);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setPreferredSize(new Dimension(900,900));//.setBounds(50, 30, 300, 50);
JPanel S = new JPanel();
S.setBackground(Color.GREEN);
S.setPreferredSize(new Dimension(900,200));
JPanel S2 = new JPanel();
S2.setBackground(Color.GREEN);
S2.setPreferredSize(new Dimension(900,200));
P.add(S,BorderLayout.NORTH);
P.add(S2,BorderLayout.NORTH);
F.add(scrollPane);
F.pack();
F.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
But when I have added a single inner panel it fills all the space vertically - which is not what I want:
//P.setLayout(new BorderLayout());
Why did you set the layout to a BorderLayout? You can only add 1 component to the NORTH. Is that what you want? Read the section from the Swing tutorial on Using Layout Managers and pick a more appropriate layout manager. Bookmark the tutorial link as it provides the basics for Swing programming.
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
Why did you set these properties? These are the default values.
scrollPane.setPreferredSize(new Dimension(900,900));
Why would you set the height to be 900. You only want the scrollpane to contain components of height 200? In general you should NOT be setting the preferred size. Let the frame.pack() method do its job.
S.setBackground(Color.GREEN);
Why would you set the background color of both panels to be the same. How can you tell if the two panels get added? Make them different color for an easy visual.
In BoxLayout, there are different methods of using invisible components as filler. I don't think you will want to use a "rigid area", since I think you want to have a variable number of inner panels. You may want to try using vertical glue or custom Box.Filler.
Another solution might be to put a JPanel between your JFrame and your ScrollPane that uses a BorderLayout, and put the scrollpane in the BorderLayout.NORTH of that panel. Components in BorderLayout.NORTH get resized horizontally, but they do not get resized vertically. Essentially, they just get pushed to the top of the panel.
Edit:
I think you will want something like this:
JFrame F = new JFrame();
F.setVisible(true);
F.setLayout(new BorderLayout());
JPanel P = new JPanel(new BoxLayout(P, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(P);
JPanel S = new JPanel();
S.setBackground(Color.GREEN);
JPanel S2 = new JPanel();
S2.setBackground(Color.BLUE);
P.add(S);
P.add(S2);
F.add(scrollPane, BorderLayout.NORTH);
F.pack();
F.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
You said you want it resizeable, so I don't see why you would set the preferred size of the frame. This way it will just fit to the panels inside.

JTabbedPane in JPanel?

I have a simple problem when I want to add tabs in my jpanel. The alignment of the tabs get horizontal instead of vertical, wich looks like crap =/.
It looks like this:
If I discard the panel instead and add the tabbedPane directly to the frame, everything works fine.
If you uncomment the three lines of code and remove the getContentPane().add(jtp); you can reproduce my probleme.
working Code:
public class TabbedPane extends JFrame
{
public TabbedPane()
{
setTitle("Tabbed Pane");
setSize(300, 300); // set size so the user can "see" it
JTabbedPane jtp = new JTabbedPane();
// JPanel panel = new JPanel();//uncomment all three lines
// panel.add(jtp);
// getContentPane().add(panel);
getContentPane().add(jtp);//remove me
JPanel jp1 = new JPanel();// This will create the first tab
JPanel jp2 = new JPanel();// This will create the second tab
JLabel label1 = new JLabel();
label1.setText("This is Tab 1");
jp1.add(label1);
jtp.addTab("Tab1", jp1);
jtp.addTab("Tab2", jp2);
JButton test = new JButton("Press");
jp2.add(test);
setVisible(true); // otherwise you won't "see" it
}
public static void main(String[] args)
{
TabbedPane tab = new TabbedPane();
}
}
Thanks a lot!
If I discard the panel instead and add the tabbedPane directly to the frame, everything works fine.
The default layout of JPanel is FlowLayout, which "lets each component assume its natural (preferred) size." The default layout of JFrame is BorderLayout, the CENTER of which ignores preferred size. In either case, invoking setSize() precludes the layout from functioning initially; re-size the frame to see the effect. Instead, use pack(), which "Causes this Window to be sized to fit the preferred size and layouts of its subcomponents."
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true); // otherwise you won't "see" it
There are many things I would change in that code, starting with the recommendations of #trashgod. OTOH this is the minimal change needed in order to stretch the tabbed pane to the width/height of the parent container.
// give the panel a layout that will stretch components to available space
JPanel panel = new JPanel(new GridLayout());//uncomment all three lines
panel.add(jtp);
getContentPane().add(panel);
//getContentPane().add(jtp);//remove me
For more details see this answer.
Well firstly you can try this:
JPanel panel = new JPanel();//uncomment all three lines
panel.setLayout(new GridLayout());
JPanel jp1 = new JPanel();// This will create the first tab
JPanel jp2 = new JPanel();// This will create the second tab
JLabel label1 = new JLabel();
label1.setText("This is Tab 1");
jp1.add(label1);
jtp.addTab("Tab1", jp1);
jtp.addTab("Tab2", jp2);
JButton test = new JButton("Press");
jp2.add(test);
getContentPane().add(jtp);
and in the main:
TabbedPane tab = new TabbedPane();
tab.pack();
tab.setVisible(true);
May I suggest using MigLayout to set layouts, it will make your life easier. Hope it helps.
Try GridbagLayout. Once you have mastered it, you can design UI of any sort with this layout.
I agree with prasanth regarding the use of GridBagLayout
I have gone through this problem once and I solved it by adding the JTabbedPaneto the panel via GridBagLayout, make sure you add the JTabbedPane using the ipadx and ipady according to your requirements in your GridBagConstraints object
e.g.
JPanel myPanel=new JPanel();
myPanel.setLayout(new GridBagLayout());
JTabbedPane jTP=new JTabbedPane();
jTP.add("Tab1",new JPanel());//substitute your component instead of "new JPanel"
GridBagConstraints myConstraints=new GridBagConstraints();
myConstraints.ipadx=400;//streches the component being added along x axis - 200 px on both sides
myConstraints.ipady=600;//streches the component being added along y axis - 200 px on both sides
myPanel.add(jTP,myConstraints);
You can adjust both these properties according to what is perfect for your need

Categories