I wrote a program for an applet that is supposed to display different text in a text box when you push a button. My program has no errors when I compiled it, but the text box doesn't display correctly. I don't know what is wrong with it. Here is my code
import java.awt.*;
import java.awt.event.*;
public class colors{
Button button1;
Button button2;
Button button3;
Label label1;
TextField objTextField1;
public static void main (String args[]){
colors c = new colors();
}
public colors() {
Frame f = new Frame ("Colors");
Button button1 = new Button("Blue");
button1.setBounds(10,305,120,75);
button1.addMouseListener(new MyMouseListener1());
Button button2 = new Button("Red");
button2.setBounds(140,305,120,75);
button2.addMouseListener(new MyMouseListener2());
Button button3 = new Button("Yellow");
button3.setBounds(270,305,120,75);
button3.addMouseListener(new MyMouseListener3());
f.add(button1);
f.add(button2);
f.add(button3);
label1 = new Label("Click a Button to Reveal Text");
label1.setBounds(20,105,200,25);
f.add(label1);
objTextField1 = new TextField("Which Color?", 15);
objTextField1.setBounds(20,75,125,50);
f.add(objTextField1);
f.add(label1);
f.add(objTextField1);
f.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent we){
System.exit(0);
}
});
f.setSize(400,400);
f.setVisible(true);
}
public class MyMouseListener1 extends MouseAdapter{
public void mouseClicked(MouseEvent me){
objTextField1.setText("Blue");
}
}
public class MyMouseListener2 extends MouseAdapter{
public void mouseClicked(MouseEvent me){
objTextField1.setText("Red");
}
}
public class MyMouseListener3 extends MouseAdapter{
public void mouseClicked(MouseEvent me){
objTextField1.setText("Yellow");
}
}
}
When a Button is clicked it fires an ActionEvent.
You should use an ActionListener instead of a MouseListener.
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
AND don't forget to add
button.addActionListener(instance);
I have tested your code and it's working as expected but I have noticed some of the points in your code as mentioned below:
Use setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) instead of System.exit(0) and adding WindowListener to close the window.
Use frame.pack() instead of frame.setSize() that fits the components as per component's preferred size.
Don't use null layout and never use absolute positioning via calling setBounds() instead use a proper Layout Manager that suits as per your application design.
Read more How to Use Various Layout Managers
Use SwingUtilities.invokeLater() or EventQueue.invokeLater() to make sure that EDT is initialized properly.
Read more
Why to use SwingUtilities.invokeLater in main method?
SwingUtilities.invokeLater
Should we use EventQueue.invokeLater for any GUI update in a Java desktop application?
Follow Java Naming convention
Keep the instance members private
This is already addressed by #TAsk that you should be using ActionListener instead of MouseListener if you are interested in only mouseClicked() method.
You should be using Swing components instead of AWT components as already mentioned by #peeskillet
To make an applet you should extend javax.swing.JApplet class & override init() method.
To change the color, you must write your logics in actionPerformed() of ActionListener. But it's an interface. So, you can make use of Anonymous Inner class & implement actionPerformed() in it.
So, when you call addActionListener() on a JButton, I recommend you to do that by using Anonymous Inner class. It would be more clear through following code.
My Suggestion: Whenever you write code, always keep OOD principles in your mind. This isn't right place to discuss that, but your code has a Code smell which is Duplication in code.
Below is the best way to do what you want & we're also using DRY Principle.
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class ColorChanger extends javax.swing.JApplet {
private JPanel mainPanel;
private JButton btnRed;
private JButton btnGreen;
private JButton btnBlue;
#Override
public void init() {
super.init();
mainPanel = new JPanel();
btnRed = new JButton("Red");
btnGreen = new JButton("Green");
btnBlue = new JButton("Blue");
this.add(mainPanel);
mainPanel.add(btnRed);
mainPanel.add(btnGreen);
mainPanel.add(btnBlue);
bindActionEvent(btnRed, Color.RED);
bindActionEvent(btnGreen, Color.GREEN);
bindActionEvent(btnBlue, Color.BLUE);
}
private void bindActionEvent(JButton b1, Color color) {
b1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mainPanel.setBackground(color);
//Write setText() for your TextField here.
}
});
} //END Of Helper Method
}
Related
I am fairly new to coding and have encountered this issue within my code.
I create a button using the Java AWT import. I then check for a response using a while loop and wish to create another button after, however .add() seems to no longer function.
import java.awt.*;
import java.awt.event.*;
public class Main1
{
public static void main(String[] args)
{
Frame f = new Frame();
f.setSize(500, 500);
f.setVisible(true);
ButtonPanel bp = new ButtonPanel(f);
bp.x = null;
while (bp.x == null)
{
}
System.out.println(bp.x);
//THE ISSUE- THIS WILL NOT APPEAR AFTER BUTTON PRESS
f.add("South", new Button("REEE"));
}
}
class ButtonPanel extends Panel implements ActionListener
{
volatile String x;
public ButtonPanel(Frame f)
{
Button b = new Button("Hi");
b.addActionListener(this);
f.add("North", b);
}
public void actionPerformed(ActionEvent e)
{
x = e.getActionCommand();
}
}
I have been trying solutions for this for the last day or so and nothing seems to be working. I've seen in other posts people have said to use Wait/Notify however I am not too sure how those work and I would like to know explicitly what is going wrong in my program (though I am still open to using Wait/Notify in my solution).
Any help would be appreciated, thank you very much
So, they're a number of issues at play here.
The first is the fact that layout managers are generally lazy. This means that you can add and/or remove a number of components quickly and then do a single layout and paint pass.
To do this, you need to revalidate the Container which was updated.
Next, AWT (and Swing by extension) is based on Model-View-Controller concept, one aspect of this is the "observer pattern". This is basically a callback concept that allows you to be notified when something of interest happens.
Button makes use of an ActionListener to generate events when the button is "actioned". This is the "observer pattern" in action.
Why is this important? You really want to think about what information is needed to be passed where and who's actually responsible for doing what.
For example, is it really the ButtonPanel's responsibility to update the frame? Is giving ButtonPanel unfettered control over the frame really a good idea?
Instead, ButtonPanel "should" be providing some kind of notification when some action has occurred and then any interested parties should be able to do what ever they need to.
As a "basic" example...
import java.awt.Button;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EventListener;
import javax.swing.event.EventListenerList;
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
public Test() {
Frame f = new Frame();
f.setPreferredSize(new Dimension(500, 500));
f.pack();
ButtonPanel bp = new ButtonPanel(f);
bp.addObsever(new Observer() {
#Override
public void hiWasPerformed() {
f.add("South", new Button("REEE"));
f.revalidate();
}
});
f.setVisible(true);
}
public interface Observer extends EventListener {
public void hiWasPerformed();
}
class ButtonPanel extends Panel {
private EventListenerList eventListener = new EventListenerList();
public ButtonPanel(Frame f) {
Button b = new Button("Hi");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Observer[] listeners = eventListener.getListeners(Observer.class);
for (Observer observer : listeners) {
observer.hiWasPerformed();
}
}
});
f.add("North", b);
}
public void addObsever(Observer observer) {
eventListener.add(Observer.class, observer);
}
public void removeObsever(Observer observer) {
eventListener.remove(Observer.class, observer);
}
}
}
It looks like nothing is happening because the buttons are being added below the bottom of the window. You should consider using a layout manager to solve this issue.
However, in the meantime the simple solution is to move this line f.add("South", new Button("REEE")); inside the action event and to make use of Frame.pack();:
public class Main1
{
public static void main(String[] args)
{
Frame f = new Frame();
//set minimums rather than a fixed size
f.setMinimumSize(new Dimension(500, 500));
f.setVisible(true);
CustomButton b = new CustomButton(f);
//Add this line to update/size/show the UI
f.pack();
//Don't place any more code inside the main method. Future events should be triggered by interacting with the UI/buttons
}
}
Then for the button we don't need to extend Panel, we can do something like this:
class CustomButton implements ActionListener
{
Frame parentFrame;
public CustomButton(Frame f)
{
parentFrame = f;
Button b = new Button("Hi");
b.addActionListener(this);
f.add("North", b);
}
public void actionPerformed(ActionEvent e)
{
//Add button here instead of the main class
parentFrame.add("South", new Button("REEE"));
//The buttons are being added below the bottom of your window, this will force them to be shown.
//Using a layout manager will solve this ploblem and you will not need to do this:
parentFrame.pack();
}
}
Note: clicking on the "Hi" button multiple times will have interesting results of the "REEE" buttons overlapping or doing odd things if you resize the window.
I am a bit sorry to ask this question, since it seems to be a bit obvious, but I can't find my solution alone.
I am coding a little app in Java, and I encounter some issues "redrawing" my swing components. Basically, I want my JFrame to update when an event occurs. I managed to reproduced the issue in the code below. This code is supposed to display two buttons (which it does), and replace them with a third button when you click on the first button (which it doesn't).
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame implements ActionListener {
private JButton button = new JButton("Button 1");
private JButton button2 = new JButton("Button 2");
private JButton button3 = new JButton("Button 3");
private JPanel buttons = new JPanel();
public void init() {
this.setVisible(true);
this.setSize(500,500);
buttons.add(button);
buttons.add(button2);
this.add(buttons);
this.button.addActionListener(this);
}
public void update() {
this.removeAll();
buttons.add(button3);
this.revalidate();
}
public static void main(String[] args) {
Example ex = new Example();
ex.init();
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button) {
update();
}
}
}
I am pretty sure that I am doing something wrong in the update() method. I actually have a lot of trouble to understand how works removeAll(), revalidate(), repaint() etc, and I guess that is the problem. I tried to call the same methods on the buttons panel, it almost worked but I still have a graphic bug, and I would like to do it for all the container. I also tried to call these methods on this.getContentPane(), but it doesn't work.
Can anyone try to help me with it?
You're removing all components from this (which in this case is the JFrame (as you're extending it, which isn't needed, and instead you should create an instance from it rather than inherit from it, as you're not changing the behavior of the JFrame so it's better to just create an instance of it). See: Extends JFrame vs. creating it inside the program
In this case you're adding your components in this way:
JFrame > buttons (JPanel) > JButtons
And you're trying to remove
JFrame > everything
That includes the contentPane, instead you should call.
buttons.removeAll()
Inside the update() method.
And also call this.repaint() so your update() method should become:
public void update() {
buttons.removeAll();
buttons.add(button3);
this.revalidate();
this.repaint();
}
Or the best approach is to use CardLayout as recommended by #AndrewThompson in the comment below. This way you don't have to handle removing / repainting for each component, as CardLayout will do it for you. For example
this works,
public void update() {
buttons.remove(button);
buttons.remove(button2);
buttons.add(button3);
this.revalidate();
this.repaint();
}
That's My Code Down Here. I want the answer for java.awt.Button and java.awt.Frame.
Can any one help me with it?
import java.awt.*;
import java.awt.event.*;
public class TestGUI extends Frame implements ActionListener, WindowListener{
private Label lbl;
private Label lbl1
private Label lbl2;
private Label lbl3;
private TextField tf;
private TextField tf1;
private TextField tf2;
private Button btn;
private Button btn1;
private Frame frame;
public TestGUI() {
setLayout(new FlowLayout());
lbl = new Label("Hi Guys! That's My First GUI Program and is made by me too");
add(lbl);
lbl1 = new Label("Enter Your Name Please ~");
add(lbl1);
tf1 = new TextField(30);
tf1.setEditable(true);
add(tf1);
lbl2 = new Label("Enter Your Age Please ~");
add(lbl2);
tf2 = new TextField(30);
tf2.setEditable(true);
add(tf2);
lbl3 = new Label("Enter Your School/College Name Please ~");
add(lbl3);
tf = new TextField(28);
tf.setEditable(true);
add(tf);
btn = new Button("Cancel");
add(btn);
btn.addActionListener(this);
addWindowListener(this);
setTitle("My own GUI");
setSize(500, 300);
setVisible(true);
}
public static void main(String[] args){
TestGUI app = new TestGUI();
}
#Override
public void actionPerformed(ActionEvent evt){
}
#Override
public void windowClosing(WindowEvent evt){
System.exit(0);
}
#Override public void windowDeactivated(WindowEvent evt){}
#Override public void windowActivated(WindowEvent evt){}
#Override public void windowOpened(WindowEvent evt){}
#Override public void windowClosed(WindowEvent evt){}
#Override public void windowIconified(WindowEvent evt){}
#Override public void windowDeiconified(WindowEvent evt){}
}
Thanks in Advance.
You're just complicating the things. Instead of extending the frame & implementing those interfaces, just extend JFrame.
public class TestGUI extends JFrame{...}
In your TestGUI frame create another JFrame say otherFrame and create two bottons say Open & Close and then bind ActionListener to them.
openBtn.addActionListener(new ActionListener(){
otherFrame.setVisible(true);
});
closeBtn.addActionListener(new ActionListener(){
otherFrame.setVisible(false);
});
The setVisible() method accepts boolean & this is what you actually need.
Much simpler & cleaner code.
It might make more sense for you to use a JFrame instead of a Frame (I recomend you read Kumar Vivek Mitra's answer here to get a better idea of why).
If you use a JFrame, you'll need to call yourJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) to stop your program when you close the window.
To respond to your button clicks, simply pass Anonymous Classes to your buttons addOnClickListener() method, like this:
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Do stuff here
}
});
Then you should be able to remove your existing actionPerformed() method.
For opening a new frame and closing your existing one, you should be creating two JFrame objects instead of extending Frame (or JFrame). Then, when you want to open your second frame, just call secondFrame.setVisable(true), and close your first one with firstFrame.dispose. However, I'd have a look at JDialogs and JOptionPanes first to see if they might work better for you.
After all this you should be able to remove all your WindowListener stuff, as that's for something slightly different. (Have a look here if you're interested)
Finally, don't forget to add a semicolon after your lbl1 label. ;)
Good luck!
You may use ActionListener interface.
However for a little addition to above guys commented. You may add animation to your frame by adding for loop and setSize method within the loop and the height width of the corresponding loop's variable.
I have a mouseclicker event added to some JLabels and, after one of them will be clicked, I want to remove the link between that JLabel and the mouseclicker event.
To add the mouseclicker event to JLabel I use this code:
JLabel.addMouseListener(this);
There is a way to remove the JLabel from being clicked after the effect is solved? How can I do this?
I searched something but I'm not sure to how I can describe the problem and search about it, so i didn't found results.
This may seem trivial, but you could simply do:
myLabel.removeMouseListener(this);
Option two is to leave the MouseListener in place, but make it smarter -- i.e., give it logic that allows it to ignore input if need be. This could be a simple if block such as
#Override
public void mousePressed(MouseEvent me) {
if (someBoolean) {
return;
}
// here have your usual code
}
and then in your code, when you want to de-activate the MouseListener, simply change the listener's someBoolean field to false. This use of a boolean switch or flag is useful for when you need to turn the listener on and off repeatedly.
As a side note, you're usually better off not using this for your listeners as that is giving the main GUI class a bit too much responsibility. Instead use anonymous inner classes for simple few line code or named class for more involved listener code.
For example:
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.border.Border;
public class TurnListenerOnAndOff extends JPanel {
private JLabel myLabel = new JLabel("My Label");
private JCheckBox listenerEnabledCheckBox = new JCheckBox("Listener Enabled", true);
public TurnListenerOnAndOff() {
// make label bigger with a border
Border outsideBorder = BorderFactory.createLineBorder(Color.black);
Border insideBorder = BorderFactory.createEmptyBorder(5, 5, 5, 5);
myLabel.setBorder(BorderFactory.createCompoundBorder(outsideBorder, insideBorder));
// create and add MyMouseListener to my label
myLabel.addMouseListener(new MyMouseListener());
// add components to the GUI's main JPanel
add(myLabel);
add(listenerEnabledCheckBox);
}
private class MyMouseListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
// if the JCheckBox isn't checked...
if (!listenerEnabledCheckBox.isSelected()) {
return; // let's get out of here
}
// otherwise if the check box is checked, do following code
System.out.println("myLabel pressed!");
}
}
private static void createAndShowGui() {
TurnListenerOnAndOff mainPanel = new TurnListenerOnAndOff();
JFrame frame = new JFrame("On and Off");
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();
}
});
}
}
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