JButtons are not resizing to match their preferred size - java

I am trying to make a menu screen for a game. I've added two buttons, play and exit, and am currently trying to figure out how to resize them. When I run my code the buttons are almost the exact same size (different I imagine because of the text). I'm using BoxLayout for my buttons, and I just read here Why will BoxLayout not allow me to change the width of a JButton but let me change the height? why it would only resize the width or height, but it's not resizing either right now. In my code I use BoxLayout.PAGE_AXIS, I don't know if that makes a difference, but it didn't resize vertically either with BoxLayout.Y_AXIS.
Here's my code:
public class Stage extends JFrame {
/* PRIVATE */
private JButton play, exit;
// Setup the Menu screen.
private void createMenuScreen() {
Container window = getContentPane();
// window.setBackground(Color.BLACK);
JPanel menuScreen = new JPanel();
menuScreen.setLayout(new BoxLayout(menuScreen, BoxLayout.PAGE_AXIS));
window.add(menuScreen, "Center");
play = new JButton("Play");
play.setPreferredSize(new Dimension(20, 20));
play.setAlignmentX(Component.CENTER_ALIGNMENT);
exit = new JButton("Exit");
exit.setPreferredSize(new Dimension(100, 100));
exit.setAlignmentX(Component.CENTER_ALIGNMENT);
menuScreen.add(play);
menuScreen.add(exit);
}
/* PUBLIC */
public Stage() {
// Setup the frame.
setSize(224, 288);
setLocationRelativeTo(null); // Centers the window.
setUndecorated(true); // Removes the Windows border.
setVisible(true);
createMenuScreen();
}
}

Try to use setMaximumSize() method
exit.setMaximumSize(new Dimension(100,100));
Or try to use BorderLayout instead of BoxLayout

Related

Java basic GUI blank

When I run this program it appears as an empty window until you fullscreen, then it can be resized as you like, why is it doing this/how do I stop it?
the program is very basic just a menubar and two panels split.
public class SplitPane {
public static void main(String[] args) {
window view = new window();
}
private static class window extends JFrame {
public window() {
this.setSize(1000, 750);
this.setVisible(true);
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//menubar is here, must lower code quantity for stack
//panels
//graph half
JPanel graphRep = new JPanel();
//Background colour - graphRep.setBackground(Color.RED);
graphRep.setVisible(true);
String graphTitle = "Textual Representation.";
Border graphBorder = BorderFactory.createTitledBorder(graphTitle);
graphRep.setBorder(graphBorder);
//text half
JPanel textRep = new JPanel();
textRep.setVisible(true);
String textTitle = "Graphical Representation.";
Border textBorder = BorderFactory.createTitledBorder(textTitle);
textRep.setBorder(textBorder);
//splitpane
JSplitPane splitPane = new JSplitPane();
splitPane.setSize(600, 750);
splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setOneTouchExpandable(true);
splitPane.setDividerSize(10);
splitPane.setDividerLocation(250);
splitPane.setLeftComponent(graphRep);
splitPane.setRightComponent(textRep);
this.add(splitPane);
}
}
this.setVisible(true);
You are making the frame visible BEFORE you add components to the frame. The layout manager is never invoked so the size of all the components remains (0, 0) so there is nothing to paint.
The frame should be made visible AFTER all the components have been added to the frame.
And the code should be:
frame.pack();
frame.setVisible();
So each component is displayed at its proper size. Don't hardcode the size() because you don't know what the size of a users screen might be.

JFrame Scroll bar and Canvas

I'm having trouble trying to add a horizontal scroll bar to a JFrame that has a canvas. I draw an images onto the canvas and sometimes these images over-run the screen so I want a scroll bar to enable the user to see them.
Here is the key section in the code, if any other code is needed please let me know and i'll edit.
Could anyone point out what i'm doing wrong ?
Many Thanks J
public class TheFrame extends JFrame {
private static ThePanel canvas;
private String deckImagesToUse;
/**
* The constructor creates a Frame ready to display the cards
*/
public TheFrame(String cardImgFile) {
// Calls the constructor in the JFrame superclass passing up the name to
// display in the title
super("Window title");
//Using users choice of cards
deckImagesToUse = cardImgFile;
// When you click on the close window button the window will be closed
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// This has North, East, South, West and center positions for components
setLayout(new BorderLayout());
// This is what we will draw on (see the inner class below)
canvas = new ThePanel();
setSize(700, 300);
this.add(canvas, BorderLayout.CENTER);
//Scroll Bar
JScrollPane scrollPane = new JScrollPane(canvas);
//scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
this.getContentPane().add(scrollPane);
int desiredWidth = (Pack.cardsInPlay.size() * 70);
Dimension d = new Dimension(desiredWidth,300);
canvas.setPreferredSize(d);
setVisible(true); // Display the window
}
canvas = new ThePanel();
setSize(700, 300);
this.add(canvas, BorderLayout.CENTER);
The setting size and adding to this is futile because later scrollpane ignores it.
When your image is bigger than the JScrollPane just call canvas.setPreferredSize(imageWidth, imageHeight);

JPanel Positioning using the Border Layout not working

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.

How to make JLabel consume space when not visible?

I have a program which creates 2 Panels and then places a label and two buttons in them. The label is set to invisible setVisible(false) and then the two buttons are added and the frame is packed. When i click the first button, the label is shown, setVisible(true), and the seccond one hides it again, setVisible(false). When i click each button, they move to fill the space of the label as it hides, and move again to get out of the way of the label as it is shown. I want to stop this from happening and have the buttons stay in the same place even when the label is hidden.
Here is the code:
public class MainFrame extends JFrame{
public JLabel statusLabel;
public JButton show;
public JButton hide;
public MainFrame(){
super("MagicLabel");
JPanel topPanel = new JPanel(); //Create Top Panel
statusLabel = new JLabel(""); //Init label
statusLabel.setVisible(false); //Hide label at startup
topPanel.setSize(400, 150); //Set the size of the panel, Doesn't work
topPanel.add(statusLabel); //Add label to panel
JPanel middlePanel = new JPanel(); //Create Middle Panel
show= new JButton("Show"); //Create show button
hide= new JButton("Hide"); //Create hide button
middlePanel.setSize(400, 50); //Set the size of the panel, Doesn't work
middlePanel.add(show); //Add show button
middlePanel.add(hide); //Add hide button
this.add(topPanel, "North"); //Add Top Panel to North
this.add(middlePanel, "Center"); //Add Middle Panel to Center
addActionListeners(); //void:adds action listeners to buttons
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBounds(100, 100, 512, 400);
this.setPreferredSize(new Dimension(400,200)); //Set size of frame, Does work
this.pack();
this.setVisible(true);
}
public void animateInstall(boolean var0){ //Void to show and hide label from action listeners
statusLabel.setVisible(var0);
sendWorkingMessage("Boo!");
}
public void sendWorkingMessage(String message){ //Void to set text of label
this.statusLabel.setForeground(new Color(225, 225, 0));
this.statusLabel.setText(message);
}
void addActionListeners(){
show.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
animateInstall(true);
}
});
hide.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
animateInstall(false);
}
});
}
this.setPreferredSize(new Dimension(400,200));
this.setMinimumSize(new Dimension(400,200));
So pack() cannot interfere.
Use CardLayout. Add the JLabel and empty JPanel. Instead of seting it visible/invisible swap the cards showing the JLabel or the JPanel when necesary.
Extending JFrame is not advisable, better extend JPanel put all your components inside and then add it to a JFrame
You need to learn how to use SwingUtilities.invokeLater(): See example how your should look like
You need to learn about Layout: Tutorial
Very dumb and easy approach in your code would be:
this.statusLabel.setForeground(bgColor); //background color
this.statusLabel.setText(" "); //some number of characters
By default for you frame you are using BorderLayout. You can try to have like:
this.add(topPanel, BorderLayout.NORTH); //Add Top Panel to North
this.add(middlePanel, BorderLayout.SOUTH); //Add Middle Panel to South
rather than at center.
Or you can create an intermediate container panel for these 2 panels, or consider other layout managers like BoxLayout, etc

