What is wrong using this keyword in Swing? - java

I am asking this question due to mKorbel's second comment on this question. I have been using this keyword to call local variables, local components of that class (example Buttons) and methods e.t.c. I am not sure what is wrong with using the keyword the way I have been doing it.
don't to use this.whatever in Swing, Java, (in MCV make me some sence), use local variables insted of.
Question: What is wrong with using this.XXX in Swing?
Sample Code
public class SwingTest extends JFrame {
// variables
private String st = "You clicked me";
SwingTest() {
this.initUI();
}
private void initUI() {
this.setTitle("Swing Test");
this.setSize(200, 200);
this.setLayout(new BorderLayout());
this.setVisible(true);
this.clickMe = new JButton("Click"); // What is wrong with using this
// ref here?
this.add(clickMe);
this.clickMe.addActionListener((ActionEvent) -> {
JOptionPane.showMessageDialog(this, this.st);// What is wrong with
// using this ref
// here?
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SwingTest swingTest = new SwingTest();
}
});
}
// components
JButton clickMe;
}

The button clickMe does not need to be a field. It can be a local variable JButton clickMe inside the dialog defining method/constructor. As normally many GUI components are created and added to the window, it cleans up the class, keeps declarations close to usage, and leaves the life-time as short as possible (on changing window contents).
(The talk about this is merely to point out the fieldness of clickMe.)

Related

How to check JToggleButton state in a class from another class using IF-statement that have actionPerformed within it?

