So I'm making sample GUI using outer and inner class. I made a two inner classes. First the parent class which is the "first panel" second I made a child class which is the "second panel" where I add the JButton using GridBagLayout. My problem is it wont move in the location I want. I assigned my gridx = 2 and gridy = 1. But it won't move. Any help will appreciate thanks!
public class Login extends JFrame{
mainPanel mainpanel = new mainPanel(); // I create a class object for mainPanel so I can set as ContentPane.
//Constructor
public Login(){
setSize(500,400);
setTitle("Login Sample");
setVisible(true);
setLocationRelativeTo(null);
getContentPane().add(mainpanel);
//Window Listener
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}//window Closing
});
}
class mainPanel extends JPanel { //InnerClass
firstPanel firstpanel = new firstPanel();
//Constructor
public mainPanel(){
setPreferredSize(new Dimension (500,400));
setLayout(new BorderLayout());
setBorder(BorderFactory.createLineBorder(Color.green, 3));
add(firstpanel);
}
class firstPanel extends JPanel{
//Create Button
JButton loginButton = new JButton("Login");
//Constraints
GridBagConstraints loginConstraints = new GridBagConstraints();
public firstPanel(){
setLayout(new GridBagLayout());
loginConstraints.gridx = 1;
loginConstraints.gridy = 2;
add(loginButton,loginConstraints);
}
}
JButton keep position in the center
The reason your JButton keeps centering itself to the center of the Frame has nothing to with inner class. Every container (e.g. JPanel, JFrame) has a default layout.
The default layout of JPanel is FlowLayout. Under this layout, all components added will be arranged in a linear fashion in a row for as much as possible the panel width can fit. Anything more than the panel's width will be pushed to the next row. The default alignment of flow layout used by the JPanel is FlowLayout.CENTER, that is why when you only add one button, it always center itself.
Since it has a layout governing the positioning of your components, attempts to change the components' positions may become futile.
My problem is it wont move in the location I want. I assigned my gridx = 2 and gridy = 1. But it won't move
If you want your components to move to a specific location specified by you, you can set the layout to null (absolute positioning). However by doing so, you will have to set the location of every components which is added by you manually. If not, the components will not even show up in the frame.
To set a panel's layout to null, you may do this:
JPanel pnlMain = new JPanel();
pnlMain.setLayout(null);
To set the location of the components, we can use setBounds():
JButton btn = new JButton();
btn.setBounds(x, y, width, height); //set location and dimension
However, setting containers' layout to null can give you many unforeseen problems. With the layout being removed and all positioning being hard coded, you are left with little or no control when your program are used in different systems and environment. Various usage by users can also cause unforeseen problems as well (e.g. When user resize your window).
First i want to say that if you just have a component and want it centered, its easy to use BorderLayout and add it(the component) "Center" to the parent. The GridbagLayout is not working like this since you dont have components in gridx = 0 and gridy = 0. The grid is calculated by the components size inside. When you want to do it with the GridBagLayout you have to configure more e.g.
anchor:
Used when the component is smaller than its display area to determine where (within the area) to place the component. Valid values (defined as GridBagConstraints constants) are CENTER (the default), PAGE_START, PAGE_END, LINE_START, LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_END, and LAST_LINE_START.
But i think its to much effort for i guess you want to do:
https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html
Related
I am learning swing from past week, I have some issue with GridBagConstraints to put one button in top left corner but all other buttons in default in GridBagConstraints ?
I am using code that like not original but states the problem
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
class MyPanel extends JPanel
{
JButton menu = new JButton("Menu"), button = new JButton("Puzzle");
GridBagConstraints gbc1 = new GridBagConstraints(), gbc2 = new GridBagConstraints();
private void setup()
{
gbc1.anchor = GridBagConstraints.FIRST_LINE_START;
gbc2.anchor = GridBagConstraints.CENTER;
gbc2.weightx = 1.0;
gbc2.weighty = 1.0;
}
public MyPanel()
{
this.setLayout(new GridBagLayout());
this.setup();
this.button.setPreferredSize(new Dimension(250, 140));
this.add(menu, gbc1);
this.add(button, gbc2);
}
}
#SuppressWarnings("serial")
public class Test extends JFrame
{
public Test()
{
this.setTitle("Test");
this.setContentPane(new MyPanel());
this.setResizable(false);
this.setSize(800, 600);
this.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(() -> new Test());
}
}
output
I want menu is top corner.
I read from here but i did not understand this Could you please explain GridBagConstraints for how to do that.
I Hope that problem is clear to understand, if not please let me know in comments.
EDIT:
#camickr suggestion works but a little problem, the Puzzle Button is not in extract center.
Thanks.
By default the GridBagLayout will display all the components centered horizontally and vertically, unless one of the components has a weightx/weighty value not equal to 0. Then that component will fill the extra space in the frame.
So if you want one component at the "top/left" and one in the "center", you need to:
use the "anchor" constraint. It will be different for both components.
the component in the center will need to use the "weightx/weighty" constraints.
However, an easer solution might be to use a combination of panels with different layout managers.
For example:
JPanel menuPanel = new JPanel( new FlowLayout(FlowLayout.LEFT) );
menuPanel.add(menuButton);
JPanel centerPanel = new JPanel( new GridBagLayout() );
centerPanel.add(puzzle, new GridBagConstraints());
frame.add(menuPanel, BorderLayout.PAGE_START);
frame.add(centerPanel, BorderLayout.CENTER);
So now the "top" of the frame will contain a panel with components displayed from the left and the "center" of the frame will contain your puzzle centered in the remaining space of the frame.
Edit:
I solved it but put gridx and gridy to 0 in center component, but i did not completely understand the setttings
Well I mentioned that you would need to use the gridx/gridy constraints. You should always use those constraints as it is very obvious what grid you want to add the component to. The examples from the tutorial always specify those values.
Using gridx/gridy both equal to 0, does not really make sense. The effect is that you have two components trying to share the same grid.
Remove the setResizable(false) statement and shrink the size of the frame to see how the button repositions itself.
It is not normal that two components share the same grid. Normally you would have the menu on the first row and the button on the second row. This will center the button horizontally in the frame and vertically in the space below the menu.
What you are doi
I am trying to display 2 panels that I have created in separate files one at the top and one at the bottom of my GUI with a button group between them. However, the window is only displaying one panel or the button group at a time. The panels and button group are displaying properly but only the last one added to the frame is being displayed at any given execution.
Here is the current code without any layouts...
package UserGUI;
import javax.swing.*;
import java.awt.*;
public class RealFrame extends JFrame {
JButton Close = new JButton("Close");
JButton Proceed = new JButton("Proceed");
AuthorPanel header = new AuthorPanel();
FreeSpacePanel disk = new FreeSpacePanel();
public RealFrame() {
super();
ButtonGroup Ops = new ButtonGroup();
Ops.add(Close);
Ops.add(Proceed);
JPanel OPS = new JPanel();
OPS.add(Close);
OPS.add(Proceed);
add(disk);
add(OPS);
add(header);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,500);
setVisible(true);
}
}
JFrame uses a BorderLayout by default, so when you do...
add(disk);
add(OPS);
add(header);
You're adding each component to the same location (the CENTRE position), but the BorderLayout will only layout the last one added.
Instead, you should use something more like...
add(disk, BorderLayout.NORTH);
add(OPS);
add(header, BorderLayout.SOUTH);
See How to Use Borders for more details
add(disk);
add(OPS);
add(header);
The default layout manager of the content pane of the JFrame is a BorderLayout. If you don't specify a constraint then the component is added to the BorderLayout.CENTER. Only one component can be added to the CENTER so the only the last component is displayed.
Try:
add(disk, BorderLayout.NORTH);
add(OPS, BorderLayout.CENTER);
add(header, BorderLayout.SOUTH);
to see the difference.
Or try another layout manager on the frame. See How to Use Layout Manager for more information.
I am trying to setup my JPanel's position to the right using i.add(jp, BorderLayout.EAST); but it is not working. Any ideas why? Thanks for the help in advance.
/* INSTANCE DECLARATIONS */
private JTextField tf;//text field instance variable
private JLabel jl2;//label instance variable
/*****************
* WINDOW METHOD *
* ***************/
public void window() {
LoadImageApp i = new LoadImageApp();//calling image class
JFrame gameFrame = new JFrame();//declaration
JPanel jp = new JPanel();
JLabel jl = new JLabel("Enter a Letter:");//prompt with label
tf = new JTextField(1);//length of text field by character
jl2 = new JLabel("Letters Used: ");
jp.add(jl);//add label to panel
jp.add(tf);//add text field to panel
jp.add(jl2);//add letters used
gameFrame.add(i); //adds background image to window
i.add(jp, BorderLayout.EAST); // adds panel containing label to background image panel
gameFrame.setTitle("Hangman");//title of frame window
gameFrame.setSize(850, 600);//sets size of frame
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit when 'x' button pressed
gameFrame.setIconImage(new ImageIcon("Hangman-Game-grey.png").getImage());//set the frame icon to an image loaded from a file
gameFrame.setLocationRelativeTo(null);//window centered
gameFrame.setResizable(false);//user can not resize window
gameFrame.setVisible(true);//display frame
}//end window method
What layout manager does i, your LoadImageApp instance, use? I'm betting it's not BorderLayout. I'm betting that the LoadImageApp class extends JPanel and if so and if you never explicitly set its layout, then it uses a FlowLayout by default, and as you're finding out, FlowLayout doesn't respect the BorderLayout.EAST int constant.
The solution is likely quite simple: make it use a BorderLayout:
setLayout(new BorderLayout());
Edit
You state in comment:
When I set the border layout of i to EAST, my background image shifts to the right also, is there a way to get around that?
No, you're missing the point. You need to set the layout of LoadImageApp to BorderLayout. You're not supposed to add i BorderLayout.EAST. This was never recommended to you.
i.e.,
public class LoadImageApp extends JPanel {
// in the constructor
public LoadImageApp() {
setLayout(new BorderLayout());
}
// .... etc....
}
THe LoadImageApp instance (which I would name loadImageApp, not i), should be added BorderLayout.CENTER, which you were doing before. Please read the layout manager tutorials which you can find here.
I have some panels in a card layout container (no idea if that is correct terminology). I can't find a way to set the location, or size of these panels inside the container. I tried setBounds and setLayout(null) and I still can't get anything to change.
These are my fields and the constructor. I've gotten my frame working and I can see and use the buttons to change cards, but I really can't change much else about the cards. I set the two card panels two have different backgrounds, but they only make a small boarder of color around the button and leave it in the centre of the screen.
I also don't understand why this isn't pasting my code properly... So sorry!
public class TestPanel extends JPanel implements ActionListener {
CardLayout cl = new CardLayout();
private JPanel panelCont = new JPanel();
private JPanel panel1 = new JPanel();
private JPanel panel2 = new JPanel();
private static JButton but1 = new JButton("Change panels");
private static JButton but2 = new JButton("Change back");
public TestPanel() {
panelCont.setLayout(cl);
panel1.add(but1);
panel2.add(but2);
panel1.setBackground(Color.black);
panel2.setBackground(Color.blue);
panelCont.add(panel1, "1");
panelCont.add(panel2, "2");
cl.show(panelCont, "1");
but1.addActionListener(this);
but2.addActionListener(this);
add(panelCont);
}
}
Thanks. I apologise in advance. I'm finding it hard to understand card layout.
A CardLayout respects the preferred size of the panels added to the layout. That is the size will be the size of the largest panel added to the layout.
I set the two card panels two have different backgrounds, but they only make a small boarder of color around the button and leave it in the centre of the screen.
The default layout for a panel is the FlowLayout. A FlowLayout by default has a 5 pixel horizontal/vertical gap around each component. So the preferred size of your panel is the size of the button plus the 5 pixel gap.
The panel is displaying correctly. When you add other components to the panel the size will change as required.
It's not clear where you pack() the enclosing Window. By default, pack() causes a panel having CardLayout to adopt the the size of the largest panel's preferred size, which is determined by the size of its contents. This example uses setPreferredSize() to specify an arbitrary size, but you can override getPreferredSize() as shown here.
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