Not all buttons showing up in Java? - java

When I run my program using eclipse only one button shows up (top left corner) but when I use javac in terminal (most of the time) all buttons show up! It's really bugging me. Can anyone help? Thanks!This is my constructor:
public TicTacToe(){
super("Farm Tic-Tac-Toe");
setSize(450,750);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cont = getContentPane();
cont.setLayout(null);
int newLine = 0;
int lineCount = 0;
for(int i = 0; i < buttons.length; i++){
buttons[ i] = new JButton(blank);
if(i == 3 || i == 6){
newLine++;
lineCount = 0;
}
buttons[ i].setBounds(lineCount*150,newLine*150,150,150);
cont.add(buttons[ i]);
buttons[ i].addActionListener(this);
lineCount++;
}
}
and here's the action listener...
public void actionPerformed(ActionEvent e){
for(int i = 0; i < buttons.length; i++){
if(e.getSource()==buttons[ i]){
if(turn%2==0){
buttons[ i].setName("x");
buttons[ i].setIcon(x);
buttons[ i].removeActionListener(this);
}
else{
buttons[ i].setName("o");
buttons[ i].setIcon(o);
}
buttons[ i].removeActionListener(this);
}
}
turn++;
checkWin();
}
Please don't tell me too much about how my code design is bad because I am (not a beginner, but) not too good at Java.

You're calling setVisible(true) before adding all of your components to the GUI, so it is not showing them all. Don't do this. Instead call setVisible(true) after all components have been added.
Also
As has been suggested by many, don't use null layout, but instead learn about and use the layout managers.
Yeah, get another book.

The solution to the problem is really very simple...
The first one is the lack of a layout manager and the other is the order in which you are displaying your UI (as has already being stated)
public class SimpleTicTacToe {
public static void main(String[] args) {
new SimpleTicTacToe();
}
public SimpleTicTacToe() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new GamePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePane extends JPanel {
public GamePane() {
setLayout(new GridLayout(3, 3));
for (int index = 0; index < 9; index++) {
add(new JButton());
}
}
}
}
Take the time to read through Creating a GUI With JFC/Swing to gain a grasp of the basics.

The Eclipse GUI only renders buttons that are drawn in certain very specific ways. If your code does it differently (for example, with a Loop), Eclipse won't be able to draw it.
Also, use a LayoutManager, don't do things like .setLayout(null)

Related

Disable Buttons on JAVA but leave unique button alone

According to my previous question here:
Remove a Button with same text when clicked
I need that the only buttons that appearing more then one will disappearing while clicking on them
Problem is when clicking on the "Unique" ones ( see picture ), they will disappear also.
My code:
private String namesArr[] = {"Yakir","Yarden","Igor","Maoz","Moshe","Israel","Tal","Haim","Nati","Mor","Daniel","Idan"};
private Button buttonArr[] = new Button[namesArr.length];
private Font font;
public StudentsGUI(String caption) {
super(caption);
addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
dispose();
System.exit(0);
}
});
this.setLayout(new GridLayout(3,3));
font = new Font("Ariel",Font.BOLD,35);
for(int i=0;i<namesArr.length;i++) {
buttonArr[i] = new Button(" "+namesArr[(int)(Math.random()*namesArr.length)]);
buttonArr[i].setFont(font);
buttonArr[i].addActionListener(this);
this.add(buttonArr[i]);
}
setLocation(800,500);
setVisible(true);
pack();
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof Button) {
String btnText = ((Button)e.getSource()).getLabel();
for(int i=0; i<buttonArr.length; i++) {
if (buttonArr[i].getLabel().equals(btnText)) {
this.remove(buttonArr[i]);
pack();
}
}
}
}
The picture to help you understand:
So if clicking on "Idan", witch is a unique name nothing will happen as it only have one instance, but if clicking on "Maoz" all the buttons with "Maoz" title will disappear ( this already happening )
using collections as per #Freddy's answer should be better. However if you're to stick with arrays, something like below should do it (haven't tested it though)
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof Button) {
String btnText = ((Button)e.getSource()).getLabel();
int counter = 0;
for(int i=0; i<buttonArr.length; i++) {
if (buttonArr[i].getLabel().equals(btnText)) counter++;
if (count > 1) {
for(int j=0; j<buttonArr.length; j++) {
if (buttonArr[j].getLabel().equals(btnText))
this.remove(buttonArr[j]);
}
}
}
pack();
}
}
You mean something like this (code may have syntax errors)?
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof Button) {
String btnText = ((Button)e.getSource()).getLabel();
List<Button> btnList = new ArrayList<Button>();
for(int i=0; i<buttonArr.length; i++) {
if (buttonArr[i].getLabel().equals(btnText)) {
btnList.add(buttonArr[i]);
//this.remove(buttonArr[i]);
//pack();
}
}
if (btnList.size() > 1) {
for (Iterator<Button> it = btnList.iterator(); it.hasNext()) {
this.remove(it.next());
}
pack();
}
}
}

