I'm trying to build a chessclock to learn and I'm stuck with the code below. I'll use the actionListener like this. When "White" button is pressed, blackTime will decrement one every second, when "Black" button is pressed whiteTime will decrement one every second.
Right now my problem is to find a way to decrement time each second. I saw some questions like this and they talked about Timer class. I never used it and my understanding is it requires an ActionListener. I'm already using one so do I add another somehow or is there a simpler way?
Thanks!
public class ChessClock extends JFrame implements ActionListener {
JPanel p;
JButton b1,b2;
JLabel l1;
public ChessClock(){
super();
this.setVisible(true);
this.setSize(600,400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int whiteTime = 59;
int blackTime = 59;
p = new JPanel(new GridBagLayout());
b1 = new JButton("White");
b2 = new JButton("Black");
l1 = new JLabel("00:" + whiteTime + " - " + "00:" + blackTime, SwingConstants.CENTER);
l1.setFont(new Font("Serif", Font.PLAIN, 85));
b1.setPreferredSize(new Dimension(200,100));
b2.setPreferredSize(new Dimension(200,100));
b1.addActionListener(this);
b2.addActionListener(this);
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(40,40,40,40);
p.add(b1,c);
p.add(b2,c);
this.add(p, BorderLayout.SOUTH);
this.add(l1, BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e){ //will later be used to switch between whiteTime - blackTime
String s = e.getActionCommand();
if(s == "White")
s = s;
if(s == "Black")
s = s;
}
}
From Java Docs,
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if(blackTurn)
black--;
else if(whiteTurn)
white--;
}
};
new Timer(delay, taskPerformer).start();
I think in general you should avoid using Thread.sleep() and use the built in timer class! A while loop with Thread.sleep() will hold up the thread and wait, while timer will not.
So yes, create another action performed!
How about a:
While(condition){
Thread.sleep(1000);
if(//White button pressed){
blackTime--;
}else{
whiteTime--;
}
It will wait 1s before doing the code below.
Related
I have a built tictactoe in java but due to some reason the reset and the exit buttons are not working. I am unable to solve the problem. I have searched through other questions but unable to figure out the problem with my code. The code is in separate class. There is also main class that calls the object to run the program.
The array of buttons are working fine. O and X are exactly working as I want them to but the 2nd panel with the reset and the exit buttons is not working. The program is in GUI.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Frame1 implements ActionListener {
private JButton[] board;
private int turn;
private JButton reset;
private JButton exit;
public Frame1() {
turn = 1;
JFrame frm = new JFrame("Chess");
JButton reset = new JButton("Reset");
JButton exit = new JButton("Exit");
frm.setSize(300, 300);
JPanel LowerPanel = new JPanel();
LowerPanel.add(reset);
LowerPanel.add(exit);
exit.addActionListener(this);
reset.addActionListener(this);
board = new JButton[9];
JPanel CenterPanel = new JPanel();
CenterPanel.setLayout(new GridLayout(3, 3));
for (int i = 0; i < 9; i++) {
board[i] = new JButton();
board[i].setFont(new Font("Arial", Font.BOLD, 72));
CenterPanel.add(board[i]);
board[i].addActionListener(this);
}
frm.add(CenterPanel, BorderLayout.CENTER);
frm.add(LowerPanel, BorderLayout.SOUTH);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == reset) {
for (int i = 0; i > 9; i++) {
board[i].setText(" ");
board[i].setEnabled(true);
turn = 1;
}
}
if (e.getSource() == exit) {
System.exit(0);
}
for (int i = 0; i < 9; i++) {
if (e.getSource() == board[i]) {
if (turn == 1) {
board[i].setText("X");
board[i].setEnabled(false);
} else {
board[i].setText("O");
board[i].setEnabled(false);
}
turn = (turn + 1) % 2;
return;
}
}
}
}
I want the buttons to work. if you could help me out to figure out the problem that would be a great help
Have a look at
JButton reset = new JButton("Reset");
JButton exit = new JButton("Exit");
You are assigning the buttons to local variables but in actionPerformed() you are accessing object properties.
Try
reset = new JButton("Reset");
exit = new JButton("Exit");
The actionPerformed method cannot access the reset and exit variables because they being instantiated as local variables by Frame1
JButton reset = new JButton("Reset");
JButton exit = new JButton("Exit");
As #Meini suggested try
reset = new JButton("Reset");
exit = new JButton("Exit");
This will set your global variables of reset and exit equal to the desired JButtons and allow the actionPerformed method to access them.
Also, fix your loop inside of the e.getSource() == reset if statement. The reset function won't work until you have addressed the i > 9 code. Since i starts at 0, the loop will not run since 0 is not greater than 9.
I am using java threads to manage multiple (3) programs concurrently.
1 is for Java swing form(draws UI for input), 1 is for setting an icon at systemtray (launchs immediate after taking input from UI), and 1 is for Processing inputs and reflect it to the SystemTray icon (in form of a popup message to that Tray Icon).
Earlier, I tried without separate Threads but the problem I was facing is "if the execution control once goes forward (from UI to next Process) where some repetitive task are performed using thread.sleep() method (that holds the control actually for entire time).Hence the earlier forms(UI) remains unresponsive (we cant even close the form that time).
So, I thought to implement separate threads for each of three. But as soon as I try to launch The Form (UI), it goes repetitive in infinite loop actually.
Here, is the code:
public class ImprovedImplementation {
public static void main(String[] args) {
System.out.println("Main thread is started...");
new LauncherUI();
}
}
class LauncherUI implements Runnable {
private JFrame mainFrame;
private JLabel headerLabel;
private JLabel statusLabel;
private JPanel controlPanel;
String textFieldValue = null;
Thread launcher ;
LauncherUI()
{
prepareGUI();
launcher = new Thread(this, "Launcher Thread");
System.out.println("launcher thread created" + launcher);
launcher.start();
}
public void run()
{
try
{
LauncherUI swingControlDemo = new LauncherUI();
swingControlDemo.showEventDemo();
}
catch(Exception e)
{
System.out.println("launcher thread interrupted");
}
System.out.println("launcher run is over" );
}
private void prepareGUI() {
mainFrame.setSize(450, 400);
mainFrame.setLayout(new GridLayout(3, 1));
mainFrame.setLocationRelativeTo(null);
headerLabel = new JLabel("", JLabel.CENTER);
statusLabel = new JLabel("", JLabel.CENTER);
statusLabel.setSize(350, 100);
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent) {
System.exit(0);
}
});
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
mainFrame.add(headerLabel);
mainFrame.add(controlPanel);
mainFrame.add(statusLabel);
mainFrame.setVisible(true);
mainFrame.setResizable(false);
}
private void showEventDemo() {
headerLabel.setText("Welcome to the Web Server Tracking System !!");
headerLabel.setFont(new Font("serif", Font.BOLD, 20));
JLabel l = new JLabel();
l.setText("Enter All (Servers) URLs separated by a comma ( , ) :");
l.setFont(new Font("Serif", Font.BOLD, 16));
JLabel l2 = new JLabel();
l2.setText("[for example: google.com,wikipedia.org,sjsu.edu]");
l2.setFont(new Font("Serif", Font.BOLD, 15));
JTextField txt = new JTextField(30);
JButton submitButton = new JButton("Start Tracking");
JButton cancelButton = new JButton("Close");
submitButton.setActionCommand("Start");
cancelButton.setActionCommand("Cancel");
submitButton.addActionListener(new ButtonClickListener());
submitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
textFieldValue = txt.getText();
// textFieldValue="Hello";
// .... do some operation on value ...
}
});
cancelButton.addActionListener(new ButtonClickListener());
controlPanel.add(l);
controlPanel.add(l2);
controlPanel.add(txt);
controlPanel.add(submitButton);
controlPanel.add(cancelButton);
mainFrame.setVisible(true);
}
private class ButtonClickListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("Start")) {
if (textFieldValue.equals("") || textFieldValue.indexOf(".") == -1) {
statusLabel.setText("Please Enter Some Server Urls, Before Start Tracking.");
if (textFieldValue.indexOf(".") == -1 && !textFieldValue.equals("")) {
statusLabel.setText("Please Enter Valid Urls.");
}
statusLabel.setForeground(Color.RED);
} else {
StringTokenizer urlValues = new StringTokenizer(textFieldValue, ",");
Vector v = new Vector();
while (urlValues.hasMoreTokens()) {
String token = urlValues.nextToken();
v.add(token);
}
String[] urlStrArray = (String[]) v.toArray(new String[v.size()]);
System.out.println("Took following URLS from the User:");
for(int m=0; m < urlStrArray.length;m++){
System.out.println(urlStrArray[m]);
}
statusLabel.setText("Tracking is started . . . it's pinned in your System Tray ( Task bar ).");
statusLabel.setForeground(Color.BLACK);
}
} else {
System.exit(0);
}
}
}
}
Can anyone Help me out.
It would be highly appreciated.
Your main() does a new LauncherUI().
Your LauncherUI constructor calls start() on a Runnable; the run() method calls new LauncherUI(). That constructor calls start(), repeating the process; classic endless loop.
On a project, I have a JFrame A starting a JDialog B, which itself starts a JDialog C (all using buttons). However, when following one of these procedures :
I click on A to start B ; or
I click on A to start B, then on B to start C, then click on C's cancel button,
what is displayed in B is not the same (the second procedure gives a weird ugly thing).
I don't get why that could be, since in both ways my updateAll method is called.
I tried to recreate this with a little program so that it's easier to see what's going on. Solving this may or may not solve it on my actual project, but it will surely help.
Since I don't know where it could come from, here's the full code of my (test) program. Brace yourselves.
The 'A' Frame
public class MyFrame extends JFrame {
private static final long serialVersionUID = 7073064926636937881L;
public MyFrame() {
this.setSize(200, 300);
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
new MyDialog1().setVisible(true);
}
});
this.getContentPane().add(button);
}
public static void main(String args[]) {
new MyFrame().setVisible(true);
}
}
The 'B' Dialog
public class MyDialog1 extends JDialog {
private static final long serialVersionUID = 9181006217120036637L;
private JScrollPane scrollPane;
public String text = "aaaaaaaaaaa\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\naaaaaaaa\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\naaaaaaaa";
public MyDialog1() {
this.setVisible(false);
this.setSize(800, 600);
this.initComponent();
this.updateAll();
}
private void initComponent() {
this.getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
this.scrollPane = new JScrollPane();
c.gridx = 0;
c.gridy = 0;
this.getContentPane().add(this.scrollPane, c);
c.gridx = 0;
c.gridy = 1;
JButton b = new JButton("Supposedly edit stuff");
final MyDialog1 caller = this;
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
new MyDialog2(caller).setVisible(true);
}
});
this.getContentPane().add(b, c);
c.gridx = 1;
c.gridy = 1;
b = new JButton("Leave");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
}
});
this.getContentPane().add(b, c);
}
public void updateAll() {
JPanel mainPanel = new JPanel();
for (int i = 0 ; i < 5 ; i++) {
JPanel subPanel = new JPanel();
JTextArea t = new JTextArea(this.text);
t.setSize(60, 30);
t.setVisible(true);// Useful ? What about setSize ?
subPanel.add(t);
mainPanel.add(subPanel);
}
this.scrollPane.setSize(150, 150); // FIXME When in initComponent, doesn't do anything, and when in updateAll, behavior is inconsistent
this.scrollPane.setViewportView(mainPanel); // Replacing previous JPanel
}
}
The 'C' Dialog
public class MyDialog2 extends JDialog {
private static final long serialVersionUID = 5676648412234106581L;
private MyDialog1 caller;
public MyDialog2(MyDialog1 c) {
this.setSize(100, 150);
this.caller = c;
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
caller.text += "\nbbbbbbbbbbbbb\nbbbbbbbbbbbbbbbbbb\nbbbbbbbbbbb\nbbbbbbbbbbbbbb\ncccccccccccccccccccccccccccccccccccccccccccc\ncccccccccc";
caller.updateAll();
}
});
this.getContentPane().add(cancelButton);
}
}
Thanks for your help.
I suggest to use
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.BOTH; // make the component fill its display area entirely
c.ipady = 150; //height
c.anchor = GridBagConstraints.FIRST_LINE_START; // component start from the left top corner
this.getContentPane().add(this.scrollPane, c);
for definition of JScrollPane constraints.
In additition, add validate() and repaint() after modifying elements
this.scrollPane.setViewportView(mainPanel); // Replacing previous JPanel
this.validate();
this.repaint();
Easy answer which ignores good practice:
Replace this:
this.scrollPane.setSize(150, 150);
with this:
this.scrollPane.setMinimumSize(new Dimension(150, 150));
Calling setSize on a component which is in a Container with a layout usually does nothing; at best, it will set the size until the next time the container is validated, since the size will be overwritten by the layout manager. However, setting a minimumSize (or preferredSize or maximumSize) sets a persistent property that is respected by (most) layout managers.
Why does setMinimumSize make a difference? Because you have not set any weightx or weighty properties on any of your GridBagConstraints, so there is not enough room for the GridBagLayout to display your JScrollPane at its preferred size. When GridBagLayout determines there isn't enough room to display everything at the size it requires, the layout "punts" and forces everything to revert to its minimum size.
The first time you display the B dialog, you are seeing the JScrollPane at its minimum size (that is, just large enough to display the scrollbars and viewport border). After canceling the C dialog, the setSize(150, 150) takes effect, but it's likely that any subsequent changes to any descendant of the GridBagLayout would cause that (150, 150) to be overwritten with the JScrollPane's minimum size again.
More complex answer which is good practice:
Remove all calls to setSize in every class. Usually you should not set explicit sizes at all, but if you must do so, use setPreferredSize.
Components which are made to grow and shrink, like JScrollPanes, should be assigned positive weightx and weighty values in their corresponding GridBagConstraints, along with fill being set to GridBagConstraints.BOTH as pcej suggested.
I think some how my actionListeners are messed up. I am supposed to have two blocks of buttons.
First panel is 16 buttons x 16 buttons(256 buttons total). Second panel is 8 buttons x 2 buttons(16 buttons total) I am able to pass "blue" from "ColorChooser" to both panels.
However, the second panel should turn RED. NOT BLUE. My second issue - Panel 2 looks correct. It starts at 1 and goes to 16. However, Panel 1 starts at 17 and goes to 256. Please and thank you for any help.
I was also wondering why my tool tips for the button arrays do not work?
Thanks Again!
example of what I mean
final JFrame MaineFrame = new JFrame("Kola Color Crapper");
MaineFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MaineFrame.setPreferredSize(new Dimension(400, 400));
final JFrame PatternGeneratorFrame = new JFrame("Pattern Generator");
PatternGeneratorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener PatternMakerActionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PatternGeneratorFrame.setVisible(true);
}
};
JButton PatternMakerBtn = new JButton("Make Pattern");
PatternMakerBtn.addActionListener(PatternMakerActionListener);
PatternMakerBtn.setToolTipText("This will allow you to create your own patterns 1 frame at a time.");
JPanel contentPane = new JPanel();
ActionListener myActionListener = new ActionListener() {
public void actionPerformed(ActionEvent aef) {
if (aef.getSource() instanceof JButton) {
((JButton) aef.getSource()).setBackground(ColorChooser.PassColor);
}
}
};
ActionListener ColorChooserActionListener = new ActionListener() {
public void actionPerformed(ActionEvent aee) {
if (aee.getSource() instanceof JButton) {
((JButton) aee.getSource()).setBackground(Color.red);
}
}
};
JButton button[] = new JButton[256];
JPanel GridPanel = new JPanel();
GridPanel.setBorder(BorderFactory.createLineBorder(Color.blue, 2));
GridPanel.setLayout(new GridLayout(16, 16, 10, 10));
for (int i = 0; i < button.length; i++) {
button[i] = new JButton(Integer.toString(i + 1));
button[i].addActionListener(myActionListener);
GridPanel.add(button[i]);
GridPanel.setToolTipText("lets make noise.");
}
contentPane.add(GridPanel);
JButton ColorPickerBtn[] = new JButton[16];
JPanel ActionPanel = new JPanel();
ActionPanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 6));
ActionPanel.setLayout(new GridLayout(2, 8, 0, 10));
for (int l = 0; l < 16; l++) {
ColorPickerBtn[l] = new JButton(Integer.toString(l+ 1));
ColorPickerBtn[l].addActionListener(ColorChooserActionListener);
ColorPickerBtn[l].setToolTipText("Choose the color you would like to use. * Colors 1-8 are static. You may change colors 9-16.");
ActionPanel.add(button[l]);
}
contentPane.add(ActionPanel);
MaineFrame.getContentPane().add(PatternMakerBtn);
PatternGeneratorFrame.setContentPane(contentPane);
PatternGeneratorFrame.pack();
PatternGeneratorFrame.setVisible(false);
MaineFrame.pack();
MaineFrame.setVisible(true);
;
}
});
}
}
}
My approach to this problem would be to just use one single ActionListener that would be listening to the entire frame.
I got a little problem with a JOptionPane which I use to warn user if wrong input is found. It works correct first time. But when I close down the JFrame which calls for that JOptionPane, and open it again it will this time call for it twice. And it will stack for every close down I do.
I have tried to look for the problem without any luck. I can provide the code, but it is quite large though.
Third EDIT: I have found and solved the problem now.
Ok, I provided the code I use. I have cut it down so it only show the necessary one. I dont think it will compile, but this is how I use the addActionListener();
public class BorderLayoutDemo extends JFrame implements ActionListener {
private JButton button1 = new JButton("L?gg till kund");
private JButton button2 = new JButton("Ta bort kund");
private JButton button3 = new JButton("Visa kund");
private JButton button4 = new JButton("Lista alla kunder");
private JButton button5 = new JButton("Avsluta");
private JButton button6 = new JButton("Change");
private JTextArea TextWindow = new JTextArea("Hej\nHej\nHej\nHej\nHej\nHej\nHej\nHej\nHej\nHej\nHej\nHej\nHej\n");
private JScrollPane scrollPane = new JScrollPane(TextWindow); //l?gger in TextWindow s? att det f?r en scroll-bar
private JPanel aPanel = new JPanel();
private JFrame aFrame = new JFrame();
private JTextField aTextfield1 = new JTextField();
private JTextField aTextfield2 = new JTextField();
private JButton aButton1 = new JButton("L?gg till kund");
private JButton aButton2 = new JButton("St?ng");
public BorderLayoutDemo() {
setTitle("Bankregister");
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
panel.setLayout(new GridLayout(6,1,55,5)); //row, cols, hgap, vgap
button1.addActionListener(this);
button2.addActionListener(this);
button3.addActionListener(this);
button4.addActionListener(this);
button5.addActionListener(this);
button6.addActionListener(this);
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);
JPanel panel2 = new JPanel();
panel2.add(panel);
add(panel2,BorderLayout.WEST);
add(scrollPane,BorderLayout.CENTER);
setJMenuBar(menu());
setSize(600,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public void addCustomer(boolean status) {
if(status) {
aFrame.setTitle("L?gg till kund");
aFrame.setSize(200,300);
aFrame.setLayout(new GridLayout(3,1));
aPanel.setLayout(new GridLayout(2,1)); //rad, kolumn
aPanel.add(aTextfield1);
aPanel.add(aTextfield2);
aButton1.addActionListener(this);
aButton2.addActionListener(this);
System.out.println("Foo!!!!!!!!!!!!!");
aFrame.add(aPanel);
aFrame.add(aButton1);
aFrame.add(aButton2);
aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aFrame.setLocationRelativeTo(null);
aFrame.setVisible(true);
}
else {
aFrame.setVisible(false);
}
}
public static void main(String[] args) {
new BorderLayoutDemo();
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1) {
setEnabled(false);
addCustomer(true);
}
//IFs f?r addCustomer();
else if(e.getSource() == aButton1) {
if((aTextfield1.getText().isEmpty() || aTextfield2.getText().isEmpty())) {
JOptionPane.showMessageDialog(null, "You miss to fill out the fields");
}
else {
JOptionPane.showMessageDialog(null, "Added");
Kund kund = new Kund(aTextfield1.getText(),aTextfield2.getText());
setEnabled(true);
register.add(kund);
}
}
else if(e.getSource() == aButton2) {
setEnabled(true);
addCustomer(false);
}
Sounds like you are adding the "validation listener" every time you open the JFrame. So check your "addListenerXXX" code to make sure it is only added/created once.
Which also leads to the question why are you using a JFrame for this? Typically an application has a single JFrame. Then, if you need a window to enter data you create a JDialog.
By passing null as the first parameter of that method you are creating a default JFrame that the JOptionPane uses as its parent component and not the JFrame you have created in your code. If you provide more detail in your question I'm sure someone here will provide you with a much more detailed answer.