I have a JDesktopPane which contains a number of JInternalFrames. I'd like to be able to bring any JInternalFrame to the front, overlaying any other active frames. I found a number of code samples to do this, but none seem to work - the frame does NOT go on top of other active JInternalFrames. E.g.
public static void moveToFront(final JInternalFrame fr) {
if (fr != null) {
processOnSwingEventThread(new Runnable() {
public void run() {
fr.moveToFront();
fr.setVisible(true);
try {
fr.setSelected(true);
if (fr.isIcon()) {
fr.setIcon(false);
}
fr.setSelected(true);
} catch (PropertyVetoException ex) {
ex.printStackTrace();
}
fr.requestFocus();
fr.toFront();
}
});
}
}
According to the API toFront or moveToFront should work (though toFront looks to be the better of the two from my reading of the API). Are these JInternalFrames sitting in a JDesktopPane? According to your post it seems they are. I wonder if the error lies elsewhere.
Consider creating and posting an SSCCE (please click on the link), a small compilable, runnable program that demonstrates your best attempt at solving this. Then we can inspect your code, run it, modify it and best be able to help you fix it.
Here is my example of an SSCCE:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Random;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class InternalFrameToFront extends JPanel {
private static final int FRAME_MAX = 21;
private static final int DT_WIDTH = 700;
private static final int DT_HEIGHT = 500;
private static final Dimension DESKTOP_SIZE = new Dimension(DT_WIDTH, DT_HEIGHT);
private static final int IF_WIDTH = 150;
private static final int IF_HEIGHT = 100;
private static final Dimension INT_FRAME_SIZE = new Dimension(IF_WIDTH, IF_HEIGHT);
private Random random = new Random();
private JInternalFrame[] internalFrames = new JInternalFrame[FRAME_MAX];
public InternalFrameToFront() {
JDesktopPane desktop = new JDesktopPane();
desktop.setPreferredSize(DESKTOP_SIZE);
for (int i = 0; i < internalFrames.length; i++) {
JInternalFrame intFrame = new JInternalFrame("Frame Number " + i);
intFrame.setSize(INT_FRAME_SIZE);
int x = random.nextInt(DT_WIDTH - IF_WIDTH);
int y = random.nextInt(DT_HEIGHT - IF_HEIGHT);
intFrame.setLocation(x, y);
intFrame.setVisible(true);
desktop.add(intFrame);
internalFrames[i] = intFrame;
}
JSlider slider = new JSlider(0, FRAME_MAX - 1, 0);
slider.setMajorTickSpacing(5);
slider.setMinorTickSpacing(1);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
JPanel sliderPanel = new JPanel();
sliderPanel.add(slider);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ce) {
JSlider slider = (JSlider) ce.getSource();
if (!slider.getValueIsAdjusting()) {
int value = slider.getValue();
internalFrames[value].toFront();
}
}
});
setLayout(new BorderLayout());
add(desktop, BorderLayout.CENTER);
add(sliderPanel, BorderLayout.SOUTH);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("InternalFrameToFront");
frame.getContentPane().add(new InternalFrameToFront());
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();
}
});
}
}
Related
I am trying to create a game about war. I am starting off with just creating a single window. I am using swing to create windows. However, when the user tries to resize the JFrame, the elements don't move with the frame. I am resizing the buttons that I use, as well as my JPanel. My code can be seen below:
Main.java:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import Numbers.Numbers;
public class Main implements ActionListener {
static JFrame frame;
static JPanel titlePane;
static JButton playButton;
static JButton explanationButton;
static JPanel explanationPane;
static JButton nextButton;
static JLabel explanationLabel;
static JButton backButton;
static int frameSize = 500;
public Main(boolean run) {
if (run) {
frame = new JFrame("War");
titlePane = new JPanel(null);
playButton = new JButton("PLAY");
explanationButton = new JButton("HOW TO PLAY");
explanationPane = new JPanel(null);
nextButton = new JButton("NEXT");
backButton = new JButton("BACK");
titlePane.setSize(frameSize, frameSize);
titlePane.add(playButton);
playButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
playButton.setBackground(Color.GRAY);
playButton.setForeground(Color.WHITE);
playButton.setVisible(true);
explanationButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/(25/11)), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
explanationButton.setBackground(Color.GRAY);
explanationButton.setForeground(Color.WHITE);
explanationButton.setVisible(true);
explanationPane.setSize(frameSize, frameSize);
explanationPane.add(nextButton);
nextButton.setBounds(225, 50, 50, 15);
nextButton.setBackground(Color.GRAY);
nextButton.setForeground(Color.WHITE);
nextButton.setVisible(true);
backButton.setBounds(225, 450, 50, 15);
backButton.setBackground(Color.GRAY);
backButton.setForeground(Color.WHITE);
backButton.setVisible(true);
frame.setSize(frameSize, frameSize);
frame.add(titlePane);
frame.add(explanationPane);
titlePane.setVisible(false);
explanationPane.setVisible(false);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
public void switchPane(String pane) {
switch (pane) {
case "title":
titlePane.setVisible(true);
explanationPane.setVisible(false);
break;
case "explanation":
titlePane.setVisible(false);
explanationPane.setVisible(true);
break;
}
}
#Override
public void actionPerformed(ActionEvent event) {
}
public static void main(String[] args) {
Main war = new Main(true);
war.switchPane("title");
while (true) {
if (frame.getX() != frameSize) {
frameSize = frame.getX();
}
else if (frame.getY() != frameSize) {
frameSize = frame.getY();
}
frame.setSize(frameSize, frameSize);
titlePane.setSize(frameSize, frameSize);
explanationPane.setSize(frameSize, frameSize);
playButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
explanationButton.setBounds(Numbers.doubleToInt(frameSize/2.5), Numbers.doubleToInt(frameSize/(25/11)), Numbers.doubleToInt(frameSize/5), Numbers.doubleToInt(frameSize/(100/3)));
}
}
}
Numbers.java:
package Numbers;
public class Numbers {
public static int doubleToInt(double toConvert) {
int toReturn = (int) toConvert;
return toReturn;
}
}
Any help would be appreciated! :)
Please note I am not close to finishing so please ignore the empty method.
I have 17 JLabel components and I want to add same handler for all these labels. Actually I have have to increase the size of the label when mouse hovers over it. Code is here:
private void lblBackupMouseEntered(java.awt.event.MouseEvent evt) {
lblBackup.setSize(lblBackup.getWidth()+5,lblBackup.getHeight()+5);
}
private void lblChangePasswordMouseEntered(java.awt.event.MouseEvent evt) {
lblChangePassword.setSize(lblChangePassword.getWidth()+5,lblChangePassword.getHeight()+5);
}
private void lblAddEmployeeMouseEntered(java.awt.event.MouseEvent evt) {
lblAddEmployee.setSize(lblAddEmployee.getWidth()+5,lblAddEmployee.getHeight()+5);
}
private void lblAddCustomerMouseEntered(java.awt.event.MouseEvent evt) {
lblAddCustomer.setSize(lblAddCustomer.getWidth()+5,lblAddCustomer.getHeight()+5);
}
Now I want to avoid this repetition of same handler.
It's simple -- you can use the same mouse handler class, and can assign it to multiple JLabels, and then get the current involved JLabel via the MouseEvent#getSource() method.
#Override
public void mouseEntered(MouseEvent evt) {
// assuming that you only add this MouseListener to JLabels...
JLabel currentLabel = (JLabel)evt.getSource();
// do what needs to be done with currentLabel
}
For example:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class ManyLabelExample extends JPanel {
private static final int SIDES = 8;
private static final int GAP = 15;
public static final Color HOVER_COLOR = Color.pink;
private List<JLabel> labels = new ArrayList<>();
public ManyLabelExample() {
setLayout(new GridLayout(SIDES, SIDES));
MyMouseHandler myMouseHandler = new MyMouseHandler();
for (int i = 0; i < SIDES * SIDES; i++) {
String text = String.format("[%d, %d]", i % SIDES + 1, i / SIDES + 1);
JLabel label = new JLabel(text);
label.setOpaque(true);
label.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
label.addMouseListener(myMouseHandler);
labels.add(label);
add(label);
}
}
private class MyMouseHandler extends MouseAdapter {
#Override
public void mouseEntered(MouseEvent evt) {
JLabel source = (JLabel) evt.getSource();
for (JLabel label : labels) {
if (label == source) {
label.setBackground(HOVER_COLOR);
} else {
label.setBackground(null);
}
}
}
}
private static void createAndShowGui() {
ManyLabelExample mainPanel = new ManyLabelExample();
JFrame frame = new JFrame("ManyLabelExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I need to make a slot machine that implements thread in java and jframe
this is what iv'e done so far kindly tell me what i need to do in order make the images change per .5 seconds when i press the the play and stop when i press stop. If all the three images are the same it'll say you won. This is what iv'e got so far how will i change this numbers or text to images in jlabel.
public class MySlotNumber extends JFrame{
private MyJLabel x;
private MyJLabel y;
private MyJLabel z;
private JButton btn;
public MySlotNumber(){
super("ABC");
setLayout(new FlowLayout());
Font font = new Font("arial",Font.ITALIC,50);
x = new MyJLabel();
x.setFont(font);
y = new MyJLabel();
y.setFont(font);
z = new MyJLabel();
z.setFont(font);
btn = new JButton("PLAY");
btn.setFont(font);
add(x);
add(y);
add(z);
add(btn);
final Thread thx = new Thread(x);
final Thread thy = new Thread(y);
final Thread thz = new Thread(z);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("PLAY")){
if(thx.isAlive()){
thx.resume();
thy.resume();
thz.resume();
} else {
thx.start();
thy.start();
thz.start();
}
btn.setText("STOP");
} else {
thx.suspend();
thy.suspend();
thz.suspend();
btn.setText("PLAY");
System.out.println(x.getText());
}
}
});
}
- - - - - - --
public class MyJLabel extends JLabel implements Runnable{
private Random r;
private int ctr;
private final int T = 500;
public MyJLabel(){
setText("0");
ctr = 0;
r= new Random();
}
#Override
public void run() {
while(true){
try {
Thread.sleep(T);
} catch (InterruptedException ex) {
Logger.getLogger(MyJLabel.class.getName()).log(Level.SEVERE, null, ex);
}
//ctr++;
ctr = r.nextInt(9)+1;
setText(String.valueOf(ctr));
}
}
}
Here is one way to put a picture on a JLabel and change it when you click a button. (I am using window builder for eclipse, so it may look a little odd.) It is not recommended you use absolute paths because when you move your project or the file, it breaks (I did this just for proof of concept).
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Test {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Test window = new Test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Test() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 1379, 643);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblNewLabel = new JLabel("");
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Andrew\\Pictures\\Random Pictures\\Capture.JPG"));
frame.getContentPane().add(lblNewLabel, BorderLayout.CENTER);
JButton btnClickMe = new JButton("click me");
btnClickMe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
lblNewLabel.setIcon(new ImageIcon("C:\\Users\\Andrew\\Pictures\\Random Pictures\\I'm pretty sure he did.JPG"));
}
});
frame.getContentPane().add(btnClickMe, BorderLayout.EAST);
}
}
First Time three random images shown on Jframe from three diffrent arrays.
even MouseClicked Method triggered but images does not refresh in Frame.
I want to refresh three random images each time i click on Frame.
Please help
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.*;
public class Cards extends JFrame implements MouseListener {
public static void main(String[] args) {
JFrame frame = new Cards();
frame.setTitle("Cards");
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
new Cards();
}
public Cards() {
this.getContentPane().addMouseListener(this);
cards1();
cards2();
cards3();
}
public void cards1() {
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void cards2() {
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images1//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void cards3() {
// this.getContentPane().addMouseListener(this);
ImageIcon[] images = new ImageIcon[10];
for (int i = 1; i < images.length; i++) {
images[i] = new ImageIcon("Drawables//Images2//" + i + ".png");
}
int[] threeRandoms = new int[1];
Random ran = new Random();
for (int i = 0; i < threeRandoms.length; i++) {
threeRandoms[i] = ran.nextInt(10);
}
// Labels with gridLayout
setLayout(new GridLayout(1, 4, 5, 5));
add(new JLabel(images[threeRandoms[0]]));
}
public void mouseClicked(MouseEvent e) {
System.out.println("The frame was clicked.");
new Cards();
}
public void mouseEntered(MouseEvent e) {
System.out.println("The mouse entered the frame.");
}
public void mouseExited(MouseEvent e) {
System.out.println("The mouse exited the frame.");
}
public void mousePressed(MouseEvent e) {
System.out.println("The left mouse button was pressed.");
}
public void mouseReleased(MouseEvent e) {
System.out.println("The left mouse button was released.");
}
}
I'm sorry, but I'm confused by your code. For one thing your cards1(), cards2() and cards3() methods look to be all the very same, and if so, why 3 different methods? Why not just one method? In those methods you appear to be trying to add JLabels repeatedly. Are you trying to add many many JLabels to the GUI? Or are you simply trying to display 3 images that change randomly on mouse action?
I would recommend structuring things a bit differently:
If possible, read all necessary images in once in your class's constructor, put the images into ImageIcons and then add them to an ArrayList or several ArrayLists if need be.
Don't add new JLabels each time a mouseClick occurs.
Create a JPanel give it a GridLayout and in your class constructor add to it three JLabels that are either instance fields or in an array or ArrayList.
Add this JPanel to your JFrame.
Add a MouseListener to each JLabel
in that MouseListener's mousePressed(MouseEvent e) method (not mouseClicked) randomize your number and use that number to call setIcon(...) on the JLabel source, obtained by calling getSource() on your MouseEvent parameter.
For example:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomImages extends JPanel {
private static final int LABEL_COUNT = 3;
private Random random = new Random();
public RandomImages() {
setLayout(new GridLayout(1, 3));
for (int i = 0; i < LABEL_COUNT; i++) {
final List<Icon> iconList = new ArrayList<>();
// TODO: get images for the ith list
// and fill iconList with ImageIcons from the first grouping
// create JLabel and give it the first Icon from the List above
final JLabel label = new JLabel(iconList.get(0));
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
// get random number from random object using iconList.size()
// get random Icon from list
// set label's icon via setIcon(...)
}
});
// add to GUI
add(label);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RandomImages());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Concrete example 2:
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomChessMen extends JPanel {
// for this example I get a sprite sheet that holds several sprite images in it
// the images can be found here: http://stackoverflow.com/questions/19209650
private static final String IMAGE_PATH = "http://i.stack.imgur.com/memI0.png";
private static final int LABEL_COUNT = 2;
private static final int ICON_COLUMNS = 6;
private Random random = new Random();
public RandomChessMen() throws IOException {
URL url = new URL(IMAGE_PATH);
BufferedImage largeImg = ImageIO.read(url);
setLayout(new GridLayout(1, 0));
// break down large image into its constituent sprites and place into ArrayList<Icon>
int w = largeImg.getWidth() / ICON_COLUMNS;
int h = largeImg.getHeight() / LABEL_COUNT;
for (int i = 0; i < LABEL_COUNT; i++) {
final List<Icon> iconList = new ArrayList<>();
int y = (i * largeImg.getHeight()) / LABEL_COUNT;
// get 6 icons out of large image
for (int j = 0; j < ICON_COLUMNS; j++) {
int x = (j * largeImg.getWidth()) / ICON_COLUMNS;
// get subImage
BufferedImage subImg = largeImg.getSubimage(x, y, w, h);
// create ImageIcon and add to list
iconList.add(new ImageIcon(subImg));
}
// create JLabel
final JLabel label = new JLabel("", SwingConstants.CENTER);
int eb = 40;
label.setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
// get random index for iconList
int randomIndex = random.nextInt(iconList.size());
Icon icon = iconList.get(randomIndex); // use index to get random Icon
label.setIcon(icon); // set label's icon
label.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
Icon secondIcon = label.getIcon();
// so we don't repeat icons
while (label.getIcon() == secondIcon) {
int randomIndex = random.nextInt(iconList.size());
secondIcon = iconList.get(randomIndex);
}
label.setIcon(secondIcon);
}
});
// add to GUI
add(label);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomImages");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
frame.getContentPane().add(new RandomChessMen());
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I have made these changes to your code:
Instead of having three methods cards1() cards2() cards3(), i have just made one cards() method.
Everytime you click on the frame, three random images get loaded.
I have set every image inside a JLabel in order to make it easy to update it.
The code below works perfectly according to your needs.
package example;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
public class Cards extends JFrame implements MouseListener {
JPanel subPanel1;
JLabel label1, label2, label3;
static ImageIcon[] images ;
static Random ran ;
static int[] threeRandoms;
public Cards() {
super("Cards");
subPanel1 = new JPanel();
// Set up first subpanel
subPanel1.setPreferredSize (new Dimension(400, 400));
//subPanel1.setBackground (Color.cyan);
label1 = new JLabel ("image 1",SwingConstants.CENTER);
label2 = new JLabel ("image 2", SwingConstants.LEFT);
label3 = new JLabel ("image 3", SwingConstants.CENTER);
subPanel1.add (label1);
subPanel1.add (label2);
subPanel1.add (label3);
add(subPanel1);
addMouseListener(this);
setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
System.out.println("Success.....");
}
public void cards() {
for (int i = 0; i < threeRandoms.length; i++)
threeRandoms[i] = ran.nextInt(3);
label1.setIcon(images[threeRandoms[0]]);
label2.setIcon(images[threeRandoms[1]]);
label3.setIcon(images[threeRandoms[2]]);
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouseClicked");
cards();
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println("mouseEntered");
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println("mouseExited");
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
}
#Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased");
}
public static void loadImages(){
images = new ImageIcon[4];
ran = new Random();
threeRandoms = new int[3];
for (int i = 1; i <= images.length; i++) {
images[i-1] = new ImageIcon("Drawables//Images//" + i + ".png");
}
}
public static void main(String[] args) {
loadImages();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Cards();
}
});
}
}
I am trying to add a 2D JButton array to a JFrame, I don't get any errors, just the JButtons don't show up.
Creating the JButtons:
public class TTTGrid {
private static JFrame frame;
private static int[][] coords;
private static int width, height;
public TTTGrid(JFrame frame,int[][] coords, int width, int height){
this.frame = frame;
this.coords = coords;
this.width = width;
this.height = height;
}
static JButton map[][] = new JButton[3][3];
public void Draw(){
for(int i = 0; i<coords.length; i++){
for(int j = 0; j<coords[i].length; j++){
map[i][j] = new JButton();
map[i][j].setBounds(i*100, j*100, width, height);
frame.add(map[i][j]);
}
}
}
}
Where the draw method is called:
public class TTTthread extends TTT implements Runnable {
int[][] map = new int[3][3];
TTTGrid grid = new TTTGrid(frame, map, 100, 100);
#Override
public void run() {
try {
while (true) {
grid.Draw();
Thread.sleep(20);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
If your code is running like I think it's running, you appear to be trying to add 9 JButtons to your GUI 50 times a second! That's a heck of a lot of buttons -- are you sure that this is what you want to be doing? Your code also runs far afoul of Swing threading rules by making Swing calls (a lot of Swing calls!) off of the Swing event thread.
Your main solution is likely to
Add your 9 JButtons to a JPanel that uses a GridLayout(3, 3)
Do this only once not 50 times a second
Then add that JPanel to your GUI, BorderLayout.CENTER and to be sure not to use null layouts.
Not try to set the bounds, size or locations of these JButtons, but rather to let the layout managers to the work
Get rid of that while loop and instead change your code to be more event-driven using Swing's event driven model.
Strive to use mostly non-static variables and methods so that your classes become true OOPS-compliant classes, allowing them to take advantage of the benefits of OOPS programming, including reducing program complexity and interconnectedness (reduce coupling).
For example
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class MyTttFoo extends JPanel {
// it's OK for constants to be static
private static final long serialVersionUID = 1L;
private static final int ROWS = 3;
// use a larger Font to make buttons larger
private static final Font BTN_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 60);
private static final String BLANK = " ";
private static final String X = "X";
private static final String O = "O";
// but not most variables
private JButton[][] buttonGrid = new JButton[ROWS][ROWS];
public MyTttFoo() {
setBackground(Color.black);
// use layout managers to help you create your GUI
setLayout(new GridLayout(ROWS, ROWS, 1, 1));
ActionListener btnListener = new ButtonListener();
// create your buttons and add them only **once**
for (int row = 0; row < buttonGrid.length; row++) {
for (int col = 0; col < buttonGrid[row].length; col++) {
JButton button = new JButton(BLANK);
button.setFont(BTN_FONT);
button.addActionListener(btnListener);
add(button); // add button to a gridlayout using component
buttonGrid[row][col] = button; // and assign into the array
}
}
}
private class ButtonListener implements ActionListener {
private boolean xTurn = true;
#Override
public void actionPerformed(ActionEvent e) {
AbstractButton btn = (AbstractButton) e.getSource();
String txt = btn.getText();
if (txt.equals(BLANK)) {
if (xTurn) {
btn.setText(X);
} else {
btn.setText(O);
}
xTurn = !xTurn;
}
}
}
private static void createAndShowGui() {
MyTttFoo mainPanel = new MyTttFoo();
JFrame frame = new JFrame("MyTttFoo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}