I have a JPanel that encapsulates two JPanels, one on top of the other.
The first holds two JLabels which hold the playing cards.
The second holds the player's text (name and score).
However, when I remove the player's cards, the lower JPanel moves up to the top, which i would prefer that it not do. Is there a way to keep it in place regardless of whether the top JPanel is occupied or not?
Thanks
What layout managers are you using? The default layout manager for a JPanel is a FlowLayout which render child components one after the other.
Maybe you could set the root JPanel to have a BorderLayout. Then set the top JPanel to the root panel's "top" spot:
JPanel rootPanel = ...;
JPanel topPanel = ...;
rootPanel.add(topPanel, BorderLayout.TOP);
Then set a minimum size for your top JPanel:
topPanel.setMinimumSize(new Dimension(someWidth, someHeight));
And add the second panel to the bottom or middle spot:
rootPanel.add(secondPanel, BorderLayout.CENTER);
Check out http://java.sun.com/docs/books/tutorial/uiswing/layout/border.html
I had time to do an example:
public class TestJpanel extends JFrame {
public TestJpanel() {
this.setLayout( new BorderLayout() );
final JLabel card1 = new JLabel( "card1" );
final JLabel card2 = new JLabel( "card2" );
final JPanel topPanel = new JPanel();
topPanel.setPreferredSize( new Dimension( 1024, 100 ) );
topPanel.add( card1 );
topPanel.add( card2 );
this.add( topPanel, BorderLayout.NORTH );
JPanel centerPanel = new JPanel();
final JButton hideCardsButton = new JButton( "Hide cards" );
hideCardsButton.addActionListener( new ActionListener() {
#Override
public void actionPerformed( ActionEvent e ) {
if ( topPanel.getComponentCount() == 0 ) {
topPanel.add( card1 );
topPanel.add( card2 );
hideCardsButton.setText( "Hide cards" );
} else {
topPanel.removeAll();
hideCardsButton.setText( "Show cards" );
}
topPanel.validate();
topPanel.repaint();
}
} );
centerPanel.add( hideCardsButton );
this.add( centerPanel, BorderLayout.CENTER );
}
public static void main( String[] args ) {
TestJpanel window = new TestJpanel();
window.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
window.setSize( 1024, 768 );
window.setVisible( true );
}
}
Note that this code if full of bad practices but helps demonstrate what I want with a short number of lines.
Related
I want to add on the same frame multiple instances of the same component which extends JPanel but unfortunately when I compile the code it adds on the frame only the last instance.
Here is my main class which extends JFrame:
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Interface extends JFrame
{
JPanel jPanel;
JPanel jPanel02;
JPanel jPanel03;
public static void main( String[] args )
{
new Interface( );
}
public Interface( )
{
setTitle( "Tile" );
setSize( 300, 300 );
setVisible( true );
jPanel = new MyOwnJPanel( "My Own JPanel 01" );
jPanel02 = new MyOwnJPanel( "My Own JPanel 02" );
jPanel03 = new MyOwnJPanel( "My Own JPanel 03" );
add( jPanel );
add( jPanel02 );
add(jPanel03);
}
}
And here is the class which extends JPanel:
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
*/
public class MyOwnJPanel extends JPanel
{
JLabel jLabel;
MyOwnJPanel(String headerTitle){
jLabel = new JLabel( headerTitle );
add(jLabel );
}
}
So, even though I add all three panels, on the frame appears only one, the last one.
Thank you!
I think you are adding jpanels at the same location so you are seeing the last one. Try setting borderlayout to jframe. I think you will see all panels.
Edit: Working code is below:
setTitle( "Tile" );
setSize( 300, 300 );
setVisible( true );
setLayout(new BorderLayout());
jPanel = new MyOwnJPanel( "My Own JPanel 01" );
jPanel02 = new MyOwnJPanel( "My Own JPanel 02" );
jPanel03 = new MyOwnJPanel( "My Own JPanel 03" );
add( jPanel, BorderLayout.CENTER );
add( jPanel02, BorderLayout.NORTH );
add(jPanel03, BorderLayout.SOUTH);
I am developing a Swing application using BorderLayout to position the components. Since BorderLayout.CENTER positions components to whatever is left after the other components are placed, and that fact is making my GUI look weird, I was wondering if there was a way to position components to true center, rather than in between the two sides. Since BorderLayout spaces make a component fill an entire space, I'm guessing the solution would be to wrap the component into a JPanel. However, positioning the component to the center of this panel will make the component be closer to one side than another if you have components on other sides. How do I work around this?
These images demonstrate the problem and the ideal solution; the gray border represents the BorderLayout.SOUTH (wrapped in a JPanel) of the main frame. The black squares represents components that are throwing the center component off. The red square represents the component that needs to be centered.
Problem:
Ideal solution:
As I see the problem, in order for the red component to be centered the right and left components must be of equal size.
You might be able to use the Relative Layout.
The RelativeLayout will allow you to make the right/left components the same size while keeping the center component at its preferred size. As the frame is resized space will be added/removed from the right/left components.
For example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
JPanel left = new JPanel( new FlowLayout(FlowLayout.LEFT) );
JPanel leftBox = new JPanel();
leftBox.setPreferredSize( new Dimension(200, 50) );
leftBox.setBackground( Color.BLACK );
left.add( leftBox );
JPanel center = new JPanel( new FlowLayout(FlowLayout.CENTER) );
JPanel centerBox = new JPanel();
centerBox.setPreferredSize( new Dimension(50, 50) );
centerBox.setBackground( Color.RED );
center.add( centerBox );
JPanel right = new JPanel( new FlowLayout(FlowLayout.RIGHT) );
JPanel rightBox = new JPanel();
rightBox.setPreferredSize( new Dimension(50, 50) );
rightBox.setBackground( Color.BLACK );
right.add( rightBox );
setLayout( new RelativeLayout(RelativeLayout.X_AXIS, 5) );
add(left, new Float(1));
add(center);
add(right, new Float(1));
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
The one problem with the relative layout is that when you pack the frame the components will be dislayed too small since the preferred size is simply the sum of the components. So the left panel will be truncated.
In the example above you can add the following to get around this problem:
right.add( rightBox );
right.setPreferredSize( left.getPreferredSize() ); // added
Another option might be to use the OverlayLayout which can be set up to display the red panel over top of a panel containing the two other components:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
JPanel left = new JPanel( new FlowLayout(FlowLayout.LEFT) );
JPanel leftBox = new JPanel();
leftBox.setPreferredSize( new Dimension(200, 50) );
leftBox.setBackground( Color.BLACK );
left.add( leftBox );
JPanel center = new JPanel( new FlowLayout(FlowLayout.CENTER) );
center.setOpaque(false);
JPanel centerBox = new JPanel();
centerBox.setPreferredSize( new Dimension(50, 50) );
centerBox.setBackground( Color.RED );
center.add( centerBox );
JPanel right = new JPanel( new FlowLayout(FlowLayout.RIGHT) );
JPanel rightBox = new JPanel();
rightBox.setPreferredSize( new Dimension(50, 50) );
rightBox.setBackground( Color.BLACK );
right.add( rightBox );
JPanel main = new JPanel( new BorderLayout() );
main.add(left, BorderLayout.LINE_START);
main.add(right, BorderLayout.LINE_END);
setLayout( new OverlayLayout(this) );
add(center);
add(main);
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Two questions.
Firstly I'm trying to display a JButton on a JFrame, so far I've managed to display the JFrame with nothing on it.
Secondly how would one add functionality to a button? Would you pass it a method?
Any feedback is appreciated.
<code>
//imports SWING etc...
//global variables...
public class FahrenheitGUI {
public static void main(String args[]){
prepareGUI();
}
private static void prepareGUI(){
JFrame frame = new JFrame("Temp");
JPanel panel = new JPanel();
JLabel temperatureLabel;
int h = 300; int w = 300;
frame.setSize(h,w);
JButton one = new JButton( "0" );
JButton two = new JButton( "1" );
JButton three = new JButton( "2" );
JButton four = new JButton( "3" );
JButton five = new JButton( "4" );
JButton six = new JButton( "5" );
JButton seven = new JButton( "6" );
JButton eight = new JButton( "7" );
JButton nine = new JButton( "8" );
JButton ten = new JButton( "9" );
JButton negative = new JButton( "-" );
JButton dot = new JButton( "." );
JButton reset = new JButton( "reset" );
one.setBounds(10,10,20,20);
//one.addActionListener(onButtonPress);
//creates an error
frame.setVisible(true);
}
}
class Keypad implements ActionListener{
public void actionPerformed( ActionEvent one){
// guessing
}
public void actionPerformed( ActionEvent two){
// guessing
}
}
You could create JPanel, add buttons to your panel and then and the whole panel to your JFrame like this:
JPanel panel = new JPanel(); //by default it will has FlowLayout
panel.add(yourButton);
frame.add(yourJPanel);
frame.setVisible(true);
Personally I create class that extends JPanel, and inside of it I set size for panel (not for frame) and then, after adding panel to my frame I call pack() method which will resize your frame in reference of the size of your panel.
If you want to change default layout manager just call setLayout(LayoutManager)
Edit:
If you want to add functionality to your button just use:
yourButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
//button logic
}
});
call frame.add(Button) for each button. Afterwards frame.pack() once.
How do i make the buttons appear under the combo box here? In other words have button 1 and button 2 right underneath the combo box?
public class GUI extends JFrame implements ListSelectionListener, ActionListener {
private JPanel myPanelA;
private JSplitPane itemPane;
public static void startWindowsGui ( ) {
SwingUtilities.invokeLater ( new Runnable ( ) {
public void run ( ) {
GUI gui = new GUI ( );
gui.setVisible ( true );
}
} );
}
public GUI() {
// Set the layout to a grid
setLayout ( new BorderLayout ( 5, 5 ) );
setTitle ( "UI " );
setSize ( 800, 600 );
setDefaultCloseOperation ( EXIT_ON_CLOSE );
setBackground ( new Color ( 15, 255, 10 ) );
addComponents ( );
}
private void addComponents ( ) {
JSplitPane mainPane = new JSplitPane ( JSplitPane.HORIZONTAL_SPLIT );
itemPane = new JSplitPane ( JSplitPane.VERTICAL_SPLIT );
mainPane.add ( PanelA ( ), JSplitPane.LEFT );
mainPane.add ( itemPane, JSplitPane.RIGHT );
mainPane.setOneTouchExpandable ( true );
itemPane.setOpaque(true);
itemPane.setBackground(new Color(0xffffffc0));
BufferedImage myPicture = null;
try {
myPicture = ImageIO.read(new File("C:/Users/Desktop/image.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
//add(picLabel);
itemPane.add(picLabel);
add ( mainPane, BorderLayout.CENTER );
}
private JPanel PanelA ( ) {
myPanelA = new JPanel ( );
myPanelA.setLayout ( new BorderLayout ( 0, 0 ) );
myPanelA.add ( buttonPanel ( ), BorderLayout.NORTH );
myPanelA.setBorder ( new EmptyBorder ( 0, 0, 0, 0 ) );
myPanelA.setBackground(new Color(0,0,0));
return myPanelA;
}
#Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void valueChanged(ListSelectionEvent arg0) {
}
private JPanel buttonPanel ( ) {
// Create the panel
JPanel addButton = new JPanel ( );
JPanel cards; //a panel that uses CardLayout
String BUTTONPANEL = "Card with JButtons";
String TEXTPANEL = "Card with JTextField";
JPanel comboBoxPane = new JPanel(); //use FlowLayout
String comboBoxItems[] = { BUTTONPANEL, TEXTPANEL };
JComboBox cb = new JComboBox(comboBoxItems);
cb.setEditable(false);
//cb.addItemListener(this);
comboBoxPane.add(cb);
//Create the "cards".
JPanel card1 = new JPanel();
card1.add(new JButton("Button 1"));
card1.add(new JButton("Button 2"));
JPanel card2 = new JPanel();
card2.add(new JTextField("TextField", 10));
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
cards.add(card2, TEXTPANEL);
addButton.add(comboBoxPane, BorderLayout.PAGE_START);
addButton.add(cards, BorderLayout.CENTER);
return addButton;
}
}
Use BoxLayout for the panel instead of it's default layout which is FlowLayout.
See this link: How to Use BoxLayout. In your case, BoxLayout.Y_AXIT will helps.
For example:
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
You need to arrange your layout, GridLayout is very good.
You need first to GridLayout(2, 1).
The first row will be assigned to the combo box,
and the second row for a panel with GridLayout(1, 2) for the two buttons.
setLayout(new GridLayout(2, 1));
add(comboBox);
JPanel inner = new JPanel();
inner.setLayout(new GridLayout(1, 2));
add(inner);
inner.add(button1);
inner.add(button2);
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);
}
}