I was checking out the example projects that people do when starting to learn Java and GUI, I was faced with a bunch of word/letter count programs such as:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class Counter extends JFrame implements ActionListener{
JLabel lb1,lb2;
JTextArea ta;
JButton b;
JButton pad,text;
Counter(){
super("Char Word Count Tool - JTP");
lb1=new JLabel("Characters: ");
lb1.setBounds(50,50,100,20);
lb2=new JLabel("Words: ");
lb2.setBounds(50,80,100,20);
ta=new JTextArea();
ta.setBounds(50,110,300,200);
b=new JButton("Count");
b.setBounds(50,320, 80,30);//x,y,w,h
b.addActionListener(this);
add(lb1);add(lb2);add(ta);add(b);
setSize(400,400);
setLayout(null);//using no layout manager
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e){
if(e.getSource()==b){
String text=ta.getText();
lb1.setText("Characters: "+text.length());
String words[]=text.split("\\s");
lb2.setText("Words: "+words.length);}
}
public static void main(String[] args) {
new Counter();
}}
But I don't want to count words whenever I click the button but in real-time so the values update each frame. Do I need to use multi-threading for this or it can be achieved without it?
You need to use a DocumentListener on the JTextArea instead of an ActionListener on a JButton.
void test() {
JTextArea textArea = new JTextArea();
textArea.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
recalculateWords();;
}
#Override
public void removeUpdate(DocumentEvent e) {
recalculateWords();
}
#Override
public void changedUpdate(DocumentEvent e) {
recalculateWords();
}
});
}
void recalculateWords() {
//Use your code from actionPerfomed here.
}
Related
What am I doing wrong with this Java JPanel/JFrame/JButton? This is my program and right now I've been trying to be able to repaint it, but it won't work. Please help! I am a beginner with JPanel and JFrame. I'm only adding this sentence to allow it to post.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Clicks implements MouseListener
{
private static int clicks, clickersInt, clickersCost;
private static JButton clickersB, click;
private static JLabel clickersL, clicksL;
private static JPanel panel;
public static void main(String[] args)
{
JFrame clicksFrame=new JFrame ("Clicks");
clicksFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
clicks=0;
panel=new JPanel(new GridBagLayout());
click=new JButton("Click Me!");
clickersB=new JButton("Cost: 10");
clickersL=new JLabel("Clickers: "+Integer.toString(clickersInt));
clicksL=new JLabel("Clicks: "+Integer.toString(clicks));
click.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
clicks++;
clicksFrame.remove(panel);
clicksFrame.add(panel);
panel.validate();
panel.repaint();
}
});
clickersB.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if(clicks>=clickersCost)
{
clickersInt++;
clicks-=clickersCost;
clickersCost*=2;
}
}
});
panel.add(click);
panel.add(clicksL);
panel.add(clickersL);
panel.add(clickersB);
clicksFrame.add(panel);
clicksFrame.setBackground(Color.CYAN);
clicksFrame.setVisible(true);
}
}
So, based on this little snippet...
click=new JButton("Click Me!");
clickersB=new JButton("Cost: 10");
clickersL=new JLabel("Clickers: "+Integer.toString(clickersInt));
clicksL=new JLabel("Clicks: "+Integer.toString(clicks));
click.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
clicks++;
clicksFrame.remove(panel);
clicksFrame.add(panel);
panel.validate();
panel.repaint();
}
});
I would suggest that what you really want to do is...
click.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
clicks++;
clicksL.setText("Clicks: "+Integer.toString(clicks));
}
});
You seem to be of the illusion that changing a variable will some how change another variable which is just a string of characters. As you've discovered, that's not how this works
Well what i'm trying to do is change the text of the JRadioButton's when they're selected, i got them to change the color. I know I can do it by putting the code to change the text inside the dedicated event handling method specific to each button, but how do I do it so that I use A DIFFERENT event handling method that just changes the buttons? I already created one but it doesn't work, here's the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class LessonTwenty extends JFrame implements ActionListener{
JRadioButton b1,b2;
JTextArea t1;
JScrollPane s1;
JPanel jp = new JPanel();
public LessonTwenty()
{
b1= new JRadioButton("green");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jp.setBackground(Color.GREEN);
}
});
b2= new JRadioButton("red");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jp.setBackground(Color.RED);
}
});
//Method to change the text of the JRadion Buttons, what i'm trying to make work
new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(b1.isSelected()){
b1.setText("Welcome");
}
else if(b2.isSelected()){
b2.setText("Hello");
}
}
};
jp.add(b1);
jp.add(b2);
this.add(jp);
setTitle("Card");
setSize(700,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String [ ] args){
new LessonTwenty();
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
if i understand you right, you want do do something like this:
//Method to change the text of the JRadion Buttons, what i'm trying to make work
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(b1.isSelected()){
b1.setText("Welcome");
}
else if(b2.isSelected()){
b2.setText("Hello");
}
}
};
b1= new JRadioButton("green");
b1.addActionListener(al);
b2= new JRadioButton("red");
b2.addActionListener(al);
ie. you define one ActionListener which you use in all your objects.
The anonymous object you define in your original code does absolutely nothing, it just creates an ActionListener which nobody can ever access, since it is not assigned to any Button.
Maybe this could help
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b1){
b1.setText("Welcome");
} else if(e.getSource() == b2){
b2.setText("Hello");
}
}
};
I am currently having trouble with being able to change the choiceDeclaration JLabel. My mindset behind the choiceDeclaration JLabel is to simply display text based on which JButton is clicked.
Here is my current code for the project:
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.awt.event.*;
public class prompt {
public static void main(String []args) {
/* Setting up the JPanel and its necessities for this program */
JFrame choicePrompt = new JFrame("Rock, Paper, Scissors Game");
JPanel choicePanel = new JPanel();
JButton rockButton = new JButton("ROCK");
JButton scissorsButton = new JButton("SCISSORS");
JButton paperButton = new JButton("PAPER");
JLabel choiceDeclaration = new JLabel();
choicePrompt.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
choicePrompt.setResizable(false);
choicePrompt.setSize(300, 300);
choicePrompt.setVisible(true);
choiceDeclaration.setVisible(true);
choicePrompt.add(choicePanel);
choicePanel.add(choiceDeclaration);
choicePanel.add(rockButton);
choicePanel.add(scissorsButton);
choicePanel.add(paperButton);
choiceDeclaration.setVerticalTextPosition(JLabel.TOP);
choiceDeclaration.setHorizontalTextPosition(JLabel.CENTER);
/* ActionListeners for the JButtons */
rockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*I have not placed any code in here because I have not gotten that far*/
}
});
scissorsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*I have not placed any code in here because I have not gotten that far*/
}
});
paperButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/*I have not placed any code in here because I have not gotten that far*/
}
});
}
}
I cannot use a setText method in my ActionListeners as shown below because it conflicts with my main class method a line below the declaration of my class. They are both using String in their parameters.
public static void main(String []args) {
rockButton.addActionListener(new ActionListener() {
setText(String text) {
}
}
}
My concluding thought was to make another class that could use the setText method to change the JLabel on that frame. However, since JLabels cannot be called from one class to another like variables or methods, I am having trouble trying to implement this idea.
Have a separate method for it...
public static void settext() {
setText(String text)
}
then call it in your action listener...
rockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
settext();
}
});
I hope this is what you meant! :)
I have JButton and want on event call this class method show() when this button in pressed. I know how to this, if I want use method from another class, but I need call method from same class as button.
JButton search = new JButton(new ButtonAction("Search", KeyEvent.VK_A));
I try add
JButton search = new JButton(show());
But it works only 1 time when object creating, but not when button is pressed.
Not sure what you want here... but if you want to attach an actionListener() to a JButton, you can do the following. Why do you need to listen to A?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerExample1 extends JFrame
implements ActionListener, KeyListener {
private static final long serialVersionUID = 1L;
private JTextField searchText;
private JButton searchButton1;
private JButton searchButton2;
public ActionListenerExample1() {
initialize();
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
protected void initialize() {
searchText = new JTextField(30);
searchButton1 = new JButton("Search 1");
searchButton2 = new JButton("Search 2");
searchText.addKeyListener(this);
searchButton1.addActionListener(this);
searchButton2.addActionListener(new ButtonAction());
this.setLayout(new FlowLayout());
this.add(searchText);
this.add(searchButton1);
this.add(searchButton2);
}
public static void main(String[] args) {
new ActionListenerExample1();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == searchButton1) {
buttonAction("GLOBAL LISTENER");
}
}
private class ButtonAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
buttonAction("LOCAL LISTENER");
}
}
private void buttonAction(String label) {
JOptionPane.showMessageDialog(this,
String.format("%s: %s", label, searchText.getText()));
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_A) {
buttonAction("KEYBOARD");
}
}
#Override
public void keyReleased(KeyEvent e) { }
#Override
public void keyTyped(KeyEvent e) { }
}
If I understand you correctly, you want to call a method from the class that you created the button in rather than a method from another class.
First off, notice that while you are technically calling a method here
JButton search = new JButton(new ButtonAction("Search", KeyEvent.VK_A));
what is really going on is that you are passing a ButtonAction object to the JButton constructor. The closest thing that I can think of that will get what you want is having the class you are using extend ButtonAction.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.lang.Thread;
public class Lthread extends JPanel{
private JTextField acctTF;
private JTextField pinTF;
private JButton cancelB;
private JLabel balanceL;
private JButton searchB;
public Lthread() {
buildGUI();
hookupEvents();
}
private void buildGUI() {
JLabel acctL=new JLabel("Account Number:");
JLabel pinL=new JLabel("PIN:");
acctTF=new JTextField(12);
pinTF=new JTextField(4);
JPanel dataEntryP=new JPanel();
dataEntryP.setLayout(new FlowLayout(FlowLayout.CENTER));
dataEntryP.add(acctL);
dataEntryP.add(acctTF);
dataEntryP.add(pinL);
dataEntryP.add(pinTF);
searchB=new JButton("Search");
cancelB=new JButton("Cancel Search");
cancelB.setEnabled(false);
JPanel innerButtonP=new JPanel();
innerButtonP.setLayout(new GridLayout(1,-1,5,5));
innerButtonP.add(searchB);
innerButtonP.add(cancelB);
JPanel buttonP=new JPanel();
buttonP.setLayout(new FlowLayout(FlowLayout.CENTER));
buttonP.add(innerButtonP);
JLabel balancePrefixL=new JLabel("Account Balance: ");
balanceL=new JLabel("BALANCE UNKNOWN");
JPanel balanceP=new JPanel();
balanceP.setLayout(new FlowLayout(FlowLayout.CENTER));
balanceP.add(balanceL);
JPanel northP=new JPanel();
northP.setLayout(new GridLayout(-1,1,5,5));
northP.add(dataEntryP);
northP.add(buttonP);
northP.add(balanceP);
setLayout(new BorderLayout());
add(northP,BorderLayout.NORTH);
}
private void hookupEvents() {
searchB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
search(ae);
}
});
cancelB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
cancelSearch(ae);
}
});
}
private void search(ActionEvent ae) {
searchB.setEnabled(false);
cancelB.setEnabled(true);
balanceL.setText("SEARCHING...");
String acct=acctTF.getText();
String pin=pinTF.getText();
String bal=lookupBalance(acct,pin);
setBalance(bal);
}
private String lookupBalance(String acct,String pin) {
try {
Thread.sleep(5000);
return "1,234.56";
} catch(Exception exc) {
return "search cancelled";
}
}
private void setBalance(String newBalance) {
balanceL.setText(newBalance);
cancelB.setEnabled(false);
searchB.setEnabled(true);
}
private void cancelSearch(ActionEvent ae) {
System.out.println("in cancelSearch");
}
public static void main(String args[]) {
Lthread Lt=new Lthread();
JFrame f=new JFrame("Balance Lookup-Can't cancel");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.setContentPane(Lt);
f.setSize(400,150);
f.setVisible(true);
}
}
As soon as we click search,cancel should get enabled,but it does not get enabled, why?
Another thing is label balanceL should display SEARCHING. When search is clicked but that is also not displayed. Why?
You're doing all the work (well, sleeping) in the UI thread. That's stopping all the rest of the UI from updating, processing events etc.
You should offload your work (the searching/sleeping) to a background thread, using SwingWorker to marshall any UI calls back to the UI thread. (You can't touch UI components from a non-UI thread.)
A search for "swing threads" gives loads of hits for tutorials etc, if you want more information. In particular, you probably want to read the Java Tutorial trail on threading in Swing.
because the eventdispatcher thread is blocked in the search() function. it should never be blocked. use SwingUtilities.invokeLater().
for your problem change search method to
private void search(ActionEvent ae) {
searchB.setEnabled(false);
cancelB.setEnabled(true);
balanceL.setText("SEARCHING...");
final String acct=acctTF.getText();
final String pin=pinTF.getText();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
String bal=lookupBalance(acct,pin);
setBalance(bal);
}
});
}