Swing going from menu to actual gameplay

So I am making a space invaders clone. Originally I had no problem getting my game to work with a simple main class that created the frame, created the gameplay and started the thread.
But then I tried to implement a start menu and it all went to crap. The menu appears with success but the gameplay does not appear when I press start.
I am running out of ideas and I am completely stumped. I am somewhat new as well to SO, so if there is anything I left out, I appreciate any help.
Here is the original with no menu that worked fine:
public static void main(String[] args) {
JFrame frame = new JFrame("SpaceRaiders");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Gameplay gameplay = new Gameplay();
frame.add(gameplay);
frame.setVisible(true);
Thread t1 = new Thread(gameplay);
t1.start();
}
However, the moment I tried to implement a menu to then play the game, I am running into all sorts of trouble. I created a UI class as well as an actual "game" class like so:
public class UI {
JFrame frame, f2;
JPanel titrePanel, startButtonPanel, loadButtonPanel, p2;
JLabel nomJeu;
JButton startButton, loadButton;
Font fontTitre, fontStart;
Gameplay gameplay;
public void createUI(ChoixJeu cj) {
frame = new JFrame("SpaceRaiders");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setLayout(null);
frame.getContentPane().setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//------------------ECRAN MENU---------------------
//Titre
titrePanel = new JPanel();
titrePanel.setBounds(100, 100, 400, 100);
titrePanel.setBackground(Color.BLUE);
Font fontTitre = new Font("Times New Roman", Font.BOLD, 50);
Font fontStart = new Font("Times New Roman", Font.PLAIN, 20);
nomJeu = new JLabel("SpaceRaiders");
nomJeu.setForeground(Color.white);
nomJeu.setFont(fontTitre);
titrePanel.add(nomJeu);
//Start button
startButtonPanel = new JPanel();
startButtonPanel.setBounds(200, 400, 200, 40);
startButtonPanel.setBackground(Color.BLACK);
startButton = new JButton("START");
startButton.setBackground(Color.BLACK);
startButton.setForeground(Color.WHITE);
startButton.setFont(fontStart);
startButton.setFocusPainted(false);
startButton.addActionListener(cj);
startButton.setActionCommand("start");
startButtonPanel.add(startButton);
//Load Button
loadButtonPanel = new JPanel();
loadButtonPanel.setBounds(200, 440, 200, 100);
loadButtonPanel.setBackground(Color.BLACK);
loadButton = new JButton("LOAD");
loadButton.setBackground(Color.BLACK);
loadButton.setForeground(Color.WHITE);
loadButton.setFont(fontStart);
loadButton.setFocusPainted(false);
titrePanel.add(nomJeu);
loadButtonPanel.add(loadButton);
frame.add(startButtonPanel);
frame.add(titrePanel);
//------------------ECRAN MENU FIN---------------------
frame.setVisible(true);
}
And the game class...
public class Jeu {
ChoixJeu cj = new ChoixJeu();
UI ui = new UI();
Ecrans e = new Ecrans(ui);
Gameplay gp;
public static void main(String[] args) {
new Jeu();
}
public Jeu() {
ui.createUI(cj);
Gameplay gameplay = new Gameplay();
this.gp = gameplay;
}
public class ChoixJeu implements ActionListener {
#Override
public void actionPerformed(ActionEvent ae) {
String yourChoice = ae.getActionCommand();
switch (yourChoice) {
case "start":
e.montrerEcranJeu();
new Thread(gp).start();
ui.frame.add(gp);
break;
default:
break;
}
}
}
}
I also tried to make a class/method that hides the menu panels
public void montrerEcranJeu() {
//Cache Menu
ui.titrePanel.setVisible(false);
ui.startButtonPanel.setVisible(false);
//Montre Jeu
// ui.frame.add(gameplay);
}
And just in case the Gameplay class. The run() method is at the bottom
public class Gameplay extends JPanel implements KeyListener, ActionListener, Runnable {
private Ship player = new Ship(new Point(200, 555));
Timer t = new Timer(5, this);
private ArrayList<Laser> lasers = new ArrayList<Laser>();
private int laserNb;
private boolean readytofire;
private boolean shot = false;
private ArrayList<Invader> invaders = new ArrayList<Invader>();
private boolean pause;
public Gameplay() {
super();
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
for (int j = 0; j < 80; j += 20) {
for (int i = 0; i < 20; i++) {
invaders.add(new Invader(5 + i * 30, j));
}
}
}
public boolean addLaser(Laser a) {
lasers.add(a);
return true;
}
public boolean addPlayer(Ship p) {
this.player = p;
return true;
}
#Override
public void keyTyped(KeyEvent ke) {
}
public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_RIGHT == e.getKeyCode()) {
moveRight();
}
if (KeyEvent.VK_LEFT == e.getKeyCode()) {
moveLeft();
}
if (KeyEvent.VK_SPACE == e.getKeyCode()) {
shoot();
System.out.println("Space Action from Gameplay is working");
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void actionPerformed(ActionEvent ae) {
repaint();
}
public void moveRight() {
if (player.getCentre().getX() >= 580) {
player.setX(580);
} else {
double movement = player.getCentre().getX();
movement += 10;
player.setX(movement);
}
this.repaint();
}
public void moveLeft() {
if (player.getCentre().getX() <= 20) {
player.setX(20);
} else {
double movement = player.getCentre().getX();
movement -= 10;
player.setX(movement);
}
this.repaint();
}
public void shoot() {
shot = true;
if (readytofire) {
Point top = new Point(player.getTopX(), player.getTopY());
Laser laser = new Laser(top);
addLaser(laser);
}
}
public void moveShot() {
if (shot) {
for (Laser l : lasers) {
l.setY(l.getTopLeft().getY() - 1);
}
}
}
#Override
public void paint(Graphics g) {
setBackground(Color.black);
super.paint(g);
player.draw(g);
for (Laser l : lasers) {
l.draw(g);
}
for (Invader i : invaders) {
i.draw(g);
}
}
// public void paintComponent (Graphics g){
// Controle Thread
public void run() {
while (true) {
moveShot();
for (Invader i : invaders) {
i.moveAndUpdate();
}
// for (Invader i : invaders) {
// if (){
// System.out.println("YOU ARE DEAD!");
// }
// }
try {
Thread.sleep(10);
readytofire = true;
} catch (InterruptedException ex) {
Logger.getLogger(Gameplay.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
So, using null layouts is the beginning of your problems. I might recommend using CardLayout which is designed to help you dynamically switch between views. See How to Use CardLayout for more details. I'd also suggest taking the time to read through Laying Out Components Within a Container and finding one or more appropriate layouts to support your menu.
You're also making a lot of fundamental mistakes. Swing is not thread safe, so you should avoid updating the UI (or something the UI depends on) from outside the context of the EDT - see Concurrency in Swing for more information and How to Use Swing Timers for a possible solution.
As a general recommendation, you should avoid overriding paint and, in the case of classes which extend from JComponent, prefer paintComponent instead. You should also avoid call methods which might change the state of the component during a paint cycle, this can increase the number of repaint requests and degrade the performance of your program (ie, don't call setBackground inside paint).
Have a look at Performing Custom Painting and Painting in AWT and Swing for more details about how the paint system works and how best you can work with it.
You should also avoid KeyListener, this is likely to cause you issues when you introduce other, focusable, components into the picture. Instead, you should favour the Key bindings API instead
I've read through [insert link or tutorial], but it still doesn't help...
And forgive me if this doesn't happen all the time.
The point of providing you the tutorial links is to encourage you to learn something;
Learn where to find answers to your questions
Learn how the APIs work
Expand your knowledge and understanding of how the APIs work
Having said that, they're not always "obvious" as to the solution. What I do when I'm in this situation is start with one or more new projects, dedicated to just working on that aspect of the API I'm trying to understand. For here I can explore the concepts in isolation and when I "think" I understand them, try and implement them into the project I'm working on. This might take a number of iterations, but once it works, I have gained a much deeper understanding and appreciation of the API then I would have gained from a simple "copy-n-paste" solution

How to update look and feel clean seperate in a class?

I want to update my look and feel by JRadioButtonMenuItem. And I searching in Stackoverflow but what I find was a big bunch of code in 1 class. For me as a beginner its easier to seperate function in a special class.
That is my Frame-Class.
public class CalenderFrame extends JFrame {
public CalenderFrame() throws HeadlessException {
createFrame();
}
public void createFrame() {
setJMenuBar(CalenderMenuBar.getInstance().createMenu());
setTitle("Calender");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(400, 300));
pack();
setLocationRelativeTo(null);
setVisible(true);
}
}
And that is my MenueBar Class. I just give a short one of Code that is specific for this question. This class is an Singleton.
public JMenuBar createMenu() {
JMenu lookAndFeelMenu = new JMenu("Look & Feel");
JRadioButtonMenuItem lAndFWindowsItem = new JRadioButtonMenuItem("Windows",true);
lAndFWindowsItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == lAndFWindowsItem) {
lAndFAction(1);
}
}
});
JRadioButtonMenuItem lAndFMetalItem = new JRadioButtonMenuItem("Metal",false);
lAndFMetalItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == lAndFMetalItem) {
lAndFAction(2);
}
}
});
JRadioButtonMenuItem lAndFMotifItem = new JRadioButtonMenuItem("Motif", false);
lAndFMotifItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == lAndFMotifItem) {
lAndFAction(3);
}
}
});
ButtonGroup group = new ButtonGroup();
group.add(lAndFWindowsItem);
group.add(lAndFMetalItem);
group.add(lAndFMotifItem);
lookAndFeelMenu.add(lAndFWindowsItem);
lookAndFeelMenu.add(lAndFMetalItem);
lookAndFeelMenu.add(lAndFMotifItem);
}
public void lAndFAction(int counter) {
try {
String plaf = "";
if (counter == 1) {
plaf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
} else if (counter == 2) {
plaf = "javax.swing.plaf.metal.MetalLookAndFeel";
} else if (counter == 3) {
plaf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
}
UIManager.setLookAndFeel(plaf);
//SwingUtilities.updateComponentTreeUI(this);
} catch (UnsupportedLookAndFeelException ue) {
System.err.println(ue.toString());
} catch (ClassNotFoundException ce) {
System.err.println(ce.toString());
} catch (InstantiationException ie) {
System.err.println(ie.toString());
} catch (IllegalAccessException iae) {
System.err.println(iae.toString());
}
}
}
I hope you guys can help me.
I'm not sure what your problem actually is. But, you must update your components after changing the LaF. According to the Look and Feel Documentation:
Changing the Look and Feel After Startup
You can change the L&F with setLookAndFeel even after the program's
GUI is visible. To make existing components reflect the new L&F,
invoke the SwingUtilities updateComponentTreeUI method once per
top-level container. Then you might wish to resize each top-level
container to reflect the new sizes of its contained components. For
example:
UIManager.setLookAndFeel(lnfName);
SwingUtilities.updateComponentTreeUI(frame);
frame.pack();
Therefore, you would need a reference to the frame holding the components in your UI. An idea would be doing something like:
public class CalendarMenuBar {
// Add this field to tour factory
private static JFrame frameThatWillBeUpdated;
// ... (Your code goes here)
// update this method to receive the reference of the frame which will
// need to be refreshed (update the GUI)
public JMenuBar createMenu(JFrame frame) {
// sets the reference for the frame
frameThatWillBeUpdated = frame;
// ... (the rest of your code for this method)
}
// ...
// Update this method to refresh the frame
public void lAndFAction(int counter) {
try{
// ... (your code)
// Set the LaF
UIManager.setLookAndFeel(plaf);
// Update the component tree (frame and its children)
SwingUtilities.updateComponentTreeUI(frameThatWillBeUpdated);
// repack to resize
frame.pack();
} catch(Exception ex){
// Your catches
}
}
}
And here is how you use it when creating your frame (inside your CalenderFrame class):
public void createFrame() {
// use this frame as reference
setJMenuBar(CalenderMenuBar.getInstance().createMenu(this));
// ... (your code goes here)
}

