Hi i am beginner to java and doing small GUI using GridBagLayout. See the attached code and also the output . what i want is to place the JButtons on top left corner as per the position assigned in gridx and gridy . But it placing components in center instead of top left as expected , if i use Insets , gridx /gridy all that is working but not from proper coordinates so please see attached code and image and guide me about it
public rect()
{
JPanel panel = new JPanel( new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
JButton nb1= new JButton("Button1 ");
JButton nb2= new JButton("Button2 ");
gbc.gridx=0;
gbc.gridy=0 ;
panel.add(nb1, gbc);
gbc.gridx=1;
gbc.gridy=1;
panel.add(nb2, gbc);
panel.setVisible(true);
JFrame frame = new JFrame("Address Book ");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300 );
frame.add(panel);
frame.setVisible(true);
}
OUTPUT : want these buttons on top left please guide me
I think the problem is more the use of setSize(..), you should rather use appropriate LayoutManager and call pack() on JFrame instance after adding all components to JFrame and before setting JFrame visible, also no need for panel.setVisible(..):
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JPanel panel = new JPanel(new GridBagLayout());
JButton nb1 = new JButton("Button1 ");
JButton nb2 = new JButton("Button2 ");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(nb1, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
panel.add(nb2, gbc);
JFrame frame = new JFrame("Address Book ");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
Related
I'm new here.
I wrote a simple program in Java and for the GUI I'm using GridBagLayout.
The problem is that it doesn't paginate well until I touch the border of the window to resize the Frame. Here are some pictures of what I mean:
The main window before I resize the frame
The main window after I resize the frame
A part of my code:
public class TW2Tempi
{
public static void main(String[] args)
{
MainFrame mf = new MainFrame();
}
}
class MainFrame extends JFrame
{
GridBagConstraints gbc = new GridBagConstraints();
//other variables .....
public MainFrame()
{
super("Calcola i tempi dei tuoi attacchi");
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new GridBagLayout());
setPreferredSize(new Dimension(500, 300));
setMinimumSize(new Dimension(500, 300));
//setResizable(false); //I would also like to add this but then I wouldn't be able to "resize" and see everything (second picture)
//row 1 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//where gbc.gridy = 0
nobile = new JLabel("Orario di arrivo del nobile", SwingConstants.RIGHT);//right align
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
gbc.insets = new Insets(7,10,0,0);
gbc.fill = GridBagConstraints.BOTH;
add(nobile, gbc);
....
Do I have to initialize GridBagConstraints in a different way?
I have Java Swing application with JFrame using BorderLayout and inside it is a JPanel using CardLayout. I am displaying 3 different cards.
If I manually set the size of the JFrame, then the content is displayed like I want it. Label with image is in south east corner.
But when I set it to full screen, there is to much margin:
Here is the code with which I set it to full screen:
Frame[] frames = Frame.getFrames();
JFrame frame = (JFrame) frames[0];
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
//frame.getContentPane().setPreferredSize( Toolkit.getDefaultToolkit().getScreenSize());
frame.setUndecorated(true);
//frame.setSize(600,500);
frame.setVisible(true);
frame.setLayout(new BorderLayout());
Cards are build with Netbeans GUI builder and for layout is set "Free Design".
Application will be whole time in full screen, where I would like that label with the image is SE corner, like it is on resized window(image example 1). Do I need to change layout for this or is it something else?
Note that these UIs have a small border around the entire UI. To remove it, comment out the line:
ui.setBorder(new EmptyBorder(4,4,4,4));
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class ImageInSouthEast {
private JComponent ui = null;
ImageInSouthEast() {
initUI();
}
public void initUI() {
if (ui!=null) return;
ui = new JPanel(new GridBagLayout());
ui.setBorder(new EmptyBorder(4,4,4,4));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = 2;
gbc.weighty = .5;
gbc.weightx = .5;
gbc.gridx = 0;
gbc.gridy = 0;
// first add the labels
for (int ii=1; ii<5; ii++) {
gbc.gridy = ii;
if (ii==4) {
gbc.gridwidth = 1;
}
JLabel l = new JLabel("Label " + ii);
l.setFont(l.getFont().deriveFont(50f));
ui.add(l, gbc);
}
// now for the image!
BufferedImage bi = new BufferedImage(100, 50, BufferedImage.TYPE_INT_RGB);
JLabel l = new JLabel(new ImageIcon(bi));
gbc.anchor = GridBagConstraints.LAST_LINE_END;
gbc.gridx = 2;
gbc.weighty = 0;
ui.add(l, gbc);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ImageInSouthEast o = new ImageInSouthEast();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
If you just want to remove the gap between the text then you could just use BoxLayout.
Set the layout by doing this:
Container pane = frame.getContentPane();
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
pane.add(Box.createHorizontalGlue());
Adding an element
public void add(Component comp, int gap){
//comp is the component that will be added
//gap is the extra space after the last component and this
pane.remove(pane.getComponents().length - 1);
pane.add(Box.createVerticalStrut(gap));
pane.add(comp);
//Obviously pane or frame need to be visible to use this method
}
Add Text by doing this:
add(new JLabel(text), 5);
Add the image by doing this:
JPanel panel = new JPanel();
panel.add(image, BorderLayout.EAST);
panel.setOpaque(false);
add(Box.createHorizontalGlue(),0);
add(panel,0);
I read some questions which stated that GBL is better than the normal GridLayout for positioning the components.
Links:
first , second, Oracle Tutorial
Well so I tried to add some components (buttons) to my GBL but it somehow always centers my components. The only way to seperate the 2 Buttons is to place Dummies into my project which looks awful.
public class GridGUI extends JPanel {
private JButton button;
public GridGUI() {
setLayout(new GridBagLayout());
GridBagConstraints comps = makeGbc(0,1);
JPanel panel = new JPanel();
button = new JButton("Datei speichern");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
panel.add(button);
add(panel,comps);
comps = makeGbc(1,1);
button = new JButton("Datei laden");
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(new JPanel());
panel.add(button);
add(panel,comps);
}
private GridBagConstraints makeGbc(int x, int y) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.gridx = x;
gbc.gridy = y;
gbc.weightx = x;
gbc.weighty = 1.0;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.anchor = (x == 0) ? GridBagConstraints.LINE_START : GridBagConstraints.LINE_END;
gbc.fill = GridBagConstraints.HORIZONTAL;
return gbc;
}
public static void showGUI() {
JFrame frame = new JFrame("Pop-Art-Collage");
frame.getContentPane().add(new GridGUI());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(800, 800);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
showGUI();
}
});
}
}
But I want them to appear at the top of the GUI and not in the center.
Also I tried to resize the buttons by using button.setSize(x,y) but they always stayed the same.
Thanks in advance
Edit:
Okay I tried now the solution I got but I got into some other problems.
GridBagConstraints comps = makeGbc(0,1,20,50,0,0);
button = new JButton("Datei speichern");
button.setPreferredSize(new Dimension(200,25));
add(button,comps);
JButton button2 = new JButton("Datei laden");
button2.setPreferredSize(new Dimension(100,25));
comps = makeGbc(1,1,20,150,0,100);
add(button2,comps);
Here is my problem that I set the prefered size for both buttons the same but it still doesnt show correctly for the second one.
(the 4 Numbers after x,y of makeGbc are the Insets values top,left,bottom,right)
Your buttons are in the middle, not on the top, because you place it there:
gbc.anchor = (x == 0) ? GridBagConstraints.LINE_START : GridBagConstraints.LINE_END;
GridBagConstraints.LINE_END and GridBagConstraints.LINE_START puts components in the centere. Try with:
gbc.anchor = (x == 0) ? GridBagConstraints.FIRST_LINE_START : GridBagConstraints.FIRST_LINE_END;
Also:
try to set size of buttons with setPreferredSize(), GBL with frame.pack() should respect choosen sizes,
you add your buttons to new JPanels, and then to container with GBL, so it place your buttons in center. Add your buttons directly to GridGUI, and it will be placed according to GridBagConstraints(), for example:
button = new JButton("Datei laden");
add(button,makeGbc(1,1));
you use one class field JButton button, for two different buttons, this way you are not able to change first button state, after you change button reference - if you try to change for example text in button, from different part of application, by using button class field you can access only second button.
EDIT
I am not sure what effect you exactly want, but I would try to add your GridGUI first to new JPanel, then to JFrame (in main method):
JFrame frame = new JFrame("Pop-Art-Collage");
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); //add FlowLayout.LEFT,
panel.add(new GridGUI());
frame.getContentPane().add(panel);
Now, the FlowLayout should keep all components to left, and you can control the space between buttons by changing insets. For first button, a would set all inputs to 0, and in second one, the new Insets(0,x,0,0), where x is desired distance. Like this:
add(button,makeGbc(0,1,0,0,0,0));
add(button2,makeGbc(0,1,0,150,0,0));
But I am not sure, how this set of layouts will behave when you add more components, so the easier way, is to use only frame.pack(), without frame.setSize(), and then extend it by adding new components. Then it should be easier to predict how changes will work.
Also pay attention to a fact, that in a example code above, you set different setPreferredSize() for both buttons.
I am new to GUI in java, and have been using this video to learn. When I run the program, the window is blank until I resize it.
public class GUIProgram extends JFrame
{
int screenWidth = 1000; //screenSize.width;
int screenHeight = 800; //screenSize.height;
public GUIProgram()
{
super("DATABASE");
setSize(screenWidth, screenHeight);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel p = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel(new GridBagLayout());
JButton b = new JButton("Button 1");
JButton c = new JButton("Button 2");
p.add(b);
p.add(c);
JCheckBox cb = new JCheckBox("Do you LOVE bacon?");
JCheckBox cb2 = new JCheckBox("Do you LOVE cheese?");
p2.add(cb);
p2.add(cb2);
JLabel label = new JLabel("This is a label");
JTextArea tb = new JTextArea("this is a test area");
JTextField textField = new JTextField("text field");
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(15,15,15,15);
gbc.gridx = 0;
gbc.gridy = 0;
p3.add(label, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
p3.add(tb, gbc);
gbc.gridx = 1;
gbc.gridy = 2;
p3.add(textField, gbc);
add(p, BorderLayout.SOUTH);
add(p3, BorderLayout.CENTER);
add(p2, BorderLayout.NORTH);
}
}
Thanks in advance to anyone who can lend me some advice!
Please let me know if there is some ambiguity in what I'm asking or how I explained myself.
Call setVisible() last, immediately after pack().
Tip:
setSize(screenWidth, screenHeight); Don't set the size of top level containers. Instead layout the content & call pack().
Same Question, different context
It seems I was too hasty in my accepting before, since the problem is still there. The problem? JLabel takes the liberty of expanding its parent panel when content is added to it.
It's time for reproducing it per "Hovercraft full of eels"-ses suggestion, and here it is:
import java.awt.*;
import javax.swing.*;
public class TestLabel {
public static void main(String[] args) {
// Var inits
JFrame frame;
JPanel panel;
JLabel label;
Container pane;
GridBagConstraints gbc = new GridBagConstraints();
// Frame, content pane, layout inits
frame = new JFrame("Label Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pane = frame.getContentPane();
pane.setLayout(new GridBagLayout());
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
// Add panels (note gbc weighty and fill carries over all instances)
gbc.weightx = 0.3;
gbc.gridx = 0;
gbc.gridy = 0;
panel = new JPanel();
panel.setBackground(Color.GREEN);
frame.add(panel,gbc);
label = new JLabel("THE PANEL IS NOW DISTORTED TO FIT THIS LABEL WHY IS THIS HAPPENING");
//label = new JLabel("");
label.setOpaque(true);
label.setBackground(Color.WHITE);
panel.add(label);
gbc.weightx = 0.7;
gbc.gridx = 1;
gbc.gridy = 0;
panel = new JPanel();
panel.setBackground(Color.RED);
frame.add(panel,gbc);
gbc.weightx = 0.3;
gbc.gridx = 0;
gbc.gridy = 1;
panel = new JPanel();
panel.setBackground(Color.BLUE);
frame.add(panel,gbc);
gbc.weightx = 0.7;
gbc.gridx = 1;
gbc.gridy = 1;
panel = new JPanel();
panel.setBackground(Color.YELLOW);
frame.add(panel,gbc);
frame.pack();
frame.setSize(800,600);
frame.setVisible(true);
}
}
Results:
As you can see, the green panel is forced wider and throws off my whole layout when text (or, in the original question, and icon) is added to it. I want my layout to remain the same weights, regardless of the content. The reason this came up is because I'm trying to add a scaled image as an icon to the label, as seen in the original question.
Incidentally, setPreferredSize() doesn't seem to work.
Is there a way to fix this?
Original Question
My JLabel element expands dramatically when I add an Icon to it. Why is this happening? Here's the applicable portion of the code:
// Show label and BG color
redLabel.setBackground(Color.RED);
redLabel.setOpaque(true);
// Grab stretched image (already loaded elsewhere in the code) and turn to icon
Img = Img.getScaledInstance(redLabel.getWidth(),12,Image.SCALE_REPLICATE);
ImageIcon icon = new ImageIcon(Img);
// This line throws everything off!
//It's commented out in the first pic, and included in the second.
redLabel.setIcon(icon);
As you can see from the first pic, I've got a label (in red) of width W. What I'm trying to do is stretch my icon to width W and put it in the label.
When I do this, the label expands (by exactly 50 pixels, I think) and also squeezes over the left edge (green). Does anyone have any idea why this is happening?
I've tried several things that are too verbose to explain but can't find the problem :-/
Your component expands because it allocates the necessary space for its Icon.
public class JLabelDemo {
private static BufferedImage bi;
public static void main(String[] args) throws IOException{
loadImage();
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
createAndShowGUI();
}
});
}
private static void loadImage() throws IOException{
bi = ImageIO.read(JLabelDemo.class.getResource("../resource/forever-alone.jpg"));
}
private static void createAndShowGUI(){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
panel.setBackground(Color.YELLOW);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JLabel emptyLabel = new JLabel();
final JLabel textLabel = new JLabel("This label has text only");
final JLabel textAndImageLabel = new JLabel("This label has text and image");
textAndImageLabel.setIcon(new ImageIcon(bi));
panel.add(emptyLabel);
panel.add(textLabel);
panel.add(textAndImageLabel);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
System.out.println("Empty label dimensions - " + emptyLabel.getSize());
System.out.println("Text only label dimensions - " + textLabel.getSize());
System.out.println("Image width: " + bi.getWidth() + ", Image height: " + bi.getHeight());
System.out.println("Text and image label dimensions - " +textAndImageLabel.getSize());
}
}
The following is outputted to console:
Empty label dimensions - java.awt.Dimension[width=0,height=0]
Text only label dimensions - java.awt.Dimension[width=129,height=16]
Image width: 194, Image height: 180
Text and image label dimensions - java.awt.Dimension[width=363,height=180]
Consider using a JLayeredPane to add components in layers. There are trips and traps though when doing this in matters of opacity, size and position of components added.
For example,
import java.awt.*;
import javax.swing.*;
public class TestLabel {
private static final Dimension SIZE = new Dimension(800, 600);
public static void main(String[] args) {
GridBagConstraints gbc = new GridBagConstraints();
JPanel defaultPane = new JPanel();
defaultPane.setLayout(new GridBagLayout());
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
// Add panels (note gbc weighty and fill carries over all instances)
gbc.weightx = 0.3;
gbc.gridx = 0;
gbc.gridy = 0;
JPanel panel = new JPanel();
panel.setBackground(Color.GREEN);
defaultPane.add(panel, gbc);
gbc.weightx = 0.7;
gbc.gridx = 1;
gbc.gridy = 0;
panel = new JPanel();
panel.setBackground(Color.RED);
defaultPane.add(panel, gbc);
gbc.weightx = 0.3;
gbc.gridx = 0;
gbc.gridy = 1;
panel = new JPanel();
panel.setBackground(Color.BLUE);
defaultPane.add(panel, gbc);
gbc.weightx = 0.7;
gbc.gridx = 1;
gbc.gridy = 1;
panel = new JPanel();
panel.setBackground(Color.YELLOW);
defaultPane.add(panel, gbc);
defaultPane.setSize(SIZE);
JLabel label = new JLabel("THE PANEL IS NOW DISTORTED TO FIT THIS LABEL WHY IS THIS HAPPENING");
label.setOpaque(true);
label.setBackground(Color.WHITE);
JPanel northPalettePanel = new JPanel();
northPalettePanel.setOpaque(false);
northPalettePanel.add(label);
JPanel palettePanel = new JPanel(new BorderLayout());
palettePanel.setOpaque(false);
palettePanel.setSize(SIZE);
palettePanel.setLocation(0, 0);
palettePanel.add(northPalettePanel, BorderLayout.NORTH);
JLayeredPane layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(SIZE);
layeredPane.add(defaultPane, JLayeredPane.DEFAULT_LAYER);
layeredPane.add(palettePanel, JLayeredPane.PALETTE_LAYER);
JFrame frame = new JFrame("Label Tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(layeredPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
Java swing is pretty old for me but if I remember well, setting a preferred size (setPreferredSize()) sometime solve these kind of problem ... Also try top lay with setMaximumSize and setMinimumSize.
You can maybe find more information in java documentation:
http://download.oracle.com/javase/tutorial/uiswing/layout/using.html#sizealignment
Regards!