EDIT: I have fixed the problem. Thank you all for your help.
I am pretty new to programming, and have been struggling through an online course. I am now working on my final project, which is to: Write a program to count the number of mouse clicks on a button within a frame. The code I have seems to be WAY off. Keep in mind that this is an applet. Here is the program:
import java.awt.*;
import java.awt.event.*;
import java.awt.MouseAdapter;
public class finalproject1
{
TextField objTextField1;
public static void main(String[] args)
{
finalproject1 p1 = new finalproject1();
}
public finalproject1
{
Frame f = new Frame("Mouse Clicks");
objTextField1 = new TextField("Click the button",200);
objTextField1.setBounds(220,140,200,40);
Button button1 = new Button("Click here");
button1.setBounds(200,200,140,140);
button1.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent evt)
{
if(evt.getClickCount() == 3)
{
objTextField1TextField1.setText("Triple click");
}
else if(evt.getClickCount() ==2)
{
objTextField1.setText("Double click");
}
});
}
f.add(button1);
f.add(objTextField1);
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we)
{
System.exit(0);
}
});
f.setSize(800,800);
f.setVisible(true);
}
}
First of all, I'd recommend you fix your tabbing to make sure you're looking at scoping correctly. In addition, there are some other quirks here that could be messing things up -- this really ought not to even compile.
It looks like you're trying to define a constructor, but you haven't added parentheses. This:
public finalproject1 { ... }
should become this:
public finalproject1() { ... }
It's also convention to name classes in camelcase, so FinalProject1 would be a better name.
Your paren placement is also off in this code:
button1.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
if(evt.getClickCount() == 3) {
objTextField1TextField1.setText("Triple click");
} else if(evt.getClickCount() ==2) {
objTextField1.setText("Double click");
}
}); // This ");" should be one brace down from where it is.
}
I can't help much more without knowing what you mean by "WAY off." Can you elaborate?
parentheses are missing to the constructor : public finalproject1() { ... }
");" at the end of method mouseClicked must be at the end of method addMouseListener.
object objTextField1TextField1 is not declared. It should be objTextField1 instead.
class name must start with upper case (Java convention)
Related
I am trying to make it easier to make buttons by making a method, but when i use the method to make a button nothing happens when i press the button, even though i have a listener for the button
public void assignButton(Button wtf,String text) //program to assign buttons easily
{
wtf = new Button(text);
add(wtf);
wtf.addActionListener(this);
}
i use assignButton(Check,"words"); to make the button
public void actionPerformed(ActionEvent event) //checks if button has been pressed
{
if(event.getSource() == Check)
{
code ++;
}
else
{
code = 2;
}
repaint();
every time i press the button it sets code to 2, anyone know what i am doing wrong?
Edit:
full code
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class PressSafeTemp extends Applet implements ActionListener
{
Button clear,Check;
int code = 0;
public void init() //assigns buttons
{
clear = new Button("C");
add(clear);
clear.addActionListener(this);
assignButton(Check,"words");
}
public void paint(Graphics g)
{
g.drawString(""+code,10,10);
}
public void assignButton(Button wtf,String text) //program to assign buttons easily
{
wtf = new Button(text);
add(wtf);
wtf.addActionListener(this);
}
public void actionPerformed(ActionEvent event) //checks if button has been pressed
{
if(event.getSource() == Check)
{
code ++;
}
else if(event.getSource() == clear)
{
code = 0;
}
else
{
code = 2;
}
repaint();
}
}
The problem is you pass Check to the method (as wtf) but then immediately set it to a new instance; this instance is not Check. It does get added but you can't get at it with Check.
You probably want to do...
Button getButton(String text) {
Button button = new Button(text);
button.addActionListener(this);
return button;
}
and then Check = getButton(someText); followed by add(Check);.
If you don't actually need Check laying around, you could also just add it directly with add(getButton(someText));.
I'm not sure what means for you event.getSource() == Check but that is the key, you need to check the correct comparison in your case. Something like for example:
event.getSource().class.equals(JCheckBox.class)
need some help with ComboBoxes in Java. Looked through similar questions, found one slightly related, but not what im dealing with.
I need to load certain arrays into combo boxes depending on the items selected in the precious combo box:
think getting some procedure done at a medical center: Choose a procedure->get a list of doctors who do it, choose a doctor->get a list of available hours etc.
A single choice is working fine(whether it's "procedure->list of doctors", or "list of doctors->their working hours"), but doing more than a single one of those changes doesn't work.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
public class GUIbandymas extends JFrame {
String[] start={"Choose","Choice1", "Choice2"};
String[] Option1={"Choose","A1"};
String[] Option2={"Choose","A2","A3"};
String[] Option3={"Choose","a","b","c","d"};
String[] Option4={"Choose","1","2","3","4"};
String[] Option5={"Choose","I","II","III","IV"};
String[] pradinis={"Pasirinkite Laika"};
String[] p1={"Pasirinkite Gydytoja"};
static double kainaR;
static double kainaK;
JComboBox<String> G=new JComboBox<String>(p1);
JComboBox<String> proc;
JComboBox<String> laikas=new JComboBox<String>(pradinis);
JComboBox<String> minutes;
JButton button = new JButton ("Registuotis");
JLabel label = new JLabel("Moketi uz vizita");
JLabel suma = new JLabel();
public GUIbandymas() throws Exception {
setValueProc(start);
frame();
}
public void frame()
{
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(500,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.add(proc);
panel.add(G);
panel.add(laikas);
panel.add(button);
button.setEnabled(false);
//panel.add(minutes);
frame.add(panel);
panel.add(label);
panel.add(suma);
proc.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
if(proc.getSelectedItem().toString().equals("Choice1"))
{
setGyd(Option1);
}
if(proc.getSelectedItem().toString().equals("Choice2"))
{
setGyd(Option2);
}
}
});
G.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent a) {
if(G.getSelectedItem().toString().equals("A1"))
{
setLaikas(Option3);
}
if(G.getSelectedItem().toString().equals("A2"))
{
setLaikas(Option4);
}
if(G.getSelectedItem().toString().equals("A3"))
{
setLaikas(Option5);
}
}
});//JComboBox
}
public void setGyd(String[] s)
{
G.removeAllItems();
for(int i=0; i<s.length; i++)
{
G.addItem(s[i]);
}
}
public void setValueProc(String[] sarasas)
{
proc=new JComboBox<String>(sarasas);
}
public void setLaikas(String[] sarasas)
{
laikas.removeAllItems();
for(int i=0; i<sarasas.length; i++)
{
laikas.addItem(sarasas[i]);
}
}
}
Im in a dire need of any suggestions and possible fixes, im inclined to think that it has something to do with action listeners, since methods do work, but im at a loss since i cant determine what is it.
EDITED: the actual code should work, seems like there is no unneeded things from other files left.
NOTE: this is work with GUI, just launch it in you main() :)
While I don't really like the if-else approach you're using, it should work just fine. I agree with rrirower's suggestion that you should look at using a data model instead. Especially if you get a lot of choices, since the code turns messy quite fast.
The problem with your code is that you run into NullPointerException when rebuilding the combobox items. The reason for this is that G.actionPerformed() is called when you remove/add items. After you have removed all items (before you start adding new ones), G.getSelectedItem() will return null.
If you code a little bit more defensively, then it works as expected:
proc.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object selectedItem = proc.getSelectedItem();
if ("Choice1".equals(selectedItem)) {
setGyd(Option1);
}
if ("Choice2".equals(selectedItem)) {
setGyd(Option2);
}
}
});
G.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent a) {
Object selectedItem = G.getSelectedItem();
if ("A1".equals(selectedItem)) {
setLaikas(Option3);
}
if ("A2".equals(selectedItem)) {
setLaikas(Option4);
}
if ("A3".equals(selectedItem)) {
setLaikas(Option5);
}
}
});//JComboBox
Instead of checking for null's, I just flipped the equals and skipped the unnecessary toString() (they are already strings, that's what you put in there).
Another thing, a pet peeve of mine, please follow the normal java code convention for all your class, field and method names. You're almost there, but Option1 etc. should start with lowercase. G should probably have a more descriptive name, as well as start with lowercase.
Finally, I didn't understand why you both create a JFrame in the constructor and extend JFrame in your class. You should choose one or the other.
You don't appear to be using a data model for the combo box. The data model controls the internal list of items. Have a look at this for more info.
I have some text field on my form. And I like focusGained and focusLost event. Doing this with 2 or 3 text field is easy. But, after 18 text field, well, it's kinda confusing.
Is there any way to shorten the focusGained and focusLost event?
Example:
txtSomeTextFocusGained(java.awt.event FocusEvent evt){
if(txtSomeText.getText().equals("Text here!"){
txtSomeText.setText("");
}
}
txtSomeTextFocusLost(java.awt.event FocusEvent evt){
if(txtSomeText.getText().equals(""){
txtSomeText.setText("Text here!");
}
}
That's one text field, I've problem handling with about 18 text field. Any way to simplify that?
Thanks.
The methods are simple enough, so I can't think of a way to simplify them any further. What you can do, though, is prevent code repetition by declaring one FocusListener instance and then add it using addFocusListener(...) to all text-fields.
It would look something like this:
// Instantiate a FocusListener ONCE
java.awt.event.FocusListener myFocusListener = new java.awt.event.FocusListener() {
public void focusGained(java.awt.event.FocusEvent focusEvent) {
try {
JTextField src = (JTextField)focusEvent.getSource();
if (src.getText().equals("Text here!") {
src.setText("");
}
} catch (ClassCastException ignored) {
/* I only listen to JTextFields */
}
}
public void focusLost(java.awt.event.FocusEvent focusEvent) {
try {
JTextField src = (JTextField)focusEvent.getSource();
if (src.getText().equals("") {
src.setText("Text here!");
}
} catch (ClassCastException ignored) {
/* I only listen to JTextFields */
}
}
};
(You could omit the try-catch blocks if you were absolutely sure that the source of the event would always be a JTextField, but it is always a bad practice to rely on such assumptions.)
Then, for every JTextField you only need to add the same FocusListener:
...
someTextField.addFocusListener(myFocusListener);
...
(It's only half a line - difficult to get any shorter than that.)
Another alternative would be to subclass JTextField, adding a FocusListener in the constructor, but I don't see any advantage over the first solution (unless you want a more flexible/powerful solution, e.g. different text for each JTextField etc).
If you want just to set some text in field which gets focused you could write separated event handler class which implements FocusListener and then override focusGained and focusLost methods. Something like this:
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JTextField;
public class CustomFocusListener implements FocusListener {
JTextField txt;
String textWhenFocusGained;
String textWhenFocusLost;
public CustomFocusListener(JTextField txt, String textWhenFocusGained,
String textWhenFocusLost) {
this.txt = txt;
this.textWhenFocusGained = textWhenFocusGained;
this.textWhenFocusLost = textWhenFocusLost;
}
#Override
public void focusGained(FocusEvent arg0) {
txt.setText(textWhenFocusGained);
}
#Override
public void focusLost(FocusEvent arg0) {
txt.setText(textWhenFocusLost);
}
}
Use this.
if(txtSomeText.getText().equals("Text here!")){
txtSomeText.setText("");
/////////////// It's problem of lower and supper case you should make ur text in lower case in code. and for desing of jtextfield it's ok
txtIdDeVoyageur = new JTextField();
txtIdDeVoyageur.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
if(txtIdDeVoyageur.getText().trim().toLowerCase().equals("id de voyageur")){
txtIdDeVoyageur.setText("");
txtIdDeVoyageur.setForeground(Color.black);
}
}
#Override
public void focusLost(FocusEvent e) {
if (txtIdDeVoyageur.getText().trim().equals("") ||
txtIdDeVoyageur.getText().trim().toLowerCase().equals("id de voyageur"))
{
txtIdDeVoyageur.setText("id de voyageur");
txtIdDeVoyageur.setForeground(new Color (153,153,153));
}
}
});
I was reading different threads on the subject which suggested the Swing Timer class or SwingUtilities.InvokeLater
...but I am having a lot of trouble wrapping my head around them.
I used atomicInteger to create my countdown timer and it works fine in the console. However, When I try to incorporate it in Swing, it only updates the starting and ending value (e.g. set a 5 sec countdown will display in the frame: "5" -> after 5 seconds -> "0".
Is there any simple way for me to keep and "refresh" my atomicInteger countdown label, or the only way is using the Swing Timer class?
Thank you for your patience!
ps. not homework, just trying to make myself a custom timer to study. (ie. procrastinating)
I hope this class is enough, please let me know if you need the frame/panel code as well.
private class ClickListener implements ActionListener{
public void actionPerformed(ActionEvent e){
int t_study = 5;
atomicDown.set(t_study);
if (e.getSource() == b_study){
while(atomicDown.get() > 0){
t_study = atomicDown.decrementAndGet();
l_studyTime.setText(Integer.toString(t_study));
try {
Thread.sleep(1000);
}
catch (InterruptedException e1) {
System.out.println("ERROR: Thread.sleep()");
e1.printStackTrace();
}
}
}
else if(e.getSource() == b_exit){
System.exit(0);
}
else
System.out.println("ERROR: button troll");
}
}
After turning the code snippet into an SSCCE, this is what I get (which seems to work - as best as I understand the original code).
I have not changed the variable names. Please learn common Java naming conventions1 for class, method & attribute names & use it consistently.
Specifically names like b_study should be more along the lines of studyButton or similar. Some will note that 'button' should not be part of the name, but when you have a GUI with both a 'Study' button & label, I don't see any other logical way to separate them.
import java.awt.event.*;
import javax.swing.*;
import java.util.concurrent.atomic.AtomicInteger;
class TimerTicker {
public static final int STUDY_TIME = 15;
AtomicInteger atomicDown = new AtomicInteger(STUDY_TIME);
JButton b_study;
JButton b_exit;
JLabel l_studyTime;
TimerTicker() {
JPanel gui = new JPanel();
b_study = new JButton("Study");
ClickListener listener = new ClickListener();
b_study.addActionListener(listener);
gui.add(b_study);
b_exit = new JButton("Exit");
b_exit.addActionListener(listener);
gui.add(b_exit);
l_studyTime = new JLabel("" + atomicDown.get());
gui.add(l_studyTime);
JOptionPane.showMessageDialog(null, gui);
}
private class ClickListener implements ActionListener {
Timer timer;
public void actionPerformed(ActionEvent e){
if (e.getSource() == b_study) {
ActionListener countDown = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (!(atomicDown.get() > 0)) {
timer.stop();
// reset the count.
atomicDown.set(STUDY_TIME);
} else {
l_studyTime.setText(
Integer.toString(
atomicDown.decrementAndGet()));
}
}
};
timer = new Timer(1000,countDown);
timer.start();
} else if(e.getSource() == b_exit) {
System.exit(0);
} else {
System.out.println("ERROR: button troll");
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TimerTicker();
}
});
}
}
is it possible in java to have a class where it has EventHandlers for with different functions? for example button1 will log you in, while button2 will log you out, is this possible? Here's the code I made it seems to be not working.
package event.handlers;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TheHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent logInEvent) {
System.out.println("Button Login");
}
public void actionPerformed(ActionEvent cancelEvent) {
System.out.println("Cancel Login");
}
}
You either need two implementations of ActionListener, one for each button or the actionPerformed needs to determine the button by the event argument and take the appropriate action. Your code will not compile because the signatures for both methods are the same.
No. You can not have a class implement two methods with the same function signature. How would the compiler know which one to call for different events? The name you give to the arguments has no meaning to the compiler.
As an alternative, you can create multiple anonymous action listeners that simply forward the call to a method that does have a unique name if you want everything to be in the same class.
public class TheHandler {
public TheHandler() {
JButton login, cancel;
//initialize code here
login.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent logInEvent) {
loginPerformed(logInEvent);
}
});
cancel.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent cancelEvent) {
cancelPerformed(cancelEvent);
}
});
}
public void loginPerformed(ActionEvent logInEvent) {
System.out.println("Button Login");
}
public void cancelPerformed(ActionEvent cancelEvent) {
System.out.println("Cancel Login");
}
}
You may use getSource() or getActionCommand() method of ActionEvent.
#Override
public void actionPerformed(ActionEvent logInEvent) {
Object src=logInEvent.getSource();
String cmd=logInEvent.getActionCommand(); //It will return caption of button
if(src==btn1)
{
//
}
//Or
if(cmd.equals("Button1")) { ... }
}
You can not have multiple actionPerformed method in one class. Simple way is to do operation based on source of action like:
(in actionPerformed method)
if(e.getSource() == loginButtton) { // based on button variable if they are in same class and accessible in actionPerformed method
loginMethod()
} else if(e.getSource == logoutButton) {
logoutMethod()
}
or
if(e.getActionCommand().equals("loginButtton")) { // based on caption/text on button
loginMethod()
} else if(e.getActionCommand().equals("logoutButtton")) {
logoutMethod()
}
or you can have different anonymous class for different buttons like
loginButton.addActionListner(new ActionListerner(){
public void actionPerformed(ActionEvent loginEvent) {
loginMethod();
}
});
logoutButton.addActionListner(new ActionListerner(){
public void actionPerformed(ActionEvent cancelEvent) {
logoutMethod();
}
});
The problem there is that your two method signatures are identical. When Java tries to figure out which method to call, it can't tell the difference between the two.
I can think of two ways to do what you want:
Presumably, you are registering the listeners on the buttons like cancelButton.addActionListener(...). So you can either provide each button with its own anonymous inner class:
loginButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent logInEvent) {
System.out.println("Button Login");
}
}
cancelButton.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent cancelEvent) {
System.out.println("Cancel Login");
}
}
or you can define a single actionPerformed method that checks the source of the call:
public class TheHandler implements ActionListener {
JButton loginButton;
JButton cancelButton;
public TheHandler()
{
...
// Now, technically, this is bad form because you're leaking 'this'.
// But as long as this will only be called after this constructor finishes
// initializing, it's safe.
loginButton.addActionListener(this);
cancelButton.addActionListener(this);
...
}
...
#Override
public void actionPerformed(ActionEvent evt) {
if(evt.getSource() == loginButton)
System.out.println("Button Login");
else if(evt.getSource() == cancelButton)
System.out.println("Cancel Login");
}
}
Using anonymous inner classes can sometimes be clearer, because you see the code right next to the addListener call, but it also adds a lot of boilerplate, and if you're working on a very large progect that can take a while to load, reducing the number of classes can sometimes make it load a little faster (each anonymous inner class is another thing for the JVM to load).