JButton expanding to take up entire frame/container - java

Hey everyone. I'm trying to make a swing GUI with a button and a label on it. im using a border layout and the label ( in the north field ) shows up fine, but the button takes up the rest of the frame (it's in the center field). any idea how to fix this?

You have to add the button to another panel, and then add that panel to the frame.
It turns out the BorderLayout expands what ever component is in the middle
Your code should look like this now:
Before
public static void main( String [] args ) {
JLabel label = new JLabel("Some info");
JButton button = new JButton("Ok");
JFrame frame = ...
frame.add( label, BorderLayout.NORTH );
frame.add( button , BorderLayout.CENTER );
....
}
Change it to something like this:
public static void main( String [] args ) {
JLabel label = new JLabel("Some info");
JButton button = new JButton("Ok");
JPanel panel = new JPanel();
panel.add( button );
JFrame frame = ...
frame.add( label, BorderLayout.NORTH );
frame.add( panel , BorderLayout.CENTER);
....
}
Before/After
Before http://img372.imageshack.us/img372/2860/beforedl1.png
After http://img508.imageshack.us/img508/341/aftergq7.png

Or just use Absolute layout. It's on the Layouts Pallet.
Or enable it with :
frame = new JFrame();
... //your code here
// to set absolute layout.
frame.getContentPane().setLayout(null);
This way, you can freely place the control anywhere you like.

