Im creating a Tic Tac Toe game out of Java and i seem to be stucj in one problem i cant get out of :( . I cant rezize my button. I tried both tried both setSize and setPreferredSize but dosent seem to work:
Here is the setPreferedSize pic:
And Code:
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import sun.org.mozilla.javascript.internal.xml.XMLLib.Factory;
public class TicTacToe {
JFrame frame;
JPanel contentPane;
JButton row1col1;
JButton row1col2;
JButton row1col3;
JButton row2col1;
JButton row2col2;
JButton row2col3;
JButton row3col1;
JButton row3col2;
JButton row3col3;
public TicTacToe() {
// TODO Auto-generated constructor stub
frame = new JFrame("Fds");
contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane,BoxLayout.Y_AXIS));
row1col1 = new JButton();
row1col1.setPreferredSize(new Dimension(600,600));
contentPane.add(row1col1);
row1col2 = new JButton();
row1col2.setPreferredSize(new Dimension(600,600));
contentPane.add(row1col2);
frame.setContentPane(contentPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private static void runGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
TicTacToe greeting = new TicTacToe();
}
public static void main(String[] args) {
/* Methods that create and show a GUI should be
run from an event-dispatching thread */
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
runGUI();
}
});
}
}
Thank you so much for your help!
The BoxLayout respects the maximum size of the component.
In your case the maximum size is less than the preferred size.
However, the solution is NOT to play with the preferred/maximum sizes.
Instead you can use:
button.setMargin( new Insets(10, 10, 10, 10) );
to control the size of your button, then normal layout management can be done as the preferred size will be calculated correctly.
As Camickr states, BoxLayout respects maximal size, but having said that, why use BoxLayout? Instead I suggest:
If you want to create a grid of JButtons, use GridLayout as it excels at creating grids.
It somewhat respects preferred sizes as long as you pack your GUI, and all the components are the same size,
But having said that, don't set the size. For tic tac toe, set the JLabel's font to something large, or use JLabels with ImageIcons that are large, so that your GUI sets its own size correctly.
You should be using an array or 2D array of JButtons for ease of coding.
For example please check out my code here: Java: Drawing using Graphics outside the class which draws the main canvas which uses programmer created ImageIcons and creates this GUI:
Or my code in this answer: How to wait for a MouseListener mouse press? which uses Font sizing to create this GUI:
Related
Currently, the problem I am trying to solve is how I get both my image and button to show up.
When I have the following line in the code the image shows up but when I remove it my image doesn't display but the button does:
setLayout (new FlowLayout()) ;
without the line of code
with the line of code
Images for example ^
import java.awt.*;
public class Panel extends JFrame {
private ImageIcon FirstPageImage;
private JLabel FirstPageLabel;
private JLayeredPane SignupButtonLayer;
private JButton Button;
public Panel(){
setLayout (new FlowLayout()) ;
FirstPageImage = new ImageIcon(getClass().getResource("FirstPageAnimationUsing.gif"));
FirstPageLabel = new JLabel(FirstPageImage);
FirstPageImage.setImage(FirstPageImage.getImage().getScaledInstance(343,820,Image.SCALE_DEFAULT));
add(FirstPageLabel);
Button = new JButton();
SignupButtonLayer = new JLayeredPane();
Button.setOpaque(true);
Button.setBackground(Color.cyan);
Button.setBounds(94,617,159,82);
SignupButtonLayer.add(Button, JLayeredPane.DEFAULT_LAYER);
add(SignupButtonLayer);
}
public static void main(String[] args) {
Panel gui = new Panel();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setVisible(true);
gui.pack();
gui.setTitle("Reminder App");
gui.setSize(360,850);
}
}
Refer to How to Use Layered Panes.
You need to give the JLayeredPane a preferred size. Since your JLayeredPane contains only a single JButton, that size should be big enough to display the entire JButton.
The arguments to method setBounds – that you call on Button – are relative to its container, i.e. SignupButtonLayer. Setting the x to 94 and the y to 617 means that Button is placed outside of the bounds of SignupButtonLayer. Hence you don't see it. In the below code, I set x and y both to 0 (zero) so that the top, left corner of Button aligns with the top, left corner of SignupButtonLayer.
No need to explicitly call method setOpaque(true) for Button since that is the default, anyway.
Either call pack() – which is usually preferred – or setSize() but don't call both.
setVisible(true) should be called only once your GUI is completely built. In the below code I call it after calling pack() and setTitle().
I suggest that you try to adhere to Java naming conventions.
I also suggest that try not to name your classes the same as classes in the JDK. I am referring to Panel.
The below code simply resolves your problem, i.e. displaying both the image and the button together – while using FlowLayout for the [content pane of the] JFrame. Notice that the preferred size of SignupButtonLayer is slightly larger than the size arguments in method setBounds.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
public class Panel extends JFrame {
private ImageIcon FirstPageImage;
private JLabel FirstPageLabel;
private JLayeredPane SignupButtonLayer;
private JButton Button;
public Panel() {
setLayout(new FlowLayout());
FirstPageImage = new ImageIcon(getClass().getResource("FirstPageAnimationUsing.gif"));
FirstPageLabel = new JLabel(FirstPageImage);
FirstPageImage.setImage(FirstPageImage.getImage().getScaledInstance(343, 820, Image.SCALE_DEFAULT));
add(FirstPageLabel);
Button = new JButton();
SignupButtonLayer = new JLayeredPane();
SignupButtonLayer.setPreferredSize(new Dimension(160, 90));
// Button.setOpaque(true);
Button.setBackground(Color.cyan);
Button.setBounds(0, 0, 159, 82);
SignupButtonLayer.add(Button, JLayeredPane.DEFAULT_LAYER);
add(SignupButtonLayer);
}
public static void main(String[] args) {
Panel gui = new Panel();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.pack();
gui.setTitle("Reminder App");
// gui.setSize(360, 850);
gui.setVisible(true);
}
}
What's wrong? ImageIcon and the frame's size are working properly.
But the JTextField and the JButton aren't.
I need the solution.
import javax.swing.*;
import javax.swing.ImageIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Frame {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("Alkalmazás");
frame.setVisible(true);
frame.setSize(500,500);
frame.setResizable(false);
JTextField field = new JTextField();
field.setBounds(40,250, 300,35);
JButton button = new JButton(new ImageIcon("table.png"));
button.setBounds(40,400, 250,25);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tf.setText(""something);
}
});
frame.add(field);
frame.add(button);
}
}
You didn't mention what's "not working properly", but there are a few errors with your code:
Don't call your class Frame, it may confuse you or others about java.awt.Frame, something that may work would be MyFrame
Right now all your class is inside the main method and it's not placed inside the Event Dispatch Thread (EDT), to fix this, create an instance of your class and call a method createAndShowGUI (or whatever you want to name it) inside SwingUtilities.invokeLater()
For Example:
public static void main(String args[]) {
SwingUtilities.invokeLater(new MyFrame()::createAndShowGUI)
}
Or if using Java 7 or lower, use the code inside this answer in point #2.
setVisible(true) should be the last line in your code, otherwise you may find some visual glitches that may be resolved until you move your mouse above your window or something that triggers the call to repaint() of your components.
Instead of calling setSize(...) directly, you should override getPreferredSize(...) of your JPanel and then call pack() on your JFrame, see this question and the answers in it: Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?
You're adding 2 components to the CENTER of BorderLayout, which is a JFrame's default layout manager, there are other layout managers and you can combine them to make complex GUI's.
setBounds(...) might mean that you're using null-layout, which might seem like the easiest way to create complex layouts, however you will find yourself in situations like this one if you take that approach, it's better to let Swing do the calculations for you while you use layout managers. For more, read: Why is it frowned upon to use a null layout in Swing?
With all the above tips now in mind, you may have a code similar to this one:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class MyFrame {
private JFrame frame;
private JPanel pane;
private JTextField field;
private JButton button;
public static void main(String[] args) {
SwingUtilities.invokeLater(new MyFrame()::createAndShowGUI);
}
private void createAndShowGUI() {
frame = new JFrame("Alkalmazás");
pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
field = new JTextField(10);
button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field.setText("something");
}
});
pane.add(field);
pane.add(button);
frame.add(pane);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Now you have an output similar to this one:
What about you want the JTextField to have a more "normal" size? Like this one:
You'll have to embed field inside another JPanel (with FlowLayout (the default layout manager of JPanel)), and then add that second JPanel to pane, I'm not writing the code for that as I'm leaving that as an exercise to you so you learn how to use multiple layout managers
I am trying to create a simple Java Swing GUI that consists of a panel on top and tabs in the center. I want the top panel to remain its preferred size and the tabs to take up the remaining space so I used a BorderLayout. The content of the tab can be tall so I put the tab component into a scroll pane.
Everything seems to work the way I expect (with respect to component sizing and scroll bar behavior when I resize the frame) except that my packed frame is 12 pixels too tall (and possibly 16 pixels too wide). Would someone please explain what is going on and how to resolve it. Somehow when the pack is sizing all of the components, something is smart enough to (mostly) respect the screen size. I am using Java 8 on Windows 7 with a screen resolution of 1920 x 1200.
Below is my test code and the output it produces.
Code:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
public final class SizeTest
{
public static void main(final String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGui();
}
});
}
private static void createAndShowGui()
{
final JPanel topPanel = new JPanel();
topPanel.setBorder(BorderFactory.createTitledBorder("Top"));
topPanel.setPreferredSize(new Dimension(800, 150));
final JPanel centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createTitledBorder("Center"));
centerPanel.setPreferredSize(new Dimension(800, 1300));
final JScrollPane scrollPane = new JScrollPane(centerPanel);
final JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab", scrollPane);
final JPanel mainPanel = new JPanel(new BorderLayout(0, 10));
mainPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.add(tabbedPane, BorderLayout.CENTER);
final JFrame mainFrame = new JFrame("Size Test");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(mainPanel);
mainFrame.pack();
System.err.println("***** Frame Size: " + mainFrame.getSize() + ", Screen Size: "
+ Toolkit.getDefaultToolkit().getScreenSize() + ", Maximum Window Bounds: "
+ GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds());
mainFrame.setVisible(true);
}
}
Output:
***** Frame Size: java.awt.Dimension[width=816,height=1212], Screen Size: java.awt.Dimension[width=1920,height=1200], Maximum Window Bounds: java.awt.Rectangle[x=0,y=0,width=1920,height=1156]
If you're going to stuff around with setPreferredSize, be prepared for things to go astray.
The first thing I would do, is seriously reconsider using setPreferredSize.
Because of the way the API works, JScrollPane will use the preferredSize of the component to make determinations about it's own size. You can change this by implementing the Scrollable interface, which allows you to return the preferredScrollableViewportSize, which JScrollPane will use instead when determing how large it needs to be
You see Scrollable demonstrated here and here and lots of other places if you do some searching
I'm trying to learn how to code Conway's game of life in Java, and I'm getting stuck creating the GUI. I want to make a JPanel within the JFrame, with a larger border at South, and then two buttons in the south border, one for "Play" and one for "Restart." But the Design element won't let me resize or move anything around. I was able to resize the JPanel by going into the code and creating a larger border in the South, but I can't figure out how to resize the JButton. Any ideas?
(I'm using Eclipse Kepler...I hear NetBeans is better at this kind of stuff, should I just ditch Eclipse and try it with NetBeans?)
Here's my code so far:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.FlowLayout;
import javax.swing.JButton;
public class GameOfLife extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameOfLife frame = new GameOfLife();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public GameOfLife() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 518, 508);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(10, 10, 50, 10));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
panel.setBackground(Color.GRAY);
contentPane.add(panel, BorderLayout.CENTER);
JButton btnNewButton = new JButton("New button");
contentPane.add(btnNewButton, BorderLayout.SOUTH);
}
}
Basically, instead of doing BorderLayout.SOUTH, I want to manually place it where I want it within the frame. I'd also love to be able to do that with the JPanel--the whole North/West/South/East/Center thing in general seems very constricting. What's the way around it?
Maybe you should look at Swing Layouts in Java documentation:
A Visual Guide to Layout Managers
And the layout which is able to give you the most flexibility is the GridBagLayout but you will write much code to display the User Interface as your needs.
You will have a detailled way to go with the following official tutorial:
How to Use GridBagLayout
In your code, you are using the simple BorderLayout which is very simple but not so much configurable.
I want to display a vertical list of JCheckBox-es in a JPanel. But I have decided to wrap each JCheckBox with a JPanel, (thinking that i would need it in future). and i am going to stack these JPanels(containing one JCheckBox each) vertically in another JPanel using BoxLayout.
The BoxLayout is working as expected without any vertical space in between the JPanels added to them. My problem is with these inner JPanels containing individual checkbox. there is a considerable amount of space around the checkbox for each panel. I want to wrap these checkboxes tightly, so that the size of jcheckbox and that of the corresponding jpanel containing them are equal.
for these individual jpanel i have tried layouts - flowlayout and default layout. both didnt help.
How can i fix this? i just simply set the flowlayout and add the jcheckbox directly to the jpanel. no other code i have used.
I am adding an example code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class TryBox implements Runnable{
/**
* #param args
*/
public static void main(String args[])
{
SwingUtilities.invokeLater(new TryBox());
}
public void run()
{
class InnerPanel extends JPanel
{
public InnerPanel(int i) {
// TODO Auto-generated constructor stub
setLayout(new FlowLayout());
setBackground(new Color(i*50, i*50, i*50));
add(new JCheckBox("CheckBox "+i));
}
}
JPanel outerPanel = new JPanel();
outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
for(int i=0;i<5;i++)
{
outerPanel.add(new InnerPanel(i));
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane sp = new JScrollPane(outerPanel);
frame.setPreferredSize(new Dimension(200, 600));
frame.getContentPane().add(new JScrollPane(outerPanel));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
here frame.setPreferredSize(new Dimension(200, 600)); is making the difference. i want the jpanels to reduce to the size of jcheckboxes. i dont want the jcheckboxes to fit into jpanel's size. if any extra vertical space is there in the container i want it to be left free.
The default layout of JPanel is FlowLayout, and the default constructor creates "a default 5-unit horizontal and vertical gap." You can specify no gap:
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
In addition, the JCheckBox UI delegate adds Insets that vary by L&F. I would be wary of changing these: the size is negligible and typically required to accommodate selection indication.
Did you try setting the margin and border insets to 0 (on the Swing components)?