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.
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;
}
}
Currently, the problem I am trying to solve is how I get both my image and button to show up.
When I have the following line in the code the image shows up but when I remove it my image doesn't display but the button does:
setLayout (new FlowLayout()) ;
without the line of code
with the line of code
Images for example ^
import java.awt.*;
public class Panel extends JFrame {
private ImageIcon FirstPageImage;
private JLabel FirstPageLabel;
private JLayeredPane SignupButtonLayer;
private JButton Button;
public Panel(){
setLayout (new FlowLayout()) ;
FirstPageImage = new ImageIcon(getClass().getResource("FirstPageAnimationUsing.gif"));
FirstPageLabel = new JLabel(FirstPageImage);
FirstPageImage.setImage(FirstPageImage.getImage().getScaledInstance(343,820,Image.SCALE_DEFAULT));
add(FirstPageLabel);
Button = new JButton();
SignupButtonLayer = new JLayeredPane();
Button.setOpaque(true);
Button.setBackground(Color.cyan);
Button.setBounds(94,617,159,82);
SignupButtonLayer.add(Button, JLayeredPane.DEFAULT_LAYER);
add(SignupButtonLayer);
}
public static void main(String[] args) {
Panel gui = new Panel();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setVisible(true);
gui.pack();
gui.setTitle("Reminder App");
gui.setSize(360,850);
}
}
Refer to How to Use Layered Panes.
You need to give the JLayeredPane a preferred size. Since your JLayeredPane contains only a single JButton, that size should be big enough to display the entire JButton.
The arguments to method setBounds – that you call on Button – are relative to its container, i.e. SignupButtonLayer. Setting the x to 94 and the y to 617 means that Button is placed outside of the bounds of SignupButtonLayer. Hence you don't see it. In the below code, I set x and y both to 0 (zero) so that the top, left corner of Button aligns with the top, left corner of SignupButtonLayer.
No need to explicitly call method setOpaque(true) for Button since that is the default, anyway.
Either call pack() – which is usually preferred – or setSize() but don't call both.
setVisible(true) should be called only once your GUI is completely built. In the below code I call it after calling pack() and setTitle().
I suggest that you try to adhere to Java naming conventions.
I also suggest that try not to name your classes the same as classes in the JDK. I am referring to Panel.
The below code simply resolves your problem, i.e. displaying both the image and the button together – while using FlowLayout for the [content pane of the] JFrame. Notice that the preferred size of SignupButtonLayer is slightly larger than the size arguments in method setBounds.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
public class Panel extends JFrame {
private ImageIcon FirstPageImage;
private JLabel FirstPageLabel;
private JLayeredPane SignupButtonLayer;
private JButton Button;
public Panel() {
setLayout(new FlowLayout());
FirstPageImage = new ImageIcon(getClass().getResource("FirstPageAnimationUsing.gif"));
FirstPageLabel = new JLabel(FirstPageImage);
FirstPageImage.setImage(FirstPageImage.getImage().getScaledInstance(343, 820, Image.SCALE_DEFAULT));
add(FirstPageLabel);
Button = new JButton();
SignupButtonLayer = new JLayeredPane();
SignupButtonLayer.setPreferredSize(new Dimension(160, 90));
// Button.setOpaque(true);
Button.setBackground(Color.cyan);
Button.setBounds(0, 0, 159, 82);
SignupButtonLayer.add(Button, JLayeredPane.DEFAULT_LAYER);
add(SignupButtonLayer);
}
public static void main(String[] args) {
Panel gui = new Panel();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.pack();
gui.setTitle("Reminder App");
// gui.setSize(360, 850);
gui.setVisible(true);
}
}
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 am attempting to learn more about creating more dynamic GUI's. I am hoping to add different panels with different content and as you press buttons on one main panel, it changes the adjacent panels. I have added two panels and some buttons and when I test the program, it displays correctly. The problem is when I add a JTextField (or JTextArea) the panels are blank and there are no buttons. The strange thing is I haven't added the JTextField to either panel. I have only created a global variable. If I comment it out, the program runs correctly. Am I missing something very simple?
Here is the gameWindow class that has the JTextField
package rpgcreator;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
class gameWindow extends JPanel {
JPanel startWindowPanel;
JPanel settingsPanel;
JPanel characterPanel;
JPanel scenarioPanel;
JPanel mapPanel;
JButton CharacterButton = new JButton("Create your character");
JButton StoryButton = new JButton("Choose your Story line");
JButton MapButton = new JButton("Choose your World");
//JTextField nameField = new JTextField(15); //comment or uncomment to see issue
public gameWindow() {
setLayout(new GridLayout(0,2,5,0));
startWindowPanel = new JPanel(new FlowLayout());
settingsPanel = new JPanel(new GridLayout(2,1));
startWindowPanel.setBackground(Color.blue);
settingsPanel.setBackground(Color.black);
startWindowPanel.add(MapButton);
startWindowPanel.add(StoryButton);
startWindowPanel.add(CharacterButton);
add(startWindowPanel);
add(settingsPanel);
}
}
Here is main
package rpgcreator;
import javax.swing.JFrame;
public class RPGCreator extends JFrame{
private static void mainWindow(){
RPGCreator mainwindow = new RPGCreator();
mainwindow.setSize(1200, 800);
mainwindow.setResizable(false);
mainwindow.setLocationRelativeTo(null);
mainwindow.setTitle("RPG Creator");
mainwindow.setVisible(true);
mainwindow.add(new gameWindow());
mainwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
// TODO code application logic here
mainWindow();
}
}
setVisible should go at the end. You're currently setting visible to true, and then adding a panel.
mainwindow.setVisible(true);
mainwindow.add(new gameWindow());
Put setVisible at the end after setDeaultCLoseOperation
I'm not entirely sure why it does it, maybe someone else can explain.
What I do know, is I usually call pack() which seems to make your problem go away.
private static void mainWindow(){
final RPGCreator mainwindow = new RPGCreator();
mainwindow.setMinimumSize(new Dimension(1200, 800));
mainwindow.setResizable(false);
mainwindow.setTitle("RPG Creator");
mainwindow.setVisible(true);
mainwindow.add(new gameWindow());
mainwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainwindow.pack(); //This usually goes after you've added all of your components
mainwindow.setLocationRelativeTo(null);
}
Some notes:
I had to change to mainwindow.setMinimumSize(new Dimension(1200, 800)); to avoid the frame looking squashed. Although I would usually let the layout manager deal with the sizes of things.
Call setLocationRelativeTo(null) after you call pack() so that it has the desired effect. Again not sure why, but I've learnt that through some hardship.
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)?