Again :)
import javax.swing.*;
public class TestFrame extends JFrame {
public TestFrame() {
JLabel label = new JLabel("Some info");
JButton button = new JButton("Ok");
Box b = new Box(BoxLayout.Y_AXIS);
b.add(label);
b.add(button);
getContentPane().add(b);
}
public static void main(String[] args) {
JFrame f = new TestFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

Related

What layout manager should I use

I am making a chat in java and need to display old messages in a JPanel. I need an image and the message that was being sent/received to be displayed, each on its own row. The code that I currently have :
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = new JPanel();
container.setPreferredSize(new Dimension(300, 400));
// Printing five messages
for (int i = 0; i < 5; i++) {
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(300, 40));
p.setBorder(BorderFactory.createLineBorder(Color.BLACK));
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
JLabel img = new JLabel("Image : ");
JLabel txt = new JLabel("This is some text");
p.add(img);
p.add(txt);
img.setAlignmentX(Component.LEFT_ALIGNMENT);
txt.setAlignmentX(Component.LEFT_ALIGNMENT);
container.add(p);
}
f.add(container);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
Result :
Right now I am specifying the width and height of each message which is not so good as it should automatically resize to its content. I feel like there should be a good layout-manager for this but I am new to swing so help is appreciated as I do not know which one to use.
it should automatically resize to its content.
Having text that wraps to a new line is the main problem here.
One way might be to:
use vertical Box - it allows each component to have a different height
wrap the text in HTML - it will allow for the text to wrap
Something like:
import java.awt.*;
import javax.swing.*;
public class Chat extends JPanel
{
private Box messageBox = Box.createVerticalBox();
public Chat()
{
setLayout( new BorderLayout() );
add(messageBox, BorderLayout.PAGE_START);
addMessage("Short message");
addMessage("A longer message that should wrap as reqired onto another line. This should happen dynamically");
}
public void addMessage(String text)
{
JPanel messagePanel = new JPanel( new BorderLayout() );
JLabel label = new JLabel( new ImageIcon("about16.gif") );
messagePanel.add(label, BorderLayout.LINE_START);
JLabel message = new JLabel("<html>" + text + "</html>");
messagePanel.add(message);
messageBox.add(messagePanel);
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Chat");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Chat());
frame.pack();
frame.setSize(200, 100);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}

JLabel automatically centers it self inside GridBagLayout

I'm trying to make a custom JTextField that hosts a JLabel, So I have wrapped the JTextField and the JLabel in a custom Class that extends JPanel
The JPanel layout is set to GridBagLayout since I only need place 2 components vertically. Here is how it looks like
This is the code, I can't spot where I have instructed the GridBagLayout to center the JLabel.
setLayout(new GridBagLayout());
jLabel = new JLabel();
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.VERTICAL;
gbc.gridy = 1;
add(jLabel, gbc);
I want to have the JLabel the same position at shown in the GIF. How can I achieve this? Would also be nice if anyone can point what the exact text size would look good on the JLabel.
the JLabel does not start from line start, nor is it center. It's kinda in between
I'm not sure what your exact code is and how you nest the custom panel in another panel.
But as I mentioned above when you have weird alignment you need to make sure each component has the same x alignment so they can be aligned the same way.
I can't reproduce your problem using the simple example below:
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class SSCCE extends JPanel
{
SSCCE()
{
JPanel box = new JPanel();
box.setLayout( new BoxLayout(box, BoxLayout.Y_AXIS) );
box.setBorder( new LineBorder(Color.RED) );
JTextField textField = new JTextField(10);
//textField.setAlignmentX(JComponent.LEFT_ALIGNMENT);
System.out.println( textField.getAlignmentX() );
box.add( textField );
JLabel label = new JLabel("Some text");
System.out.println( label.getAlignmentX() );
box.add( label );
add( box );
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
But as you can see from the output by default a text field has center alignment and the label left alignment. Try making them both left aligned.
Thanks to VGR in the comments, I have solved this issue by setting the anchor to LINE_STARTS
gbc.anchor = GridBagConstraints.LINE_STARTS;
Edit: Ended up using BoxLayout thanks to camickr for answering with an example.

Background Image covering JComponents

I'm trying to make a registration form for a game(assignment) for school and i have finished it but i wanted to add an image on it but it blocks everything, JButton,JTextField etc.. How can i fix this? EDITED : I MADE THE CODE A LITTLE SHORTER SAME PROBLEM OCCURS.
public class MyGUI {
JLabel xyz;
JButton b1;
public JPanel createContentPane () {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(null);
xyz = new JLabel("Don't have an account? Sign up!");
xyz.setBounds(10,0,390,30);
xyz.setFont(new Font("Lucida Grande", Font.BOLD, 20));
xyz.setLayout(new FlowLayout());
mainPanel.add(xyz);
b1 = new JButton("Create Account");
b1.setBounds(40,540,310,33);
b1.setFont(new Font("Comic San Ms", Font.BOLD , 16));
b1.setForeground(Color.white);
b1.setBackground(Color.blue);
mainPanel.add(b1);
return mainPanel;
}
public static void CreateAndShowGUI() {
JFrame frame = new JFrame("Romaverse ONLINE! REGISTRATION");
Container c = frame.getContentPane();
MyGUI demo = new MyGUI();
c.add(demo.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(480,700);
frame.setVisible(true);
frame.setContentPane(new JLabel(new ImageIcon("C:\\Users\\Admin\\Desktop\\roma.jpg")));
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
CreateAndShowGUI();
}
});
}
}
Here Is the part where i put the image
frame.setContentPane(newJLabel(newImageIcon("C:\\Users\\Admin\\Desktop\\roma.jpg"));
The image doesn't block buttons, it replaces them because you are calling setContentPane. Why are you doing this? You can simply add the image together with all other controls inside the createContentPane method. Note that the order in which controls are added may affect their Z-order.
Check out the Background Panel.
It shows two approaches:
Add the image to a JLabel and then add your components to the label
Do custom painting of the image on a JPanel and then add your components to the panel.
Edit:
Basic code using approach 1:
JLabel background = new JLabel( new ImageIcon(...) );
label.setLayout( new FlowLayout() );
label.add( new JButton("Hello") );
JFrame frame = new JFrame();
frame.add( background );

Hide the scroll bar, but it continue working

I'm trying to hide the vertical bar of a scrollpane, but I want that it continues scrolling vertically. This is my code:
JScrollPane scroll=new JScrollPane(arbol);
scroll.setBounds(35,40, 230, 530);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setBorder(null);
scroll.setOpaque(false);
scroll.getVerticalScrollBar().setBorder(null);
scroll.getViewport().setOpaque(false);
JLabel sep=new JLabel(Imagen("SeparaV.png"));
sep.setSize(scroll.getSize());
sep.setLocation(-17, 0);
sep.setHorizontalAlignment(JLabel.RIGHT);
scroll.add(sep);
Frame.add(scroll);
For me it is good, if it only shows the arrows. So this is what I need:
for me is good if only show the arrows
I assume you mean you don't want to see the bar in the middle that is used to drag the scrollbar. If so then you can use the default Actions of the scrollbar to create a simple panel with only the arrow buttons:
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
public class ScrollPaneSSCCE extends JPanel
{
public ScrollPaneSSCCE()
{
setLayout( new BorderLayout() );
JTable table = new JTable(50, 5);
JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
add(scrollPane);
JScrollBar vertical = scrollPane.getVerticalScrollBar();
JPanel east = new JPanel( new BorderLayout() );
add(east, BorderLayout.EAST);
BasicArrowButton north = new BasicArrowButton(BasicArrowButton.NORTH);
north.setAction( new ActionMapAction("", vertical, "negativeUnitIncrement") );
east.add(north, BorderLayout.NORTH);
BasicArrowButton south = new BasicArrowButton(BasicArrowButton.SOUTH);
south.setAction( new ActionMapAction("", vertical, "positiveUnitIncrement") );
east.add(south, BorderLayout.SOUTH);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("ScrollPaneSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ScrollPaneSSCCE());
frame.setSize(200, 300);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
You will need to check out Action Map Action to understand how this works.

SetVisible(false) changes the layout of my components within my Panel

How do I make the subpanels within my main panel stay where they are when I set one of the subpanels to be invisible?
What I have looks like:
[ (Panel1) (Panel2) (Panel3) (Panel4) ]
When I do panel3.setVisible(false) it then looks like:
[ (Panel1) (Panel2) (Panel4) ]
I would like it to look like:
[ (Panel1) (Panel2) (Panel4) ]
I am using the GridBagLayout and my mainPanel declaration looks like:
final JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
and I add an new panel like:
final JTextField valueTextField = new JTextField();
valueTextField.setPreferredSize(new Dimension(80, 25));
valueTextField.setName("Value");
c.gridx =0;
panel.add(valueTextField, c);
I'll provide more code if needed and I don't care which layout I use as long as it gets me what I want.
I suggest using a CardLayout within the individual cells, and instead of setting it to invisible, switch to an empty panel instead.
The code below demonstrates this. Within hidePanel() there are two options to hide the cell with the CardLayout route currently enabled.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class InvisiblePanels {
public static void main(String... args) throws Exception {
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
frame.add(new MyPanel(), c);
c.gridx = 1;
frame.add(new MyPanel(), c);
c.gridx = 2;
frame.add(new MyPanel(), c);
frame.pack();
frame.setVisible(true);
}
private static class MyPanel extends JPanel {
CardLayout layout;
public MyPanel() {
layout = new CardLayout();
setLayout(layout);
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
hidePanel();
}
});
add(button, "visible");
add(new JPanel(), "invisible");
layout.show(this, "visible");
}
public void hidePanel() {
// setVisible(false);
layout.show(this, "invisible");
}
}
}
I believe all the layout manager respect the visibility of a component and don't include invisible components in the preferred size and layout calculations.
One solution might be to wrap all your panels in a panel using the OverlayLayout:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class OverlayLayoutInvisible
{
public static void main(String[] args)
{
JPanel panel = new JPanel();
panel.add( createPanel("Button 1") );
panel.add( createPanel("Button 2") );
panel.add( createPanel("Button 3") );
panel.add( createPanel("Button 4") );
panel.add( createPanel("Button 5") );
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( panel );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static JPanel createPanel(String text)
{
JButton button = new JButton( text );
button.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Component c = (Component)e.getSource();
c.setVisible(false);
}
});
InvisibleComponent ic = new InvisibleComponent( button );
JPanel panel = new JPanel();
panel.setLayout( new OverlayLayout(panel) );
panel.add( ic );
panel.add( button );
return panel;
}
public static class InvisibleComponent extends JComponent
{
private Component master;
public InvisibleComponent(Component master)
{
this.master = master;
setAlignmentX( master.getAlignmentX() );
setAlignmentY( master.getAlignmentY() );
}
public Dimension getPreferredSize()
{
return master.getPreferredSize();
}
}
}
You might be able to tweak GridLayout (do you have an SSCCE?)
Otherwise:
Put Panel3 and Panel4 together in a single panel that you add to the GridBagLayout. Then setup the new Panel in a Layout like FlowLayout (aligned Left with a preferred size), BorderLayout, GridLayout, etc.

Categories

Resources