EDIT : I found my problem but still don't have a clue for why this happen, I'm still not finished Online Lectures from Professor Mehran
Sahami (Stanford), maybe I'll find an answer if I push on on the
lecture videos.
The problem is I remove my other components methods before my button
method for efficient posting space, so I should put my JToggleButton
method after my main JFrame method for it to work, but what if my
other components inherit other class too? Which method should I put first to make all of components works? That I'll found out with
practicing java more.
Thank you #Dan and #SebVb for answers and suggestions, sorry if this
just a beginners mistake :)
I am learning java for a month now and already had simple project for learning but now I have problems with JToggleButton, ItemEvent, and actionPerformed included in If-statement.
I've searching for a week for examples on using actionPerformed within if-statement that have ItemEvent from another class but i can't find a same problem to produce a working result.
I'm trying to make a window scanner that will scan only if toggle button is selected then paint JPanel using buffered image (repaint every 100 millisecond) and disposed it if toggle button is deselected, but I think my approach to do it is wrong. I have one main class and two sub-classes like these:
Main class:
public class WindowScanner {
public static void main(String[] args) {
new Window().setVisible(true);
}
}
Window class:
class Window extends JFrame {
static JToggleButton captureButton = new JToggleButton("CAPTURE");
#SuppressWarnings("Convert2Lambda")
public Window() {
// JFrame looks codes
/** EDIT: these components method should be written after button method
* JPanel looks codes
* JLabel looks codes
* END EDIT
*/
add(captureButton);
// capture button default looks code
ItemListener captureListener = new ItemListener(){
#Override
public void itemStateChanged(ItemEvent captureButtonEvent) {
int captureState = captureButtonEvent.getStateChange();
if(captureState == ItemEvent.SELECTED){
// capture button SELECTED looks code
System.out.println("capture button is selected");
} else if(captureState == ItemEvent.DESELECTED){
// capture button DESELECTED looks code
System.out.println("capture button is deselected");
}
}
}; captureButton.addItemListener(captureListener);
}
}
Scanner class:
public class Scanner extends Window {
private static BufferedImage boardCaptured;
static int delay = 100;
protected BufferedImage boardScanned(){
return boardCaptured;
}
#SuppressWarnings("Convert2Lambda")
public static void Scan() {
if (captureButton.isSelected()) {
ActionListener taskPerformer = new ActionListener() {
#Override
public void actionPerformed(ActionEvent captureEvent) {
try {
// capturing method
} catch (AWTException error) {
// AWTException error method
}
// is this the right place to put JPanel code?
JPanel panel = new JPanel();
boardCaptured = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphic = boardCaptured.createGraphics();
panel.setSize(500,500);
panel.paint(graphic);
panel.revalidate();
panel.repaint();
}
}; new Timer(delay, taskPerformer).start();
} else {
// this suppose to end capturing if capture button isSelected() == false
}
}
}
So here is my questions:
Do I really have to make Main class separated from Window class?
What the reason?
How to make my if statement in Scan method recognize state of my
JToggleButton from Window class? Is it impossible and I had a wrong
approach to do it?
In Scanner class, i can't make a get/set for my actionPerformed
(Netbeans always checked it as an error), but why I can make one for
BufferdImage?
If I can't get question number 3 happen, how can I make If statement
to stop capturing using Timer.stop()? Or am I in wrong approach again?
Do my JPanel in Scanner class would be produced and make a viewer
for my buffered image?
P.S. I'm sorry it cramped with questions, I tried not to make multiple post, so I make single post with multiple questions. Please notice me if there's answer before, I'm honestly can't find it or had search it with wrong tags.
Here is a simple version of what I think you want to do. This can be edited to include your variables, such as boardCaptured. This code mainly portrays how to get a component from a different class.
Main.java (Contains all the classes in one java file)
import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.JFrame;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.Timer;
class WindowScanner extends JFrame {
private JLabel label;
private JToggleButton captureButton = new JToggleButton("CAPTURE");
WindowScanner() {
super("Fist Window");
setSize(150, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
add(captureButton);
setVisible(true);
new Scanner(this);
}
public JToggleButton getCaptureButton() {
return captureButton;
}
}
class Scanner extends JFrame {
private WindowScanner wS;
private int delay = 1000;
private Timer t = new Timer(delay, new taskPerformer());
Scanner(WindowScanner wS) {
super("Second Window");
this.wS = wS;
setBounds(200,0,500,500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
wS.getCaptureButton().addActionListener(new taskPerformer());
}
private Color randomColor() {
Random rand = new Random();
float r = rand.nextFloat() / 2f ;
float g = rand.nextFloat() / 2f;
float b = rand.nextFloat() / 2f;
Color randomColor = new Color(r, g, b);
return randomColor;
}
private class taskPerformer implements ActionListener {
#Override
public void actionPerformed(ActionEvent captureEvent) {
if(captureEvent.getSource() == wS.getCaptureButton()) {
if (wS.getCaptureButton().isSelected()) {
t.start();
} else {
t.stop();
}
}
if(captureEvent.getSource() == t) {
getContentPane().setBackground(randomColor());
revalidate();
repaint();
}
}
}
}
public class Main {
public static void main (String[] args) {
new WindowScanner();
}
}
This particular piece of code changes the color of the background in the second JFrame to a random color every second using a timer from javax.swing.timer. This code portrays how to get a component, or a variable if you change it, from a different class.
It is mainly these code fragments which allow it.
1
public JToggleButton getCaptureButton() {
return captureButton;
}
This allows other classes to get the component.
2
private WindowScanner wS;
Scanner(WindowScanner wS) {
...
this.wS = wS;
...
}
This makes the current instance of WindowScanner and the instance of WindowScanner declared in Scanner the same instance.
Note: Look into using public getters and setters.
As for your 5 listed questions.
1) Do I really have to make Main class separated from Window class? What the reason?
In most cases yes you do. As SebVb said it is good practice. However you can do something like this if you wish to have them in the same class.
import javax.swing.JToggleButton;
import javax.swing.JFrame;
import java.awt.FlowLayout;
public class Test extends JFrame {
private JToggleButton captureButton = new JToggleButton("CAPTURE");
Test() {
super("Fist Window");
setSize(150, 100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
add(captureButton);
setVisible(true);
}
public JToggleButton getCaptureButton() {
return captureButton;
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Test frame = new Test();
}
});
}
}
2) How to make my if statement in Scan method recognize state of my JToggleButton from Window class? Is it impossible and I had a wrong approach to do it?
You were using the wrong approach to do this. See the code and code fragments I have put above for how to do it correctly. (Using public getters.)
3) In Scanner class, i can't make a get/set for my actionPerformed (Netbeans always checked it as an error), but why I can make one for BufferdImage?
I can't entirely say I'm sure what you are asking but see my code above to see if that helps. If it doesn't leave a comment trying to fully explain what you mean.
4) If I can't get question number 3 happen, how can I make If statement to stop capturing using Timer.stop()? Or am I in wrong approach again?
In my code I show you how this can be related to the JToggleButton. See code fragment below
private class taskPerformer implements ActionListener {
#Override
public void actionPerformed(ActionEvent captureEvent) {
if(captureEvent.getSource() == wS.getCaptureButton()) {
if (wS.getCaptureButton().isSelected()) {
t.start();
} else {
t.stop();
}
}
if(captureEvent.getSource() == t) {
getContentPane().setBackground(randomColor());
revalidate();
repaint();
}
}
}
This code says when the JToggleButton fires an ActionEvent if it is selected then start the timer, t.start(), or if it is not selected stop the timer, t.stop().
5) Do my JPanel in Scanner class would be produced and make a viewer for my buffered image?
Again I'm not entirely sure what you are asking but here is my best guess. You have two options.
1
Put boardCaptured directly on the frame.
paint(graphic);
repaint();
revaildate();
2
Create a JPanel like you did but outside the ActionListener
JPanel panel = new JPanel()
boardCaptured = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphic = boardCaptured.createGraphics();
panel.setSize(500,500);
panel.paint(graphic);
add(panel);
private class taskPerformer implements ActionListener {
if(captureEvent.getSource() == t) {
panel.paint(graphic);
panel.revalidate();
panel.repaint();
}
}
I think there's an easier way do do what do you want. Taking your questions by order
Having the main class separated from your Window class allow you to re-use your Windows class everywhere you want. It's a good pratice to only init your GUI objects on your main class
Why don't you have your JToggleButton private and a mehtod wwhich will access to his status ? also, with a static field, all your instaces of Windows will share the same JToggleButton.
It's an anonymous class that contains your actionPerformed method. If you want to see it, you have to create an inner class.
I think your approch is wrong. Using a thread, which will launch your repaint with a specific delay is better. If you create a class which extends Runnable, you can check the state of your button and then do the appropriate action
Your JPanel is inside an ActionListener, i've never seen that and i don't think that it can works.
In a shorter version
Put in your Window class your JPanel, BufferedImage and JToggleButton
Create a specific thread to do your repainting when the JToggleButton is selected

