Prevent JButton repaint() after click - java

I have a button. I want to change the background after I click on it. My problem here is the button auto call paintComponent(). How can prevent this? I expect after clicking the button the button will be blue, but it will still be red.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonDemo extends JButton implements ActionListener{
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.RED);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(500, 500);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.setBackground(Color.BLUE);
}
}

My personal gut feeling is that JButton is probably not suited to your desired goal.
Essentially, you want to control when and how the "selected" state of the piece is changed.
Personally, I would have some kind of controller which monitored the mouse events in some way (probably having the piece component delegate the event back to the controller) and some kind of model which control when pieces become selected, this would then notify the controller of the state change and it would make appropriate updates to the UI.
But that's a long process to setup. Instead, I'm demonstrating a simple concept where a component can be selected with the mouse, but only the controller can de-select. In this example, this will allow only a single piece to be selected
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(5, 5));
ChangeListener listener = new ChangeListener() {
private PiecePane selectedPiece;
#Override
public void stateChanged(ChangeEvent e) {
if (!(e.getSource() instanceof PiecePane)) { return; }
PiecePane piece = (PiecePane) e.getSource();
// Want to ignore events from the selected piece, as this
// might interfer with the changing of the pieces
if (selectedPiece == piece) { return; }
if (selectedPiece != null) {
selectedPiece.setSelecetd(false);
selectedPiece = null;
}
selectedPiece = piece;
}
};
for (int index = 0; index < 5 * 5; index++) {
PiecePane pane = new PiecePane();
pane.addChangeListener(listener);
add(pane);
}
}
}
public class PiecePane extends JPanel {
private boolean selecetd;
private Color selectedBackground;
private Color normalBackground;
private MouseListener mouseListener;
public PiecePane() {
setBorder(new LineBorder(Color.DARK_GRAY));
mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
setSelecetd(true);
}
};
setNormalBackground(Color.BLUE);
setSelectedBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void addNotify() {
super.addNotify();
addMouseListener(mouseListener);
}
#Override
public void removeNotify() {
super.removeNotify();
removeMouseListener(mouseListener);
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
protected void fireSelectionChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners.length == 0) {
return;
}
ChangeEvent evt = new ChangeEvent(this);
for (int index = listeners.length - 1; index >= 0; index--) {
listeners[index].stateChanged(evt);
}
}
public boolean isSelected() {
return selecetd;
}
public void setSelecetd(boolean selecetd) {
if (selecetd == this.selecetd) { return; }
this.selecetd = selecetd;
updateSelectedState();
fireSelectionChanged();
}
public Color getSelectedBackground() {
return selectedBackground;
}
public void setSelectedBackground(Color selectedBackground) {
this.selectedBackground = selectedBackground;
updateSelectedState();
}
public Color getNormalBackground() {
return normalBackground;
}
public void setNormalBackground(Color normalBackground) {
this.normalBackground = normalBackground;
updateSelectedState();
}
protected void updateSelectedState() {
if (isSelected()) {
setBackground(getSelectedBackground());
} else {
setBackground(getNormalBackground());
}
}
}
}

I created a toggle button.
You set the primary color and the alternate color in the class constructor.
When you call the switchColors method, the JButton background changes from the primary color to the alternate color. When you call the switchColors method again, the JButton background changes from the alternate color to the primary color.
In the following example, I put the switchColors method in the actionListener so you can see the color change. Each time you left-click on the JButton, the background color changes.
You would call the switchColors method when you want the JButton background to change from blue to red, and again when you want the JButton background to change from red to blue. It's under your control.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonDemo extends JButton
implements ActionListener {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Button Demo");
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo(Color.BLUE,
Color.RED));
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
private boolean primaryBackground;
private Color primaryColor;
private Color alternateColor;
public ButtonDemo(Color primaryColor,
Color alternateColor) {
this.primaryColor = primaryColor;
this.alternateColor = alternateColor;
this.primaryBackground = true;
this.setText("BUTTON TEXT");
this.setBackground(primaryColor);
this.addActionListener(this);
}
public void switchColors() {
primaryBackground = !primaryBackground;
Color color = primaryBackground ? primaryColor :
alternateColor;
this.setBackground(color);
}
#Override
public void actionPerformed(ActionEvent e) {
switchColors();
}
}

If you want to change the background for a short while you can do it with swing Timer:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ButtonDemo extends JButton implements ActionListener{
private static final int DELAY = 600; //milliseconds
private final Timer timer;
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
Color defaultCloor = getBackground();
timer = new Timer(DELAY, e-> setBackground(defaultCloor));
timer.setRepeats(false);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(300, 200);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
this.setBackground(Color.RED);
timer.start();
}
}

