I have a very simple example. A button on the bottom of the screen that says "hi" and when its clicked it prints "hello" to the console. However, When I press the button, it doesn't change visually. Its the same with the other JSwing interactors, but for a SSCCE, here you go.
import acm.program.*;
import javax.swing.*;
import java.awt.event.*;
public class SimpleGUI extends ConsoleProgram {
public void init() {
JButton hi = new JButton("Hi");
add(hi, SOUTH);
addActionListeners();
}
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd.equals("Hi")) println("Hello there sexy");
}
}
Appearance of Swing controls (including buttons) is controlled by the look-n-feel. This includes whether or not buttons look depressed when clicked.
This may help:
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
Related
Is it possible to add more than 1 mouselistener to a JButton? You know when I click on the button it should change color and text, and do something (e.g system.out.println), and when I click it again it should go back to the previous state, and print something else.
What I've tried:
JButton b = new JButton("First");
b.setBackground(Color.GREEN);
b.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
b.setBackground(Color.RED);
b.setText("Second");
System.out.println("You've clicked the button");
}
if(b.getModel.isPressed){
b.setBackground(Color.GREEN);
b.setText("Second");
System.out.println("You're back");
}
The problem is that the button doesn't go back to the previous state with the color (green) and text, and I don't how to handle that.
First of all, you shouldn't be using a MouseListener to do these things, because a better listener, ActionListener, was built specifically to be used with JButtons and similar entities to notify programs that a button has been pressed.
Having said that, sure you can add multiple ActionListeners (or MouseListeners) to a JButton, or you can have an ActionListener change its behaviors depending on the state of the program (usually meaning the values held by fields of the class).
A problem with your code and question is that I don't see when you expect or want the button to change its color back to green. If after a certain period of time, then have your ActionListener start a Swing Timer that changes the button's color back to green after x milliseconds.
Edit: I see, you want to toggle color -- then use a boolean field that you toggle or check the button's current color and base the listener's response based on that color.
example
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
#SuppressWarnings("serial")
public class ToggleColor extends JPanel {
public ToggleColor() {
JButton button = new JButton(new MyButtonAction());
button.setBackground(Color.GREEN);
add(button);
}
private static void createAndShowGui() {
ToggleColor mainPanel = new ToggleColor();
JFrame frame = new JFrame("ToggleColor");
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(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class MyButtonAction extends AbstractAction {
// !! parallel arrays being used below -- avoid if possible
private static final String[] TEXT = {"First", "Second", "Third"};
private static final Color[] COLORS = {Color.GREEN, Color.RED, new Color(108, 160, 220)};
private int index = 0;
public MyButtonAction() {
super(TEXT[0]);
}
#Override
public void actionPerformed(ActionEvent e) {
index++;
index %= TEXT.length;
putValue(NAME, TEXT[index]);
Component c = (Component) e.getSource();
c.setBackground(COLORS[index]);
}
}
This uses an AbstractAction class which is like an ActionListener but on "steroids"
You should only register one lister, but that listener will maintain some state regarding the number for mouse clicks. A simple if/else block will change the actions and change the text on the button label.
I have a code that opens up a JOptionPane dialog box once the user hits a button. The first thing I want to do is close the first JFrame as soon as the user hits one of the buttons. I have tried doing this
setVisible(false); // Delete visibility
dispose(); //Delete window
but the original JFrame doesn't close as soon as a button is pressed. The goal is to have two buttons. When one is pressed, show a JOptionPane box, while simultaneously closing the first JFrame window. How can I do that? Next, after the ok is pushed in the new JOptionPane I wan't to stimulate what would be an action listener. I do this by calling the method
sinceyoupressedthecoolbutton();
right after my JOptionPane declaration. Here is where the second issue starts, it displays the JOptionPane perfectly, but doesn't go to the method
sinceyoupressedthecoolbutton();
I don't know if the problem is in the method calling or the content of the method. Basically, after ok is pressed on the JOptionPane, I wan't to move to another method, which opens a new JLabel.
Here is the code:
package Buttons;
import java.awt.Dimension;
import java.awt.FlowLayout; //layout proper
import java.awt.event.ActionListener; //Waits for users action
import java.awt.event.ActionEvent; //Users action
import javax.swing.JFrame; //Window
import javax.swing.JLabel;
import javax.swing.JButton; //BUTTON!!!
import javax.swing.JDialog;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane; //Standard dialogue box
public class ButtonClass extends JFrame {
private JButton regular;
private JButton custom;
public ButtonClass() { // Constructor
super("The title"); // Title
setLayout(new FlowLayout()); // Default layout
regular = new JButton("Regular Button");
add(regular);
custom = new JButton("Custom", b);
add(custom);
Handlerclass handler = new Handlerclass();
Otherhandlerclass original = new Otherhandlerclass();
regular.addActionListener(handler);
custom.addActionListener(original);
//THIS WAS MY FIRST PROBLEM, I WANT TO CLOSE THE FIRST JFRAME WINDOW AS THE USER HITS OK
setVisible(false); // Close the show message dialog box
dispose();
}
public class Handlerclass implements ActionListener { // This class is
// inside the other
// class
public void actionPerformed(ActionEvent eventvar) { // This will happen
// when button is
// clicked
JOptionPane.showMessageDialog(null, String.format("%s", eventvar.getActionCommand())); //opens a new window with the name of the button
}
}
public class Otherhandlerclass implements ActionListener {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null,"Since you pressed that button, I will open a new window when you press ok, okay?");
//Code works up until here
sinceyoupressedthecoolbutton(); //THIS METHOD SHOULD OPEN A NEW WINDOW!
}
public void sinceyoupressedthecoolbutton() {
JDialog YES = new JDialog();
JLabel label = new JLabel("Here is that new window I promised you!");
add(label);
YES.setDefaultCloseOperation(JDialog.EXIT_ON_CLOSE);
YES.setSize(500, 500);
YES.setVisible(true);
}
public class okay implements ActionListener {
public void actionPerformed(ActionEvent ok) {
}
}
}
}
Help would be appreciated!
You're working in a Event Driven Environment, not a linear processing one. This means that you run some code and then wait (the waiting is done for you) for some event to occur and then you respond to it...
Nothing can happen till the user presses the custom button, so it's pointless trying to close the frame before then
When your Otherhandlerclass's actionPerformed is triggered, obviously you show the JOptionPane pane, this will block the flow of the execution until it's closed. At this point, you should have the opportunity to the dispose of the original window.
So instead of calling setVisible(false) and dispose in your constructor, it would be better to move it to Otherhandlerclass
public class Otherhandlerclass implements ActionListener {
public void actionPerformed(ActionEvent e) {
dispose();
JOptionPane.showMessageDialog(null, "Since you pressed that button, I will open a new window when you press ok, okay?");
sinceyoupressedthecoolbutton();
}
public void sinceyoupressedthecoolbutton() {
JDialog YES = new JDialog();
JLabel label = new JLabel("Here is that new window I promised you!");
YES.add(label);
YES.setSize(500, 500);
YES.setVisible(true);
}
public class okay implements ActionListener {
public void actionPerformed(ActionEvent ok) {
}
}
}
Having said that, I'd encourage you to have a read of The Use of Multiple JFrames, Good/Bad Practice? and maybe consider using something like How to Use CardLayout instead
I am trying to write a test java program in order to learn how mouse listeners work in java. Basically, I was trying to write a graphics program and that if I click on the canvas, the program generates a label "hello" at the place where I clicked my mouse. But nothing happens after I click my mouse. Here is my code. Can anybody help me with it?
import acm.program.*;
import acm.graphics.*;
import java.awt.event.*;
public class test extends GraphicsProgram{
public void run(){
addMouseListeners();
}
public void MouseClicked(MouseEvent e){
label=new GLabel("Hello",e.getX(),e.getY());
add(label);
}
private GLabel label=null;
}
My goal is to write something that is visible to the user in the JTextField and to display this text in the console.
As of now, the JTextField is accepting text but nothing shows. No cursor, no text.
I've tried using textfield.setEditable(true), textfield.setEnable(true) and different fore and background colors but nothing happens.
Curiously I can use textField.setText("Random text") and it shows, but I cant delete it or edit this when the program is running and it's not included in the outputs from getText().
This is the program :
import acm.program.*;
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class TextFieldTest extends ConsoleProgram implements SomeConstants {
public void init() {
setSize(APPLICATION_WIDTH, APPLICATION_HEIGHT);
textField = new JTextField(20);
add(textField, SOUTH);
textField.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == textField)
println("Hi, " + textField.getText());
}
private JTextField textField;
}
If you're working with acm.program.ConsoleProgram, you may need to use Java SE 5 (version 1.5), as suggested here.
Addendum: As #Tor comments, java.awt.TextField may be acceptable under later versions of the JRE.
I have a problem where when I try and add a mouselistener to a JLabel or JButton in a JTextPane I get the error "cannot be converted to Mouselistener by invocation conversion". I would prefer to have the component in a JEditorPane. I also heard a HyperlinkEvent could be used.
Basicly I want a component that can be right/left clicked in a JEditorPane(preffered)/JTextPane. Any help would be appreciated
Now it works (sortof) it only recives right clicks and I need to not draw button edges. Can I underline the button's text?
Example code follows...
import java.awt.*;
import javax.swing.*;
import java.awt.Color;
import javax.swing.JTextPane;
import javax.swing.JButton;
import java.applet.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class jlabeltest extends Applet {
public void init() {
jlabeltest editorPaneExample = new jlabeltest();
editorPaneExample.setSize(550, 300);
// editorPaneExample.setText("tutorialData.com");
editorPaneExample.setVisible(true);
}
public jlabeltest() {
JTextPane editorPane = new JTextPane();
editorPane.setSelectedTextColor(Color.red);
editorPane.setText("<p color='#FF0000'>Cool!</p>");
InlineB label = new InlineB("JLabel");
label.setAlignmentY(0.85f);
label.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e)
{
if (e.isPopupTrigger())
{
JOptionPane.showMessageDialog(null,"Hello!");
// do your work here
}
}
});
editorPane.insertComponent(label);
this.add(editorPane);
}
}
InlineB.java
import javax.swing.JButton;
public class InlineB extends JButton {
public InlineB( String caption ) {
super( caption );
}
}
I'm not sure what you want the question is everywhere.
But look too underline text of a JButton simply set the text of the button with HTML tags:
//added <u></u> to underlone button
InlineB label = new InlineB("<html><u>JLabel</u></html>");
as for the left click add a check to your if statement for the MouseEvent.BUTTON1 or SwingUtilities.isLeftMouseButton(MouseEvent me):
//added check for MouseEvent.BUTTON1 which is left click
if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON1) {
}
To not draw the borders of the JButton simply call setBorder(null); either in the InlineB class or on the InlineB instance (I did it within the class):
public InlineB(String caption) {
super(caption);
setBorder(null);//set border to nothing
}
also I see that you dont set the content type of the JTextPane, which you should:
//set content as html
editorPane.setContentType("text/html");
I did a small example though I did not use an Applet but its very easy to port:
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class Test {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.pack();
frame.setVisible(true);
}
private void initComponents(JFrame frame) {
JTextPane editorPane = new JTextPane();
editorPane.setSelectedTextColor(Color.red);
//set content as html
editorPane.setContentType("text/html");
editorPane.setText("<p color='#FF0000'>Cool!</p>");
//added <u></u> to underlone button
InlineB label = new InlineB("<html><u>JLabel</u></html>");
label.setAlignmentY(0.85f);
label.addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
//added check for MouseEvent.BUTTON1 which is left click
if (e.isPopupTrigger() || e.getButton() == MouseEvent.BUTTON1) {
JOptionPane.showMessageDialog(null, "Hello!");
// do your work here
}
}
});
editorPane.insertComponent(label);
frame.getContentPane().add(editorPane);
}
}
class InlineB extends JButton {
public InlineB(String caption) {
super(caption);
setBorder(null);//set border to nothing
}
}
I have a problem where when I try and add a mouselistener to a JLabel or JButton in a JTextPane I get the error "cannot be converted to Mouselistener by invocation conversion".
The object you are passing to addMouseListener() implements the MouseListener interface. Right? (Just seen the code sample. Mouse adapter seems right).
You now say Now it works (sortof). Does it mean you have corrected that error?
BTW if that is resolved and you have subsequent problems, and they are reusable by the community, then i would advise to open a separate question: https://meta.stackexchange.com/questions/48345/what-is-the-etiquette-for-changing-the-substance-of-a-question
I would prefer to have the component in a JEditorPane.
I guess you mean the component you are listening. Anyway I'm not sure the JEditorPane is meant to be used as other components' container.
I also heard a HyperlinkEvent could be used.
HyperLinkEvent is meant for ENTERED, EXITED, and ACTIVATED event types. You are intending to handle Hyperlink events or mouse events?
Basicly I want a component that can be right/left clicked in a JEditorPane(preffered)/JTextPane. Any help would be appreciated
I would advise next time give the scope/context of the question first. I guess you mean you want something (can you be more specific?) on top of a text pane that can be clicked. Anyway I'm surprise you intend to use JEditorPane that way.