Jbutton event handler not working properly

rollDice.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//generate roll
int roll = dice.getRoll();
addGameFeedMessage(players[1].getName() + " rolled " + roll);
//store the player's position before the roll
int currentPlayerPos = players[1].getPosition();
//update player's position
players[1].movePlayer(roll);
//move the player icon to the player's position
tiles[players[1].getPosition()].addIconCurrentPlayersPanel(players[1].getPlayerIcon());
//revalidate components
//tiles[currentPlayerPos].getCurrentPlayersPanel().revalidate();
//tiles[players[1].getPosition()].getCurrentPlayersPanel().revalidate();
//this loop was put in to see if doing revalidate() on all panels would make a difference but the problem is still there
for(int i = 0; i < tiles.length; i++)
{
tiles[i].getCurrentPlayersPanel().revalidate();
}
}
});
Can anyone explain why the for loop in the actionListener for roll dice doesn't seem to work yet the for loop just above it which is the exact same thing works? There's no actual error as such it just doesn't do anything, however it does get inside the actionListener and executes as we've put print statements etc in it.
Guessing its something strange about actionListeners but I'm not sure what.
Any assistance would be appreciated, thankyou.
You should call validate() after the for loop as follows:
for(int i = 0; i < getNumOfPlayers(); i++)
{
currentPlayersOnTile[5].add(players[i].getPlayerIcon());
}
validate();
For Example consider the code given below:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class DemoPanels extends JFrame
{
public void createAndShowGUI()
{
final JPanel panel = new JPanel();
getContentPane().add(panel);
JButton button = new JButton("Click");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
for (int i = 0 ; i < 10 ; i++ )
{
JPanel panel1 = new JPanel();
panel1.add(new JButton(String.valueOf(i)));
panel.add(panel1);
}
validate();//comment this line and then compile and execute the code to see the effect
}
});
getContentPane().add(button,BorderLayout.SOUTH);
setVisible(true);
setSize(300,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
DemoPanels dp = new DemoPanels();
dp.createAndShowGUI();
}
});
}
}
NOTE: comment the code validate() and then compile and execute it to see the effect.