Related

Repeated clicks of JButton automatically

How to make a JButton to be clicked automatically after every second?
I've tried editing the button action performed but that doesn't work.
You can use swing's Timer class and
doClick method with AbstractButton.
Here is a full source code.
package stackoverflow;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class JButtonTimer extends JPanel {
private static final long serialVersionUID = 1L;
private static final int SCREEN_WIDTH = 500;
private static final int SCREEN_HEIGHT = 500;
public JButtonTimer() {
final JButton clickBtn = new JButton("clickMe");
clickBtn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println(e.getActionCommand());
}
});
add(clickBtn);
Timer timer = new Timer(1 * 1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
clickBtn.doClick();
}
});
timer.start();
}
public Dimension getPreferredSize() {
return new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);
}
public static void createAndShowGui() {
JFrame frame = new JFrame();
frame.add(new JButtonTimer());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Use a SwingTimer and call doClick on the button
import javax.swing.JButton;
import javax.swing.Timer;
public class ButtonClicker implements ActionListener {
private JButton btn;
private Timer timer;
public ButtonClicker(JButton btn) {
this.btn = btn;
timer = new Timer(1000, this);
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
}
#Override
public void actionPerformed(ActionEvent e) {
btn.doClick();
}
}
See How to use Swing Timers for more details
You can put it into WindowOpened Frame event
Timer t = new Timer(1000, jButton.doClick());
t.start();

trying to display timer count, drawString method not working properly

I am trying to display a timer count, but it is not being displayed, but everything else works fine. Thank you for helping btw.
import javax.swing.*;
import java.util.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Tester {
static Timer timer;
static JFrame frame;
static JPanel panel;
public static void init(){
frame = new JFrame();
panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
frame.add(panel);
}
The method above is just to make code cleaner.
public static void main(String[] args) {
init();
class Clicker extends JPanel{
int timesClicked;
public Clicker(){
timesClicked = 0;
}
void updateClicks(){
timesClicked++;
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.drawString("Half Seconds: "+timesClicked, 100, 100);
}
} //end of Clicker
drawString method not working is above.
final Clicker c = new Clicker();
panel.add(c);
class TimeChecker implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
c.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
timer = new Timer(500,listener);
timer.start();
}
}
You have a combination of issues
Clicker was never actually added to anything
panel uses a FlowLayout by default, but Clicker provides no sizing hints, so it's sized to 0x0
You code generally is setup a little weird. I would learn to do without static very, very quickly.
Quick and fast solution...
Change the layout manager for panel to BorderLayout...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
static Timer timer;
static JFrame frame;
static JPanel panel;
public static void init() {
frame = new JFrame();
panel = new JPanel(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
frame.add(panel);
}
public static void main(String[] args) {
init();
class Clicker extends JPanel {
int timesClicked;
public Clicker() {
timesClicked = 0;
}
void updateClicks() {
timesClicked++;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.setColor(Color.BLACK);
g2.drawString("Half Seconds: " + timesClicked, 100, 100);
}
} //end of Clicker
final Clicker c = new Clicker();
panel.add(c);
panel.revalidate();
panel.repaint();
class TimeChecker implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
c.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
timer = new Timer(500, listener);
timer.start();
}
}
A slightly different approach (with out static)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Clicker clicker = new Clicker();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(clicker);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
class TimeChecker implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
clicker.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
Timer timer = new Timer(500, listener);
timer.start();
}
});
}
public class Clicker extends JPanel {
private int timesClicked;
public Clicker() {
timesClicked = 0;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
void updateClicks() {
timesClicked++;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.setColor(Color.BLACK);
g2.drawString("Half Seconds: " + timesClicked, 100, 100);
}
}
}

Paint Swing JButton as disabled

