Snippet of code is here:
int area;
int[] xcoords = new int[3];
xcoords[0] = coordsAX;
xcoords[1] = coordsBX;
xcoords[2] = coordsCX;
sortArray(xcoords);
int[] ycoords = new int[3];
ycoords[0] = coordsAY;
ycoords[1] = coordsBY;
ycoords[2] = coordsCY;
sortArray(ycoords);
//Remember, array[0] is the biggest and array[2] is the smallest!
int rectWidth = xcoords[0] - xcoords[2];
int rectHeight = ycoords[0] - ycoords[2];
area = (rectWidth * rectHeight);
System.out.println(area);
lblArea.setText("Area: " + area);
The entirety of the code is within the paint(g) method of my applet. I'm aiming to let the user be able to see the JLabel. Calculations go absolutely fine. But when I run, the applet looks like:
I've gathered that the setText line should not be in paint(g) but, in that case, where should it go in order to make it so the JLabel remains the same until a new triangle is generated (by clicking "Click Me" button)?
Please note that I'm a high schooler teaching myself Java and, as a result, my knowledge of the language looks like a hunk of Swiss Cheese. I'd appreciate explanations that don't explain too many topics that are well above the level of basic applet making. :)
Appreciate any help! Thanks!
Presumably you have an action listener attached to the "click me" button.
When the action is fired, I would update the label and the UI at that point.
You might like to have a read through How to Write an Action Listener
(I'm also kind of worried that it looks like you're using AWT instead of Swing, but I could be mistaken ;))
UPDATED example
public class TestArea {
public static void main(String[] args) {
new TestArea();
}
public TestArea() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AreaPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AreaPane extends JPanel {
private JLabel areaLabel;
public AreaPane() {
areaLabel = new JLabel("Area: ...");
JButton clickMe = new JButton("Click Me");
clickMe.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
areaLabel.setText("Area: " + NumberFormat.getNumberInstance().format(Math.random() * 1000));
// update UI as required
}
});
add(areaLabel);
add(clickMe);
}
}
}
Related
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
I have a problem with one of my frames not looking as it should, when it is called upon the press of a button.
The frame looks as if it was rendered improperly, the label text in it is shortened, however when i move the same line of code outside the action listener, it works as it should.
I have a sort of main menu, with two buttons, only the Generate Menu works at the moment, it looks like this:
https://i.imgur.com/k1Ne5v9.png
The code for the action listener:
runMenuButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Generate Menu pressed");
mF.dispose();
MenuGenerator.generateTheMenu();
}
});
The result looks wrong: https://i.imgur.com/n86y4CD.png
The frame is also unresponsive, clikcing X does not, while it should close the frame and the application.
However changing the code to:
runMenuButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Generate Menu pressed");
//mF.dispose();
}
});
MenuGenerator.generateTheMenu();
Produces correct look: https://i.imgur.com/TFbkmAO.png
The code for the "Main menu"
public static void openMainMenu() {
Font menuFont = new Font("Courier",Font.BOLD,16);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mF.setSize(465,230);
mF.setLocation(dim.width/2-mF.getSize().width/2, dim.height/2-mF.getSize().height/2);
mF.getContentPane().setBackground(Color.WHITE);
Color blueSteel = new Color(70,107,176);
JPanel p = new JPanel();
p.setSize(600,50);
p.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
p.setLocation((mF.getWidth() - p.getWidth()) /2, 20);
p.setBackground(blueSteel);
JLabel l = new JLabel("Welcome to the menu GENERATORRRR");
l.setFont(menuFont);
l.setForeground(Color.WHITE);
p.add(l, gbc);
JButton runMenuButt = new JButton("Generate Menu");
runMenuButt.setLocation(20 , 90);
JButton manageRecipButt = new JButton("Manage Recipients");
manageRecipButt.setLocation(240 , 90);
menuUtilities.formatButton(runMenuButt);
menuUtilities.formatButton(manageRecipButt);
mF.setResizable(false);
mF.setLayout(null);
mF.add(runMenuButt);
mF.add(manageRecipButt);
mF.add(p);
mF.setVisible(true);
runMenuButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Generate Menu pressed");
//mF.dispose();
}
});
MenuGenerator.generateTheMenu();
manageRecipButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Not supported yet", "Function not yet available",JOptionPane.INFORMATION_MESSAGE);
}
});
//System.out.println(mF.getContentPane().getSize());
}
And the status bar:
public class StatusBar {
private static JLabel statusLabel= new JLabel("Starting");
private static JFrame statusFrame = new JFrame("Generation Status");
public static void createStatusBar() {
Font menuFont = new Font(Font.MONOSPACED,Font.BOLD,20);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
statusFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
statusFrame.setSize(700,100);
JPanel p = new JPanel();
p.setPreferredSize(new Dimension(100,100));
statusLabel.setFont(menuFont);
p.add(statusLabel);
statusFrame.add(p,BorderLayout.CENTER);
statusFrame.setLocation(dim.width/2-statusFrame.getSize().width/2, dim.height/2-statusFrame.getSize().height/2);
statusFrame.setVisible(true);
}
public static void setStatusBar(String statusText) {
statusLabel.setText(statusText);
statusLabel.paintImmediately(statusLabel.getVisibleRect());
statusLabel.revalidate();
}
public static void closeStatusBar(){
statusFrame.dispose();
}
}
I create the bar with this line:
StatusBar.createStatusBar();
Why does the status bar not render properly when the MenuGenerator.generateTheMenu(); is called from the action listener?
Here is minimal code that reproduces this behavior for anyone who would like to test it: It also uses class for the StatusBar, which is already posted.
public class MinimalClass {
private static JFrame mF = new JFrame("Main Menu");
public static void main(String[] args) {
openMainMenu();
}
public static void openMainMenu() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mF.setSize(465,230);
mF.setLocation(dim.width/2-mF.getSize().width/2, dim.height/2-mF.getSize().height/2);
mF.getContentPane().setBackground(Color.WHITE);
JButton runMenuButt = new JButton("Generate Menu");
runMenuButt.setLocation(20 , 90);
runMenuButt.setSize(200 , 85);
mF.setResizable(false);
mF.setLayout(null);
mF.add(runMenuButt);
mF.setVisible(true);
runMenuButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Generate Menu pressed");
mF.dispose();
generateTheMenu();
}
});
}
public static void generateTheMenu() {
System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
String rawMenuOutput = "";
try {
rawMenuOutput= getMenuInJavaNow();
} catch (Exception e){
System.out.println("Something went terribly wrong");
}
System.out.println(rawMenuOutput);
}
public static String getMenuInJavaNow() throws IOException {
String rawMenuOutput = "Restaurant Menu" ;
rawMenuOutput = rawMenuOutput + "Test line";
String []menuOtpArr = new String [3];
try {
StatusBar.createStatusBar();
TimeUnit.SECONDS.sleep(2);
StatusBar.setStatusBar("Test1");
TimeUnit.SECONDS.sleep(2);
menuOtpArr[0]="Test line";
StatusBar.setStatusBar("Test2");
TimeUnit.SECONDS.sleep(2);
menuOtpArr[1]="Test line";
StatusBar.setStatusBar("Test3");
TimeUnit.SECONDS.sleep(2);
menuOtpArr[2]="Test line";
StatusBar.setStatusBar("Test4");
TimeUnit.SECONDS.sleep(2);
StatusBar.closeStatusBar();
} catch (Exception e) {
}
for (int i=0;i < menuOtpArr.length;i++) {
rawMenuOutput = rawMenuOutput + "\n\n" +menuOtpArr[i];
}
return rawMenuOutput;
}
}
Thank you for your time
statusLabel.paintImmediately(statusLabel.getVisibleRect()); seems to masking a larger issue.
The problem is, Swing is single threaded (and NOT thread safe). This means that when you call TimeUnit.SECONDS.sleep(2); from within getMenuInJavaNow, which is called by generateTheMenu, which is called by the ActionListener, it's been called within the context of the Event Dispatching Thread.
This is putting the EDT to sleep, meaning that it isn't processing layout or paint requests (properly)
Start by having a read of Concurrency in Swing for more details
Now, you have a larger issue, how to solve it. For the answer to that question, we require a lot more context then is currently available.
The getMenuInJavaNow seems to be returning some values, to what end I'm not sure.
"A" solution, would be to use a SwingWorker (see Worker Threads and SwingWorker for more details). It provides the ability to execute long running tasks in the background, but also provides the means for sync updates back to the UI, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
public class MinimalClass {
private static JFrame mF = new JFrame("Main Menu");
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
openMainMenu();
}
});
}
public static void openMainMenu() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mF.setLocationRelativeTo(null);
mF.getContentPane().setBackground(Color.WHITE);
JButton runMenuButt = new JButton("Generate Menu");
runMenuButt.setMargin(new Insets(25, 25, 25, 25));
JPanel buttons = new JPanel(new GridLayout(0, 2));
buttons.add(runMenuButt);
mF.add(buttons);
mF.pack();
mF.setVisible(true);
runMenuButt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Generate Menu pressed");
mF.dispose();
generateTheMenu();
}
});
}
public static void generateTheMenu() {
System.setProperty("sun.java2d.cmm", "sun.java2d.cmm.kcms.KcmsServiceProvider");
StatusBar.createStatusBar();
SwingWorker<String, String> worker = new SwingWorker<String, String>() {
#Override
protected String doInBackground() throws Exception {
String rawMenuOutput = "Restaurant Menu";
rawMenuOutput = rawMenuOutput + "Test line";
String[] menuOtpArr = new String[3];
try {
TimeUnit.SECONDS.sleep(2);
publish("1234567890123456789012345678901234567890");
TimeUnit.SECONDS.sleep(2);
publish("This is a test");
TimeUnit.SECONDS.sleep(2);
publish("More testing");
TimeUnit.SECONDS.sleep(2);
publish("Still testing");
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
}
for (int i = 0; i < menuOtpArr.length; i++) {
rawMenuOutput = rawMenuOutput + "\n\n" + menuOtpArr[i];
}
return rawMenuOutput;
}
#Override
protected void done() {
StatusBar.closeStatusBar();
}
#Override
protected void process(List<String> chunks) {
StatusBar.setStatusBar(chunks.get(chunks.size() - 1));
}
};
worker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (worker.getState() == SwingWorker.StateValue.DONE) {
try {
String result = worker.get();
System.out.println(result);
StatusBar.closeStatusBar();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}
}
});
worker.execute();
}
public static class StatusBar {
private static JLabel statusLabel = new JLabel("Starting");
private static JFrame statusFrame = new JFrame("Generation Status");
public static void createStatusBar() {
Font menuFont = new Font(Font.MONOSPACED, Font.BOLD, 20);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
statusFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
statusFrame.setSize(700, 100);
JPanel p = new JPanel();
p.setBackground(Color.RED);
// p.setPreferredSize(new Dimension(100, 100));
statusLabel.setFont(menuFont);
p.add(statusLabel);
statusFrame.add(p, BorderLayout.CENTER);
statusFrame.setLocationRelativeTo(null);
statusFrame.setVisible(true);
}
public static void setStatusBar(String statusText) {
statusLabel.setText(statusText);
}
public static void closeStatusBar() {
statusFrame.dispose();
}
}
}
Observations...
static is not your friend, especially in cases like this. You really, really, really need to learn to live without it.
setLayout(null) is not doing you any favours, especially in the long run. Take the time to go through Laying Out Components Within a Container and start making proper use of layout managers, they might seem "complicated", but they will save you from a lot of hair loss
Avoid using setPreferred/Minimum/MaximumSize where ever possible, you are robing the component of the ability to provide useful rendering hints which may change across platforms and rendering pipelines
Just a quick follow up question, what is the difference between done and addPropertyListener ? Is there any? Isnt it redundant to use both?
The example here is pretty basic, for me I've used done to handle what the SwingWorker "knows" needs to be done, it doesn't however, know what is to be done with the result.
I've used the PropertyChangeListener to deal with that instead - the point - it's an example.
And I also noticed, that I dont need to actually publish, as calling StatusBar.setStatusBar(""); works as well. Is it necessary to use publish?
In a word YES. Swing is NOT thread safe, calling StatusBar.setStatusBar("") directly can lead to some weird and unexpected results. publish pushes the call into the Event Dispatching Thread, making it safe to update the UI from within.
I have the code for generating the String I want to set as the StatusBar Title in another class, not in the generateTheMenu, therefore it is more convenient for me to simply call .setStatusBar. The not minimal code I have is actually something like this
This is where things like interfaces come in really handy. You "string" generating class "could" either return the resulting text OR you could pass a reference to a interface implementation which is used to "display" it. This way, your SwingWorker could act as a consumer for the String and pass it through the publish method.
There are a number of really important concepts to understand.
You want to decouple your code. This makes it easier to change certain parts of the code without affecting the other parts
You want to be able to "code to interface, not implementation". This goes hand in hand with the first comment. Basically, you want to "hide" the implementation details as much as possible - lots of different reasons for it, but it helps keep your code lean, helps make the follow more understandable and stops one part of the code from accessing another it really has no responsibility to do so (is the string generation really responsible for updating the status bar? IMHO - not really)
There is also a swagger of design patterns available to make solving issues easier. I've already mentioned the concept of "produce/consumer", but this is just one
The "Event Dispatching Thread"
The Event Dispatch Thread
Java Event-Dispatching Thread explanation
Swing threading and the event-dispatch thread
I'm self learning java beginner
i'm trying to create simple calculator using java swing and i want to create array of JButtons to create all the buttons in the project , i had some issues so i declare all variables outside the constructor
public class SimpleCalculator extends JFrame implements ActionListener {
JButton btnArray[] = new JButton[16];
JLabel nameLabel = new JLabel("Ghanayem's Calculator",
SwingConstants.CENTER);
JTextField txt = new JTextField();
JPanel numPanel = new JPanel(new GridLayout(4, 3, 15, 5));
JPanel opPanel = new JPanel(new GridLayout(4, 1, 0, 5));
JPanel panel = new JPanel(new GridLayout(2, 1, 0, 5));
int counter;
char operation;
double operand1;
double operand2;
like that ,and i think to add actions to buttons inside for-loop no compiler errors every thing is ok
for (counter = 0; counter < 10; counter++) {
btnArray[counter] = new JButton("" + counter);
btnArray[counter].addActionListener(this);
}
and here is action performed implementation
#Override
public void actionPerformed(ActionEvent e) {
txt.setText(txt.getText() + counter);
}
just like that ,when i try to run the program and press any number button the number added to text field is "16" for all buttons, and this is main method
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SimpleCalculator frame = new SimpleCalculator();
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
i am getting crazy i don't know what is wrong , please i need your help this my first swing application i am so disperate
thank you
Try something like this (I can't test right now so it may contain some lesser errors):
#Override
public void actionPerformed(ActionEvent e) {
String value = ((JButton)e.getSource()).getText();
Integer intValue = Integer.parseInt(value);
Integer intValue2 = Integer.parseInt(txt.getText());
txt.setText( "" + (intValue + intValue2));
}
#Override
public void actionPerformed(ActionEvent e) {
JButton b = (JButton) e.getSource();
txt.replaceSelection(b.getActionCommand());
}
this is a solution for my question i found here
java-action-listener
#Override
public void actionPerformed(ActionEvent e) {
String value = (JButton) e.getSource().getText();
txt.setText(txt.getText() + value);
}
and this is another solution #Paco Abato helps me to find
I've been trying to call a method which displays frames in an EditorWindow, when pushing a button in the ExplorerWindow.
There are 3 modules:
AppEditorAPI which contains this interface
package org.app.AppEditorAPI;
public interface Displayer {
public void Display();
}
AppEditor which contains EditorTopComponent
#ServiceProvider(service=Displayer.class)
public final class EditorTopComponent extends TopComponent implements Displayer{
private JDesktopPane jdpDesktop=null;
private int openFrameCount = 0;
...
protected void createFrame() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
jdpDesktop.add(frame);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
}
}
class MyInternalFrame extends JInternalFrame {
int xPosition = 30, yPosition = 30;
public MyInternalFrame() {
super("IFrame #" + (++openFrameCount), true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
setLocation(xPosition / openFrameCount, yPosition / openFrameCount);
// Add some content:
add(new JLabel("hello IFrame #" + (openFrameCount)));
}
}
public void Display(){
jdpDesktop = new JDesktopPane();
createFrame(); // Create first window
createFrame(); // Create second window
createFrame(); // Create third window
//Add the JDesktop to the TopComponent
add(jdpDesktop);
}
}
And AppExplorer which contains ExplorerTopComponent
public final class ExplorerTopComponent extends TopComponent {
...
private void initComponents() {
B_Display = new javax.swing.JButton();
..
}
private void B_DisplayActionPerformed(java.awt.event.ActionEvent evt) {
Displayer D = Lookup.getDefault().lookup(Displayer.class);
D.Display();
}
...
}
Below, are links to the project zip file.
http://dl.free.fr/k2Z6DRLrW
http://www.fileswap.com/dl/lCeFPcUfbg/
After doing some tests. I found that I can't change (add, remove or edit) the variables or properties of the EditorTopComponent.
Like in this case, these two lines;
public void Display(){
jdpDesktop = new JDesktopPane();
...
add(jdpDesktop);
}
Are not executed as they should, that's why after the execution, the EditorTopComponent.jdpDesktop still was equal to null and wasn't added to the EditorTopComponent.
Knowing what I want to do, can someone please guide me on the right track ?
At last, 'made It work... see that's what happens when you avoid reading the books :P
I'm posting the solution if anyone's facing the same issue.
As I mentioned when editing my question, knowing that modifications are not allowed through the lookup, you can either use the InstanceContent variable which can be modified in the lookup, or, use the WindowManager to fitch the EditorTopComponent and call the Display() method.
Good luck
I'm trying to write a game applet that responds to keys typed by the player. I'm trying to use key bindings to accomplish this. But I can't get it to work. The applet (what little of it there is, at the moment) seems to display correctly in Appletviewer, but nothing happens when I press keys. I haven't been able to test it in a browser, as it doesn't always display correctly in a browser.
I'm running Sun Java 6 on Ubuntu. I managed to find mention of a Ubuntu bug where iBus would block keyboard input to applets. However, I don't have iBus running, and I've been able to use keyboard input with other applets (not written by me).
Here is the code so far
public class AlxTestVersion extends JApplet {
private GridBagLayout layout;
private GridBagConstraints layoutConstraints;
private JPanel mainPanel;
public void init() {
this.setLayout ( new FlowLayout(FlowLayout.LEFT) );
//Main frame.
mainPanel = new JPanel();
layout = new GridBagLayout();
layoutConstraints = new GridBagConstraints();
layoutConstraints.anchor = GridBagConstraints.NORTHWEST;
layoutConstraints.fill = GridBagConstraints.NONE;
mainPanel.setLayout(layout);
mainPanel.setBackground(Color.pink);
getContentPane().add(mainPanel);
//Map display
JPanel leftPanel = new JPanel();
GlobalData.mainMap = new MapCanvas(9);
addComponent(GlobalData.mainMap, 0, 0, 1, 1);
/*
Define other components...
*/
}
public class MapCanvas extends JPanel {
private int tileSize;
private int mapTileWidth;
private int mapOffset;
private int mapDim;
private MapSquare screenTiles[];
public void paintComponent(Graphics g) {
super.paintComponent(g);
ImageIcon testImage = new ImageIcon("tiles/test_land.gif");
int x,y;
for (x=0;x<mapTileWidth;x++) {
for (y=0;y<mapTileWidth;y++) {
g.drawImage(testImage.getImage(), x*tileSize + mapOffset, y*tileSize + mapOffset, this);
}
}
}
public MapCanvas(int numTiles) {
//Set up window
tileSize = 48;
mapTileWidth = numTiles;
mapOffset = 4;
mapDim = (tileSize * mapTileWidth) + (2 * mapOffset);
Dimension dim = new Dimension(mapDim, mapDim);
this.setPreferredSize(dim);
this.setMinimumSize(dim);
this.setMaximumSize(dim);
this.setLayout( new GridLayout(numTiles, numTiles, 0, 0) );
this.setBackground(Color.black);
screenTiles = new MapSquare[numTiles^2];
//Map-related actions
InputMap im = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = this.getActionMap();
AbstractAction north = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Just for testing", "testing",
JOptionPane.PLAIN_MESSAGE);
}
};
am.put("North", north);
im.put(KeyStroke.getKeyStroke('2'), "North");
im.put(KeyStroke.getKeyStroke('i'), "North");
}
}
About the only difference I can find between what I've used and working examples found in various places is they add the keystroke to the inputmap before mapping the keystroke to the action. I tried switching the order, but it didn't seems to have any effect.
Can anyone see what I'm doing wrong here? I just know I'm missing something obvious.
Your code doesn't work for me either (on a mac), until I click inside the window. Adding the following as the last thing in init() seems to help (but is not totally reliable):
GlobalData.mainMap.requestFocus();
Your applet window probably does not have the focus when you press the keys.
Try adding this to your init():
GlobalData.mainMap.addFocusListener(new FocusDebugger("canvas"));
this.addFocusListener(new FocusDebugger("applet"));
Here's FocusDebugger:
public static class FocusDebugger implements FocusListener {
private final String name;
public FocusDebugger(String name) {
this.name = name;
}
public void focusGained(FocusEvent focusEvent) {
System.out.println(name + ".focusGained");
}
public void focusLost(FocusEvent focusEvent) {
System.out.println(name+".focusLost");
}
}