How to change a JLabel with a button from another class?

I have two classes and a text file database, The JLabel in the first class, let's call it class1 automatically set it self to the number in the database. Now, in class2 I have this little JFrame and a text field and of course a button, the value I put in the text field overwrites the one in the database, but here's the problem. The label in the first class wont update while running, but if I restart it it will show me the value that I want.
How do I update it while the program is running?
I've tried to change the label in the buttonActionperformed in the other class but it gives me a NullPointException every time.
How do I fix this?
THE MAIN CLASS ( JUST THE JFRAME )
package BankrollG;
import java.awt.Graphics;
import javax.swing.JFrame;
public class BGbrain {
BGbody body = new BGbody();
JFrame Frame = new JFrame();
public BGbrain() {
Frame.setSize(body.width, body.height);
Frame.setTitle(body.title);
Frame.setResizable(false);
Frame.setDefaultCloseOperation(Frame.EXIT_ON_CLOSE);
Frame.add(body.panel);
Frame.setLocationRelativeTo(null);
Frame.setFocusable(true);
Frame.setVisible(true);
}
public static void main(String[] args ) {
new BGbrain();
}
}
Then you got the class with the components:
private JLabel bankroll_label
public BGbody(){
panel.setLayout(null);
windowComponents();
}
public void windowComponents() {
// Bankroll database access
try {
FileReader fr = new FileReader("Bankroll.txt");
BufferedReader br = new BufferedReader(fr);
set_bankroll = br.readLine();
} catch(IOException e) {
System.out.println("FEL MED LĂ„SNING AV DATABAS /// BGBODY");
}
}
}
THEN you got the JFrame class that I created with the netbeans function
private void AddcurrencyActionPerformed(java.awt.event.ActionEvent evt) {
String CBR = txt_bankroll.getText();
try {
FileWriter fw = new FileWriter("Bankroll.txt");
PrintWriter pw = new PrintWriter(fw);
pw.println(CBR);
pw.close();
} catch(IOException e) {
System.out.println("FEL MED INSKRIVNINGEN I DATABASEN");
}
}
Now, everything goes as plan, but I can't update my JLabel "bankroll_label" from the button class because it just returns nullpointsexceptions. The data is there, because the JLabel reads from the database but it wont update when changes has been made from the button class. So a getter setter method wont work because the value IS there but it wont update the JLabel.
I hope this made it easier to understand my problem.
It's ALOT more code, that dont have to do with this, I hope I simplified it at least some.
Your question is a specific example of a basic problem in programming in Java -- how to transfer information between classes. There are several ways to do this, one of the most elegant being giving to use a "model" class that holds your program's logic code and key data, having one class change the model's state by changing a text String that it holds. Then using a listener or observer pattern, have the model notify the other class that it has been changed so the other class can extract the new information, its new String from the model. While this is likely the best solution, it may be a bit of overkill and likely is above your current level of coding, so for you, I'm not going to recommend this.
Instead, I'm going to recommend a simpler less elegant solution, that you instead have one class call a setter method of the other to push the new String into it.
One problem we have as volunteer answerers here is that your question is hard to answer because it lacks critical code, making it hard for us to guess why your code is misbehaving, why specifically you're running into a NullPointerException (or NPE) when you try to run it. So all I can do is guess, but guess I will try nevertheless.
For simplicity's sake, let's call one class the, the one that holds the JLabel, the LabelClass and the other class the ButtonTextFieldClass.
One possible reason is that you've got a NullPointerException is because your ButtonTextFieldClass may have a LabelClass variable, but never initialized the variable, something like so:
// this guy is null because it is never initialized
private LabelClass labelClass;
A simple solution could be to try to initialize it like so:
private LabelClass labelClass = new LabelClass();
But this won't work because while it does create and assign a LabelClass instance, it's likely not the LabelClass instance that is visualized in the running GUI.
A better solution is to give the ButtonTextFieldClass a setter method that allows other classes to set the ButtonTextFieldClass with the proper LabelClass instance.
e.g.,
public void setLabelClass(LabelClass labelClass) {
this.labelClass = labelClass;
}
This way the code that sets up both classes can pass the visualized LabelClass to the first class, and it can call methods on it.
A simple example of LabelClass could look like so:
class LabelClass extends JPanel {
private JLabel label = new JLabel("");
public LabelClass() {
setBorder(BorderFactory.createTitledBorder("Label Panel"));
add(label);
}
public void setLabelText(String text) {
label.setText(text);
}
}
I have it extend JPanel because this way it gives me the freedom of placing it into a JFrame or JDialog or other JPanel as I see fit. Note that I've made the JLabel private and have given the class a public setter method, setLabelText(String text), that allows outside classes the ability to set the JLabel's text.
The ButtonTextFieldClass could look something like:
class ButtonTextFieldClass extends JPanel {
private JTextField textField = new JTextField(10);
private JButton button = new JButton(new ButtonAction("Send Text"));
private LabelClass labelClass;
public ButtonTextFieldClass() {
setBorder(BorderFactory.createTitledBorder("Button TextField Panel"));
add(textField);
add(button);
}
// here we allow other classes to set instances of our LabelClass
public void setLabelClass(LabelClass labelClass) {
this.labelClass = labelClass;
}
// ....
I've also given the button an AbstractAction in place of an ActionListener since it is like a super ActionListener on steroids. Inside of it, I'd get the text from the JTextField and then call the LabelClass's setter method (if the variable is not null) to set the label's text:
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
if (labelClass != null) {
labelClass.setLabelText(text);
}
}
Then to set everything up, in another class I'd create instances of both LabelClass and ButtonTextFieldClass, and then "hook them up" by calling the setter method:
LabelClass labelClass = new LabelClass();
ButtonTextFieldClass buttonTextFieldClass = new ButtonTextFieldClass();
buttonTextFieldClass.setLabelClass(labelClass); // set our reference
The whole thing could look like so:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class TransferData {
private static void createAndShowGui() {
LabelClass labelClass = new LabelClass();
ButtonTextFieldClass buttonTextFieldClass = new ButtonTextFieldClass();
buttonTextFieldClass.setLabelClass(labelClass); // set our reference
JPanel mainPanel = new JPanel(new GridLayout(0, 1));
mainPanel.add(buttonTextFieldClass);
mainPanel.add(labelClass);
JFrame frame = new JFrame("TransferData");
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();
}
});
}
}
class LabelClass extends JPanel {
private JLabel label = new JLabel("");
public LabelClass() {
setBorder(BorderFactory.createTitledBorder("Label Panel"));
add(label);
}
public void setLabelText(String text) {
label.setText(text);
}
}
class ButtonTextFieldClass extends JPanel {
private JTextField textField = new JTextField(10);
private JButton button = new JButton(new ButtonAction("Send Text"));
// one possible solution -- give this class a variable
// of the LabelClass -- but don't initialize the variable
// here, but rather do it in a setter
private LabelClass labelClass;
public ButtonTextFieldClass() {
setBorder(BorderFactory.createTitledBorder("Button TextField Panel"));
add(textField);
add(button);
}
// here we allow other classes to set instances of our LabelClass
public void setLabelClass(LabelClass labelClass) {
this.labelClass = labelClass;
}
// an AbstractAction is like a "super" ActionListener
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name); // set the button's text and actionCommand
int mnemonic = (int) name.charAt(0); // get first char
putValue(MNEMONIC_KEY, mnemonic); // set mnemonic
}
#Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
if (labelClass != null) {
labelClass.setLabelText(text);
}
}
}
}
For simplicity's sake, I've displayed both JPanels within the same GUI, but it could work just as well if one JPanel were in one JFrame and the other within a JDialog.