Java JPanel inside JScrollPane?

I have a JFrame, in this JFrame I have a JPanel that I draw on, this Panel can be any size and so I placed it into a JScrollpane to let me scroll when the panel is larger than the window screen size.
Unfortunately does not work as I expected:
Making the JFrame window smaller than the JPanel size does not show scroll bars
The JScrollPane size now seems locked to the size of the JPanel I have added to it, where as before it resized to the bounds of it's JFrame window (it still kinda does this but only vertically now?!)
The JPanel seems to assume the size of the JScrollpane regardless of what I set for preferred size
I am sure I'm doing something stupid, if someone could point out what I would be most grateful!
JPanel imageCanvas = new JPanel(); // 'Canvas' to draw on
JScrollPane scrollPane = new JScrollPane();
// set size of 'canvas'
imageCanvas.setMinimumSize(new Dimension(100,100));
// Scroll pane smaller then the size of the canvas so we should get scroll bars right?
scrollPane.setMinimumSize(new Dimension(50,50));
// Add a border to 'canvas'
imageCanvas.setBorder(BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
scrollPane.setViewportView(imageCanvas);
setPreferredSize() is the trick, setMinimumSize() and even setSize() on the component will be ignored by JScrollPane. Here's a working example using a red border.
import java.awt.*;
import javax.swing.*;
public class Scroller extends JFrame {
public Scroller() throws HeadlessException {
final JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.red));
panel.setPreferredSize(new Dimension(800, 600));
final JScrollPane scroll = new JScrollPane(panel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(scroll, BorderLayout.CENTER);
setSize(300, 300);
setVisible(true);
}
public static void main(final String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Scroller().setVisible(true);
}
});
}
}
// suggest a size of 'canvas'
_ImageCanvas.setPreferredSize(new Dimension(100,100));
// Scroll pane smaller then the size of the canvas so we should get scroll bars right?
_ScrollPane.setPreferredSize(new Dimension(50,50));
// ..later
_Frame.pack();
Set preferred size on the canvas.
Increase dimensions 100,100 is too small atleast on my computer.
You may want to use new GridLayout(1,1); for you JFrame if you want the scrollpane to expand when you expand the frame.
As far as I remember there are 2 options:
define the preferredSize of _ImageCanvas
create a subclass of JPanel and implement Scrollable: http://docs.oracle.com/javase/7/docs/api/javax/swing/Scrollable.html
For more details, see the Javadoc:
http://docs.oracle.com/javase/7/docs/api/javax/swing/JScrollPane.html
Check out the Scrollable interface, this may help with the sizing issues.
These two method maybe helpful:
boolean getScrollableTracksViewportWidth();
boolean getScrollableTracksViewportHeight();

Categories