For a small project, I'm trying to make a TicTacToe Game using JFrame and JButtons. The game is going to consist of 9 Buttons that when clicked will changed to either an X or O. I havent gotten too far into the project but The problem I'm running into is when I display an image as an Icon on the Jbutton, Its incredibly small and Ive tried to resize it with no avail. Any feedback is appreciated.
This is what the button looks like when i put the icon on it:
Image of small button when Icon on it
import java.awt.*;
import javax.swing.*;
import java.io.*;
public class TicTacToe
{
public static void main ( String[] args )
{
ButtonFrame frm = new ButtonFrame("TicTactToe");
frm.setSize(300, 450);
frm.setVisible( true );
}
}
class ButtonFrame extends JFrame
{
JButton bChange;
ButtonFrame(String title)
{
super( title );
ImageIcon XIcon = new ImageIcon("X.png");
Icon OIcon = new ImageIcon("O.png");
setLayout( new FlowLayout() ); // set the layout manager
//top row
bChange = new JButton(XIcon);
add( bChange );
setSize(400, 400);
bChange = new JButton("Button2");
add( bChange );
bChange = new JButton("Button3");
add( bChange );
//middle row
bChange = new JButton("Button4");
add( bChange );
bChange = new JButton("Button5");
add( bChange );
bChange = new JButton("Button6");
add( bChange );
//bottom row
bChange = new JButton("Button7");
add( bChange );
bChange = new JButton("Button8");
add( bChange );
bChange = new JButton("Button9");
add( bChange );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
}
your problem seems to be the image you are using. when I copied your code and used my own image the program worked properly. http://i.stack.imgur.com/io2yV.png
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'm trying to align my JLabel at the top of the screen but it is showing at the bottom instead. It can be fixed if put some negative values in the Top-Bottom parameter in setBounds, However ! I wish to know why it's behaving like this and how it can be fixed the other way.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class T2{
private JFrame jf;
private JLabel jL;
private JButton b1, b2;
private JRadioButton jr1;
private JTextField tf1, tf2;
private Font ft;
public void run(){
//JFrame
jf = new JFrame("Program");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
jf.setLayout(null);
jf.setBounds(0,40,500,500);
//Container
Container c = jf.getContentPane();
//Font
ft = new Font("Consolas",1,25);
//JLABEL
jL = new JLabel();
jL.setText("Enter Name:");
c.add(jL);;
//Top-Bottom Positioning isn't working here..
jL.setBounds(50, 0 , 600, 600);
jL.setFont(ft);
//JTextField
tf1 = new JTextField("Type here...");
c.add(tf1);
tf1.setBounds(200, 0 , 200, 20);
}
public static void main(String args[]){
T2 obj = new T2();
obj.run();
}
}
Here's the screenshot:
LINK
Use a layout (the default BorderLayout does what you want), add the components you want to appear at the top to the layout with the constraint "NORTH", then magically it all works.
Further comments in the code.
class T2 {
private JFrame jf;
private JLabel jL;
private JButton b1, b2;
private JRadioButton jr1;
private JTextField tf1, tf2;
private Font ft;
public void run() {
//JFrame
jf = new JFrame( "Program" );
jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// jf.setVisible( true ); // don't do this until the frame is composed
// jf.setLayout( null ); // yucky in all respects
// jf.setBounds( 0, 40, 500, 500 ); // use setSize() instead
//Container
// Container c = jf.getContentPane(); // normally you just call add()
//Font
ft = new Font( "Consolas", 1, 25 );
// Make panel first
JPanel panelNorth = new JPanel();
//JLABEL
jL = new JLabel();
jL.setText( "Enter Name:" );
jL.setFont( ft );
panelNorth.add( jL );
//Top-Bottom Positioning isn't working here..
// jL.setBounds( 50, 0, 600, 600 );
//JTextField
tf1 = new JTextField( "Type here..." );
// c.add( tf1 );
panelNorth.add( tf1 );
// tf1.setBounds( 200, 0, 200, 20 );
// now just add the panel to the "north" of the jframe border layout
jf.add( panelNorth, BorderLayout.NORTH );
// now make visible
jf.setSize( 600, 480 );
jf.setLocationRelativeTo( null );
jf.setVisible( true );
}
public static void main( String args[] ) {
// Swing is not thread safe, do on EDT
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
T2 obj = new T2();
obj.run();
}
} );
}
}
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.
I have several text areas aligned vertically. I want them to expand as more text is typed, but put a limit on how tall they'll become.
I've tried setting the max size, but that seems to be ignored. Any ideas?
_recipients = new JTextArea();
_recipients.setBorder( BorderFactory.createEtchedBorder() );
_recipients.setLineWrap( true );
_recipients.setWrapStyleWord( true );
_recipients.setMaximumSize( new Dimension( 111, 55 ) );
_subject = new JTextArea();
_subject.setBorder( BorderFactory.createEtchedBorder() );
_subject.setLineWrap( true );
_subject.setWrapStyleWord( true );
_subject.setMaximumSize( new Dimension( 111, 55 ) );
//JComponent area = LAF.Area.clear( );
JPanel area = new JPanel( new GridLayout( 1, 2, 6, 0 ) );
area.setOpaque( false );
area.add( _recipients );
area.add( _subject );
add( area, BorderLayout.CENTER );
I recieved advice that i should use a scroll pain, but that just created an uneditable area
JScrollPane pain = new JScrollPane();
pain.add( _recipients );
area.add( pain );
pain = new JScrollPane();
pain.add( _subject );
area.add( pain );
EDIT
not much more to it, but
public class TestFrame extends JFrame
{
TestFrame()
{
setSize( new DimensionUIResource( 800, 668 ) );
JPanel area = new JPanel( new FlowLayout( 0, 0, 0 ) );
Stuff thing = new Stuff();
area.add( thing );
add( area );
}
public static void main( String args[] )
{
TestFrame frame = new TestFrame();
frame.show();
}
private static class Stuff extends JComponent
{
private final JTextArea _subject;
Stuff()
{
setLayout( new BorderLayout() );
_subject = new JTextArea();
_subject.setBorder( BorderFactory.createEtchedBorder() );
_subject.setLineWrap( true );
_subject.setWrapStyleWord( true );
_subject.setSize( new Dimension( 111, 55 ) );
_subject.setMaximumSize( new Dimension( 111, 55 ) );
JPanel area = new JPanel( new GridLayout( 1, 2, 6, 0 ) );
area.setOpaque( false );
area.add( _subject );
add( area, BorderLayout.CENTER );
}
}
}
Personally, I prefer not to limit my JTextArea's size lest I prevent the user from adding as much information as needed. Again, I feel you're better off wrapping the JTextArea in a JScrollPane and limiting the JScrollPane vewport's size. This can be done explicitly or implicitly by telling the JTextArea how many rows and columns to start out with. For example:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;
public class TestPanel extends JPanel {
private static final int AREA_COUNT = 4;
public TestPanel() {
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new GridLayout(0, 1, 0, 5));
for (int i = 0; i < AREA_COUNT; i++) {
JTextArea area = new JTextArea(5, 30);
area.setLineWrap(true);
area.setWrapStyleWord(true);
JPanel wrapPanel = new JPanel(new BorderLayout());
wrapPanel.add(new JLabel("JTextArea " + i), BorderLayout.PAGE_START);
wrapPanel.add(new JScrollPane(area), BorderLayout.CENTER);
add(wrapPanel);
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("TestPanel");
frame.getContentPane().add(new TestPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
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.