I want to display a normal JButton as disabled, without setting it to setEnabled(false)!
I just want to show that this button is not enabled, but if the user pushs the button it should call the actionlistener as normal.
So what I did is:
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class SwingTests {
private static void createWindow() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
MyButton button = new MyButton("Press");
button.setEnabled(false);
panel.add(button);
frame.add(panel);
frame.setSize(200, 200);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createWindow();
}
});
}
}
class MyButton extends JButton {
private boolean enabled = false;
public MyButton(String text) {
super(text);
super.setEnabled(true);
}
#Override
protected void paintBorder(Graphics g) {
if (isEnabled())
super.paintBorder(g);
else
; // paint disabled button
}
#Override
protected void paintComponent(Graphics g) {
if (isEnabled())
super.paintComponent(g);
else
; // paint disabled button
}
#Override
public void setEnabled(boolean b) {
enabled = b;
}
#Override
public boolean isEnabled() {
return enabled;
}
}
I "just" need to know what to write in paintComponent(g) and paintBorder(g).
if it is disabled and a user pushs the button i display an alarm why this button is disabled!
If it looks disabled I am probably not going to push it in the first place. You could achieve this type of effect using tool tips.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
public class TestGUI {
public TestGUI() {
JFrame frame = new JFrame();
final JButton button = new JButton("Press Me");
final JToggleButton enable = new JToggleButton("Enable / Disable");
enable.setSelected(true);
button.setToolTipText("Enabled");
enable.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
if (enable.isSelected()) {
button.setEnabled(true);
button.setToolTipText("Enabled");
} else {
button.setEnabled(false);
button.setToolTipText("Not Enabled");
}
}
});
frame.add(button, BorderLayout.CENTER);
frame.add(enable, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TestGUI();
}
});
}
}
if it is disabled and a user pushs the button i display an alarm why this button is disabled!
Add a MouseListener to the button when it is disabled. Then you can handle the mouseClicked() event to display your "alarm".

Adding background image to JPanel on button action

What is the best way to add a background image to a JPanel/JLabel when a JButton is called? I know how to get the JButton action and such. I just can't figure out or find a way to get the background image to change when that button is pressed.
Here is an example:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class ModifiableBackgroundFrame extends JFrame implements ActionListener
{
private static final long serialVersionUID = 1L;
private ImageIcon image;
private JPanel pan;
private JButton btn;
private int count = 0;
private static final String[] images =
{"http://www.dvd-ppt-slideshow.com/images/ppt-background/background-3.jpg",
"http://www.psdgraphics.com/wp-content/uploads/2009/02/abstract-background.jpg",
"http://hdwallpaperpics.com/wallpaper/picture/image/background.jpg",
"http://www.highresolutionpics.info/wp-content/uploads/images/beautiful-on-green-backgrounds-for-powerpoint.jpg"};
public ModifiableBackgroundFrame()
{
super("The title");
image = new ImageIcon();
btn = new JButton("Change background");
btn.setFocusPainted(false);
btn.addActionListener(this);
pan = new JPanel()
{
private static final long serialVersionUID = 1L;
#Override
public void paintComponent(Graphics g)
{
g.drawImage(image.getImage(), 0, 0, null);
}
};
pan.setPreferredSize(new Dimension(400, 400));
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(pan, BorderLayout.CENTER);
contentPane.add(btn, BorderLayout.SOUTH);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new ModifiableBackgroundFrame();
}
});
}
#Override
public void actionPerformed(ActionEvent e)
{
btn.setEnabled(false);
btn.setText("Loading...");
new SwingWorker<Image, Void>()
{
#Override
protected Image doInBackground() throws Exception
{
return ImageIO.read(new URL(images[count++ % 4]));
}
#Override
protected void done()
{
try
{
image.setImage(get());
pan.repaint();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
catch(ExecutionException e)
{
e.printStackTrace();
}
btn.setText("Change background");
btn.setEnabled(true);
}
}.execute();
}
}
In your JButton's actionPerformed, you can call JLabel.setIcon(Icon) to set a background image.
final JLabel label = new JLabel();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
label.setIcon(new ImageIcon(SOME_IMAGE));
}
}

Animate/scroll text

I am wondering to know about how to make scrolling text. Just like text which can scroll from right to the left. How to animate text in Java GUI?
maybe not an answer for OP, but I can't see reason, very simple by implements Swing Timer, (may be with Translucent container) and put there a JLabel, (updates to the JLabel could be from Array of Chars to avoids resize of container), for example
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
public class SlideTextSwing {
private JWindow window = new JWindow();
private JLabel label = new JLabel("Slide Text Swing, Slide Text Swing, ..........");
private JPanel windowContents = new JPanel();
public SlideTextSwing() {
windowContents.add(label);
window.add(windowContents);
window.pack();
window.setLocationRelativeTo(null);
final int desiredWidth = window.getWidth();
window.getContentPane().setLayout(null);
window.setSize(0, window.getHeight());
window.setVisible(true);
Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int newWidth = Math.min(window.getWidth() + 1, desiredWidth);
window.setSize(newWidth, window.getHeight());
windowContents.setLocation(newWidth - desiredWidth, 0);
if (newWidth >= desiredWidth) {
((Timer) e.getSource()).stop();
label.setForeground(Color.red);
mainKill();
}
}
});
timer.start();
}
public void mainKill() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
timer.start();
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
SlideTextSwing windowTest = new SlideTextSwing();
}
});
}
}

Categories

Resources