JButton Not performing Any Action

Hi I have a JButton defined like:
private JButton btnExp;
private JPanel jpShow = new JPanel();
jpShow.setLayout(null);
btnExp = new JButton("Export");
btnExp.setBounds(100, 250, 120, 25);
jpShow.add(jspTable);
jpShow.add(btnExp);
//Adding Panel to Window.
getContentPane().add(jpShow);
public void actionPerformed(ActionEvent ae) {
try{
Object obj = ae.getSource();
if (obj == btnExp) {
FileWriter excel = new FileWriter("File.TSV");
for(int i = 0; i < dtmCustomer.getColumnCount(); i++){
excel.write(dtmCustomer.getColumnName(i) + "\t");
}
excel.write("\n");
for(int i=0; i< dtmCustomer.getRowCount(); i++) {
for(int j=0; j < dtmCustomer.getColumnCount(); j++) {
excel.write(dtmCustomer.getValueAt(i,j).toString()+"\t");
}
excel.write("\n");
}
excel.close();
JOptionPane.showMessageDialog(this, "File Written","Success", JOptionPane.PLAIN_MESSAGE);
}
}catch(Exception e){
System.out.println(e);
}
}
Am trying to get the JTable to be exported after the user clicks the button but nothing happens and no exception is raised. Am I doing it the wrong way?
You are not adding the ActionListener to your button correctly. The correct way is:
btnExp.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// add here the contents in your actionPerformed method
}
})
The code you post will not even compile
You should add the ActionListener to your JButton as #Dan already showed in his answer
You should make sure you close the FileWriter in a finally block. Now, when an exception occurs it will not be closed
You will end up with a non-responsive UI if you export the table on the Event Dispatch Thread. Consider using a SwingWorker. Consult the Concurrency in Swing tutorial for more information
Avoid the use of setLayout( null ) and setBounds. Use a decent LayoutManager instead

Categories