I want to display a vertical list of JCheckBox-es in a JPanel. But I have decided to wrap each JCheckBox with a JPanel, (thinking that i would need it in future). and i am going to stack these JPanels(containing one JCheckBox each) vertically in another JPanel using BoxLayout.
The BoxLayout is working as expected without any vertical space in between the JPanels added to them. My problem is with these inner JPanels containing individual checkbox. there is a considerable amount of space around the checkbox for each panel. I want to wrap these checkboxes tightly, so that the size of jcheckbox and that of the corresponding jpanel containing them are equal.
for these individual jpanel i have tried layouts - flowlayout and default layout. both didnt help.
How can i fix this? i just simply set the flowlayout and add the jcheckbox directly to the jpanel. no other code i have used.
I am adding an example code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TryBox implements Runnable{
/**
* #param args
*/
public static void main(String args[])
{
SwingUtilities.invokeLater(new TryBox());
}
public void run()
{
class InnerPanel extends JPanel
{
public InnerPanel(int i) {
// TODO Auto-generated constructor stub
setLayout(new FlowLayout());
setBackground(new Color(i*50, i*50, i*50));
add(new JCheckBox("CheckBox "+i));
}
}
JPanel outerPanel = new JPanel();
outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
for(int i=0;i<5;i++)
{
outerPanel.add(new InnerPanel(i));
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane sp = new JScrollPane(outerPanel);
frame.setPreferredSize(new Dimension(200, 600));
frame.getContentPane().add(new JScrollPane(outerPanel));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
here frame.setPreferredSize(new Dimension(200, 600)); is making the difference. i want the jpanels to reduce to the size of jcheckboxes. i dont want the jcheckboxes to fit into jpanel's size. if any extra vertical space is there in the container i want it to be left free.
The default layout of JPanel is FlowLayout, and the default constructor creates "a default 5-unit horizontal and vertical gap." You can specify no gap:
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
In addition, the JCheckBox UI delegate adds Insets that vary by L&F. I would be wary of changing these: the size is negligible and typically required to accommodate selection indication.
Did you try setting the margin and border insets to 0 (on the Swing components)?
Related
I am currently working on a N-Body simulation and I have made particles move on a black screen. My current problem is that there is no way of controlling it.
My plan:
Each color stands for a different JPanel. The blue one should contain the buttons and text fields, the red one the viewport.
But with my small knowledge in Java, I didn't succeed in creating this. I first tried with setBounds and setLayoutManager(null), in vain.
My structure goes like that:
Window class extends JFrame
Simulation class creating blueJPanel class (extends JPanel) and redJPanel,
adds them to the window.
But this is garbage code... So how would you draw these simple panels on top of each other?
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.
As I said in my comment, you create two JPanels. Here's an example.
Here's the complete runable code to create this example.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BorderLayoutExampleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new BorderLayoutExampleGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("BorderLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createButtonPanel(), BorderLayout.NORTH);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.setPreferredSize(new Dimension(600, 100));
panel.setBackground(Color.blue);
// Add the buttons and text fields
return panel;
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.setPreferredSize(new Dimension(600, 380));
panel.setBackground(Color.red);
// Add the drawing code
return panel;
}
}
I am trying to create a simple Java Swing GUI that consists of a panel on top and tabs in the center. I want the top panel to remain its preferred size and the tabs to take up the remaining space so I used a BorderLayout. The content of the tab can be tall so I put the tab component into a scroll pane.
Everything seems to work the way I expect (with respect to component sizing and scroll bar behavior when I resize the frame) except that my packed frame is 12 pixels too tall (and possibly 16 pixels too wide). Would someone please explain what is going on and how to resolve it. Somehow when the pack is sizing all of the components, something is smart enough to (mostly) respect the screen size. I am using Java 8 on Windows 7 with a screen resolution of 1920 x 1200.
Below is my test code and the output it produces.
Code:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public final class SizeTest
{
public static void main(final String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGui();
}
});
}
private static void createAndShowGui()
{
final JPanel topPanel = new JPanel();
topPanel.setBorder(BorderFactory.createTitledBorder("Top"));
topPanel.setPreferredSize(new Dimension(800, 150));
final JPanel centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createTitledBorder("Center"));
centerPanel.setPreferredSize(new Dimension(800, 1300));
final JScrollPane scrollPane = new JScrollPane(centerPanel);
final JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab", scrollPane);
final JPanel mainPanel = new JPanel(new BorderLayout(0, 10));
mainPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.add(tabbedPane, BorderLayout.CENTER);
final JFrame mainFrame = new JFrame("Size Test");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(mainPanel);
mainFrame.pack();
System.err.println("***** Frame Size: " + mainFrame.getSize() + ", Screen Size: "
+ Toolkit.getDefaultToolkit().getScreenSize() + ", Maximum Window Bounds: "
+ GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds());
mainFrame.setVisible(true);
}
}
Output:
***** Frame Size: java.awt.Dimension[width=816,height=1212], Screen Size: java.awt.Dimension[width=1920,height=1200], Maximum Window Bounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1156]
If you're going to stuff around with setPreferredSize, be prepared for things to go astray.
The first thing I would do, is seriously reconsider using setPreferredSize.
Because of the way the API works, JScrollPane will use the preferredSize of the component to make determinations about it's own size. You can change this by implementing the Scrollable interface, which allows you to return the preferredScrollableViewportSize, which JScrollPane will use instead when determing how large it needs to be
You see Scrollable demonstrated here and here and lots of other places if you do some searching
I am creating a program in which when a person click on label it will take you to a 2nd panel which will have 2 tabs. The problem is when I click on image label I only see blank window with no tabs and nothing in it.
import java.awt.*;
import static java.awt.Font.BOLD;
import java.awt.event.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.*;
import javax.swing.Timer;
import javax.swing.border.*;
import javax.swing.event.*;
public class hotels extends JFrame{
JButton hotel;
JLabel image;
JTabbedPane tabbed,tabbed1;
JPanel panel;
JPanel panel1;
Container pane;
public hotels(){
panel=new JPanel();
panel.setBackground(Color.cyan);
hotel=new JButton();
hotel.setText("Hotels");
Font myFont = new Font("Serif", Font.BOLD, 18);
hotel.setFont(myFont);
panel.setLayout(null);
panel.add(hotel);
hotel.setBounds(50, 80, 100, 40);
image=new JLabel();
image.setBounds(50,1,80,80);
image.setBorder(BorderFactory.createLineBorder(Color.yellow));
image.setBackground(Color.white);
image.setIcon(new ImageIcon("2.gif"));
panel.add(image);
panel1=new JPanel();
tabbed=new JTabbedPane();
tabbed.add( "Round Trip",panel1);
tabbed.add("One Way",panel1);
panel1.setVisible(false);
panel1.revalidate();
panel.revalidate();
panel1.repaint();
panel.repaint();
pane=getContentPane();
pane.add(tabbed);
pane.add(panel1);
pane.add(panel);
image.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
if (e.getSource()==image){
panel1.show();
panel.setVisible(false);
panel1.setVisible(true);
tabbed.setVisible(true);
}
}
});
}
public static void main(String[] args) {
hotels mw=new hotels();
mw.setVisible(true);
mw.setSize(400, 400);
}
}
pane.add(tabbed);
pane.add(panel1);
pane.add(panel);
The above code attempts to add 3 children to the Content pane's - the Content pane by default has a BorderLayout, which cannot have more than 1 component in it's CENTER position - hence the last Component added is the Component that will be seen. Your options are
Use a CardLayout which allows you to change the Panel shown dynamically
Remove all items from the appropriate Container, then add them and revalidate/repaint
Example of 1 in link above. Example of 2 (in the MouseListener):
pane.removeAll();
pane.add(tabbed);//presuming you want tabbed to show now
pane.revalidate();//or invalidate/validate for <1.7 JRE versions
pane.repaint();
There are a series of problems, including the use of null layouts, which will haunt you with no end of problems...
tabbed.add( "Round Trip",panel1);
tabbed.add("One Way",panel1);
The above code is adding the same panel to two different tabs, but since a component can only have a single parent, it will automatically remove the "Round Trip" tab
Then...
pane=getContentPane();
pane.add(tabbed);
pane.add(panel1);
pane.add(panel);
Which removes all the tabs from the tabbed lane (for the same reason above) and, depending on what layout manager your using, may only show panel
You don't need to change the visibility state of your components been managed by the JTabbedPane, as it will take care of all that for you
See How to Use Tabbed Panes for more details
I'm new in Java GUI programming and I have a strange issue with the BoxLayout:
I have an JLabel with an Icon. Added to the label are two JButtons. The Jlabel is placed in the CENTER position of the BorderLayout from a JFrame. Now I want that these two JButtons are always in the center of the JLabel even when I resize the JFrame. With setAlignmentX() the Jbuttons are centered horizontally , but there is no solution with setAlignmentY() for the vertical direction.
here is the code:
package footballQuestioner;
import java.awt.BorderLayout;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Houdini {
public static void main(String[] args) {
JFrame frame = new House();
}
}
class House extends JFrame {
private JLabel label = new JLabel(
new ImageIcon(
"C:\\Users\\laudatio\\Documents\\Java\\MyProject\\src\\footballQuestioner\\footballfield.jpg")
);
private JButton one=new JButton("one");
private JButton two=new JButton("two");
public House() {
label.setLayout(new BoxLayout(label, BoxLayout.Y_AXIS));
label.add(one);
label.add(two);
one.setAlignmentX(CENTER_ALIGNMENT);
one.setAlignmentY(CENTER_ALIGNMENT);
two.setAlignmentX(CENTER_ALIGNMENT);
two.setAlignmentY(CENTER_ALIGNMENT);
setLayout(new BorderLayout());
setLocation(300, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(true);
add(label,BorderLayout.CENTER);
pack();
setVisible(true);
}
}
Please Help! :-((((
but there is no solution with setAlignmentY() for the vertical direction.
Use "glue" before and after your two components. See the section from the Swing tutorial on How to Use Box Layout for more information and examples.
Although MadProgrammers comment to use a GridBagLayout is an easier solution, but knowing about "glue" and "struts" can be helpful for customizing the layout of a BoxLayout.
Can somebody please help me understand why my custom JComponent 'Bar', only displays when added directly to the JFrame, and not when added to a JPanel (which is then added to the JFrame)?
Thanks!
package main;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Board {
public void start(){
JFrame frame = new JFrame();
JButton button1 = new JButton("Button 1");
Bar statusbar = new Bar();
JLabel status = new JLabel("Status: ");
JPanel topPanel = new JPanel();
topPanel.add(status);
topPanel.add(statusbar);
JPanel mainPanel = new JPanel();
mainPanel.add(button1);
mainPanel.add(statusbar);
frame.getContentPane().add(BorderLayout.NORTH, topPanel);
frame.getContentPane().add(BorderLayout.SOUTH, mainPanel);
frame.getContentPane().add(BorderLayout.CENTER, statusbar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200,100);
frame.setVisible(true);
}
}
Here is my Bar Class...
package main;
import java.awt.Graphics;
import javax.swing.JComponent;
public class Bar extends JComponent{
public void paint(Graphics g){
g.fillRect(0, 0, 100, 10);
}
}
You're adding statusbar to several different places in the component tree, Swing doesn't deal with that well (or at all).
Create a separate Bar instances each time you use it, if you want their display to be synchronized, they should share the same model.
Edit
Ah, on a second glance, the problem here is that you never set a size (or preferred size) for the Bar components, so they get squished to 0 by the layout manager.
Try:
public static class Bar extends JComponent {
private Bar() {
setPreferredSize(new Dimension(25, 5));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(0, 0, 100, 10);
}
}
You should also add a frame.pack() before display.
(the multiple references to the same component thing is still true, too)
The dimension of the custom component is (0, 0).
When added to a container with a BorderLayout layout manager, it will expand to fill the available space, and therefore become visible.
When added to a container with a FlowLayout layout manager, it will not expand and will instead remain at its preferred size (i.e. (0, 0)). And therefore, will not become visible, albeit it is still there.
This explains why the custom component is only displayed when added directly to the JFrame, since it uses a BorderLayout layout manager, whereas a JPanel uses a FlowLayout layout manager.