How do you close a JFrame dialog box?

When I put in the code below I get the error: "local variable classWindow is accessed from within inner class; needs to be declared final."
classWindow.dispose();
I did put:
private final void classWindow
and I still get the error.
private final void classWindow() {
// Create the frame
JFrame classWindow = new JFrame("Pick A Class");
// Set the size of the frame
classWindow.setSize(230, 150);
// Specify an action for the close button.
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add a layout manager to the content pane.
setLayout(new GridLayout());
JButton warriorButton = new JButton("Warrior");
warriorButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
userClass = "Warrior";
classWindow.dispose();
}});
classWindow.add(warriorButton, BorderLayout.WEST);
classWindow.setLocationRelativeTo(null);
classWindow.setVisible(true);
}
Yes, I did look it up and that's why I tried the 'final' thing and it doesn't seem to work on my code for some weird reason. I'm sure it is a very simple fix.
The ultimate reason is confusing way to name variables and methods. The error is referring to the variable, which need to be final:
final JFrame classWindow = new JFrame("Pick A Class");
I would seriously recommend also picking a different name for it.

JButton disappears when resize

anyone know or have an idea as to why my button disappears after i resize the applet?
this is my code:
import java.awt.event.*;
import javax.swing.*;
import acm.program.*;
public class button extends ConsoleProgram {
public void init(){
hiButton = new JButton("hi");
add(hiButton, SOUTH);
addActionListeners();
}
public void actionPerformed(ActionEvent e){
if(hiButton == e.getSource()){
println("hello") ;
}
}
private JButton hiButton;
}
I'm not sure if it is a good Idea to redefine the init-method. When I have a look at http://jtf.acm.org/javadoc/student/acm/program/ConsoleProgram.html I would expect that you have implement only the run-method. Overriding init without calling super.init() Looks strange to me.
Maybe I would be better to derive from JApplet directly for your first steps in Applet programming.
Assuming that
your ConsoleProgram extends (directly or indirectly) JApplet
You declared SOUTH as a static final variable that has the value BorderLayout.SOUTH (otherwise your code doesn't compile)
The code should work, no need to repaint (unless you would like to do some application-specific optimization). I just copied and pasted your code (by expliciting the two assumptions above), I see the applet and the button doesn't disappear on resize.
Anyway there are few "not good" things in the code:
First of all, a naming convention issue: the class name should be "Button" with the first letter capitalized (on top of that, it's a poor name for an Applet)
Second, action listeners should be attached before adding the component;
Third, as Oracle doc suggests here, the code that builds the GUI should be a job that runs on the event dispatcher thread. You can do that by wrapping the build gui code in a Runnable using a SwingUtilities.invokeAndWait(Runnable()
Have you tried calling super.init() at the start of your init() method?
Try explicitly using a layout for your Console and then use relative positioning.
To re-size a button in Applet:
public class Button extends JApplet implements ActionListener {
private JButton button;
public void init() {
Container container = getContentPane();
container.setLayout(null);
container.setBackground(Color.white);
button = new JButton("Press Me");
button.setSize(getWidth()/2,20);
button.setLocation(getWidth()/2-button.getSize().width/2, getHeight()/2-button.getSize().height/2);
container.add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
int width = (button.getSize().width == getWidth()/2) ? getWidth()/4 : getWidth()/2;
int height = button.getSize().height;
button.setSize(width,height);
button.setLocation(getWidth()/2-width/2, getHeight()/2-height/2);
}
}
To re-size a button in JFrame:
public class Button extends JFrame implements ActionListener {
private JButton button;
public Button(String title) {
Container container = getContentPane();
container.setLayout(null);
container.setBackground(Color.white);
setTitle(title);
setSize(400,400);
button = new JButton("Press Me");
button.setSize(getWidth()/2,20);
button.setLocation(getWidth()/2-button.getSize().width/2,
getHeight()/2-button.getSize().height/2);
container.add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
int width = (button.getSize().width == getWidth()/2) ? getWidth()/4 : getWidth()/2;
int height = button.getSize().height;
button.setSize(width,height);
button.setLocation(getWidth()/2-width/2, getHeight()/2-height/2);
}
public static void main(String[] args) {
Button button = new Button("Test");
button.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button.setVisible(true);
}
}
Have you declared the repaint method...???
You are using swing. It needs to have declared a repaint.
Please define a custom repaint mwthod

Using an ActionListener in one class to start a timer in another class

I have a class (simulation) which creates an instance of another class (GUI). Inside the class GUI there is a button (start) which has an actionlistener attached to it.
I need this actionlistener to start a timer in simulation but I can't figure out how to do it.
Code in Class Simulation:
public class Simulation{
private static JFrame frame;
private static GUI control;
public static Integer xcontrol = 100, ycontrol = 100;
public Timer timer;
public int steps;
public static void main(String[] args) {
Simulation sim = new Simulation ();
}
public Simulation() {
frame = new JFrame("Action Listener Test");
frame.setLayout(new BorderLayout(1,0));
control = new GUI (xcontrol, ycontrol);
frame.getContentPane().add(control , BorderLayout.CENTER);
frame.setResizable(false);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void StartTimer() {
timer.start();
System.out.println("It worked!");
}
Code in Class GUI:
panel1.add(button1a);
button1a.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent event) {
Simulation.StartTimer();
}
} );
The error Eclipse tells me there is, is that for "Simulation.timer.start();" :
Cannot make a static reference to the non-static method StartTimer() from the type Simulation.
However the method StartTimer() cannot be static as this seems to break the timer...
Any help would be very appreciated.
Pass this as an argument to the GUI constructor.
In general it is best to avoid such cyclic references. Both the GUI and Simulator become dependent upon one another. The essence of the solution is to separate out the GUI from the interesting domain-specific behaviour.
(BTW: I would strongly avoid using static variables for anything other than constants. Also avoid non-private instance variables. But point for not extending JFrame!)
There is some hideous boilerplate that you should add to prevent multithreading.
public static void main(final String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
Simulation sim = new Simulation();
}});
}
What I would do is have your GUI class expose the button via a getButton() method, then after creating the GUI object, your Simulation class can add its own ActionListener to the button, e.g. control.getButton().addActionListener(new ActionListener()... etc.

Categories