I want to set setDissmissDelay() method multiple times, but I could not set it for a specific value again and again. I also tried to use an infinite loop, and tried to override (ToolTipManager Constructor is on default modifier).
I know for sure the code is working properly as I can see it's printing the e.getsource() in console. I was trying to solve this issue asked by someone (This Question) and while solving that I became stumped at this point. What is the reason behind that? And if I can set the value how can it be? Is there any other way to achieve this?
Here is my code snippet:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class Hello {
static JButton button;
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton("Hello World");
button.setToolTipText("Its a tool tip Experiment!");
frame.getContentPane().add(button);
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() == button) {
ActionListener tt = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ToolTipManager.sharedInstance().setDismissDelay(
1000);
System.out.println(e.getSource());
}
};
new Timer(100, tt).start();
}
}
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Please guide me through this.
Calling setDismissDelay() is a global setting to indicate how long should a Tooltip remain on the display before it is removed. It does not reset the time until when the current tooltip is removed. As suggested in your linked question setting the dismiss delay, once and for all, to Integer.MAX_VALUE should do the trick.
Related
I have made an SSCCE. Please note that it must be Windows Look&Feel.
import java.awt.*;
import javax.swing.*;
public class DefaultButtonBug {
private static final String LAF_WINDOWS = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(LAF_WINDOWS);
} catch (Exception ex) {
System.out.println("Setting the L&F failed so I cannot reproduce the bug.");
System.exit(1);
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JPanel content = new JPanel();
JButton defaultButton = new JButton("Default");
content.add(defaultButton);
JFrame frame = new JFrame();
frame.getRootPane().setDefaultButton(defaultButton);
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
Launch this
The button should be focused. If not, click it.
Click on any other window, to make sure this current window loses the focus
The button keeps animating in blue tints, even when this window has no focus anymore!
The button 'pulsing' animation is something not present in the standard Java L&F.
Remark that when this button is no longer the default button (remove the appropriate line in the code), the button will be gray after the window loses focus and there is no animation whatsoever.
My question to you is: is this considered a bug? Because this makes the EDT keep doing stuff instead of being idle when the window is hidden behind another window too (I did some profiling). Indeed, that's the stuff that bothers me the most of all: hiding the window does not make the EDT go idle.
getRootPane() default button - Is this a bug?
not as described in a comment by #Guillaume Polet
but I'd be inclined to use KeyBindings, because any JComponents with FocusInWindow and added ActionListener can consume() ENTER key pressed, for all JButtons JComponents
focus is managable by getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT/*.WHEN_FOCUSED*/)
notice (Win OS) JButton has implemented TAB as an accelerator in KeyBindings, too.
from code
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class DefaultButtonBug {
private static final String LAF_WINDOWS = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(LAF_WINDOWS);
} catch (Exception ex) {
System.out.println("Setting the L&F failed so I cannot reproduce the bug.");
System.exit(1);
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JPanel content = new JPanel();
JButton focusedButton1 = new JButton("Focused");
focusedButton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Focused pressed");
}
});
content.add(focusedButton1);
final JButton defaultButton2 = new JButton("Default");
defaultButton2.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
defaultButton2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Default pressed");
}
});
defaultButton2.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isRollover()) {
defaultButton2.setIcon(UIManager.getIcon("OptionPane.errorIcon"));
} else {
defaultButton2.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
}
}
});
content.add(defaultButton2);
JFrame frame = new JFrame();
frame.getRootPane().setDefaultButton(defaultButton2);
frame.getRootPane().getInputMap(
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT/*.WHEN_FOCUSED*/)
.put(KeyStroke.getKeyStroke("ENTER"), "clickButton");
frame.getRootPane().getActionMap().put("clickButton", new AbstractAction() {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
defaultButton2.doClick();
}
});
frame.getRootPane().setDefaultButton(defaultButton2);
frame.setContentPane(content);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
learning item of day
on Win7/8 (Java6/7) are allowed mouse event on un_focused Java Window (for all standard L&F), can be listener from ChangeListener added to ButtonModel
doesn't work on WinXP
focused
un_fosused firing the same events a
EDIT
in Win7 compiled in JDK7_011 flashing JButtons (focused in Java window) with blue Color
flashing with blue color on second period
and
In Swing, there are several ways to capture the event of minimizing a frame (iconifying), but the event happens when the frame is ICONIFIED which means after the frame becomes invisible from the screen.
Now I wish to run some code before disappearance of the frame -- immediately when I click the taskbar button.
In other words, do something when the JFrame is "about to" (NOT AFTER) be minimized. Is it possible to do this?
Use WindowStateListener, and call WindowEvent#getNewState() and check against Frame.ICONIFIED.
Here is an example:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
frame.add(panel);
frame.addWindowStateListener(new WindowAdapter() {
#Override
public void windowStateChanged(WindowEvent we) {
if (we.getNewState() == Frame.ICONIFIED) {
System.out.println("Here");
}
}
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
Create your own JFrame and override setExtendedState method.
public class MyFrame extends JFrame{
....
setExtendedState(JFrame.ICONIFIED);
....
#Override
public void setExtendedState(int state) {
// your code
super.setExtendedState(state);
};
}
Answer to the question "Is it possible to perform some action BEFORE a JFrame is minimized?"
I would say no unfortunately, I checked the native code for openjdk (windows) for frame and window that sends these events to java-space. And as I understand it, it is a callback from the windows API VM_SIZE message. And the SIZE_MINIMIZED is sent when "The window has been minimized" and is not getting any messages before the actual minimization.
Here is a simple version of my code:
JTextArea textareaA = new JTextArea(...);
JTextArea textareaB = new JTextArea(...);
textareaA.addModificationListener(new Modification Listener()
{
public void modified(Modifiable arg0){
if (textareaA.getValue().contains("\t"))
{
textareaA.setValue(textareaA.getValue().trim());
textareaB.getTextComponent().requestFocusInWindow();
}
}
});
The problem is, when I try different ways to change the value of A, B never gets the focus. If I turn off the focusable of A, I can't turn it back on. I need to remove the tab from A, then give focus to B, allowing the user to click back to A if needed, and the tab be gone. The above code causes the focus to stay in A, even though I had B request it. Is this a timing issue maybe?
Thank you!
As far as I understood your question, you want a user to be able to type "Tab" and switch to the next textarea. You also want to trim the last "Tab" entered.
Besides the fact that if you type a "Tab" in the middle of the text, it will not get removed, the next code (based and elaborated from your own) seems to do what you want:
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class Test {
protected void initUI() {
final JFrame frame = new JFrame();
frame.setTitle("Test dialog synch");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
final JTextArea textareaA = new JTextArea(24, 80);
final JTextArea textareaB = new JTextArea(24, 80);
textareaA.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
textareaB.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
textareaA.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
modified();
}
#Override
public void insertUpdate(DocumentEvent e) {
modified();
}
#Override
public void removeUpdate(DocumentEvent e) {
modified();
}
public void modified() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
if (textareaA.getText().contains("\t")) {
textareaA.setText(textareaA.getText().trim());
textareaB.requestFocusInWindow();
}
}
});
}
});
panel.add(textareaA, BorderLayout.NORTH);
panel.add(textareaB, BorderLayout.SOUTH);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test().initUI();
}
});
}
}
I have a Swing application that deals with date and time, so a lot of tests are done changing the system's date and time settings.
During the tests, we noticed that after decreasing the clock, the first click is ignored by the application.
Is it a bug of Swing/Java/Windows? Is there a workaround to this?
Interestingly, this issue only happens when decreasing the date/time settings. If I increase it, the application behaves normally.
Situation:
Swing application running.
Decrease Windows date and time settings (e.g. change time from 15:00 to 14:00).
Notice that the first click in the Swing application does not fire any action.
Code example (you can use it to testify the situation):
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
final JFrame frame = new JFrame("frame");
final JButton button = new JButton("button");
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
System.out.println("Button Pressed!");
}
});
frame.add(button);
frame.setSize(200, 200);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
}
}
As seen here the Swing uses a date to check when the event occoured. So, in some way, probally a handler is acting here, by discarting your action, since it happened "before" the last action. I can't confirm you this, but probally some Layout Manager or another handler is messing with something here to prevent delayed events to mess up with the current flow.
I've debugged it via Eclipse and found out what is happening.
Clock at 15:00h.
Click at the button. Swing record last event time to 15:00.
Change the clock to 14:00h.
Click at the button. Swing ignores the event because it looks like a multi-click.
The problem here is that the comparison made by Swing checking for multi-click is this:
if (lastTime != -1 && currentTime - lastTime < multiClickThreshhold) {
shouldDiscardRelease = true;
Here, currentTime - lastTime yields a negative value. It's less than 0 (my multiClickThreshhold), so it does not fire the action event:
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
// Support for multiClickThreshhold
if (shouldDiscardRelease) {
shouldDiscardRelease = false;
return;
}
AbstractButton b = (AbstractButton) e.getSource();
ButtonModel model = b.getModel();
model.setPressed(false);
model.setArmed(false);
}
}
All the source listed above is in javax.swing.plaf.basic.BasicButtonListener.
The Button class does have a setMultiClickThreshhold, but it throws IllegalArgumentException in case the threshhold is less than 0.
So, as a workaround, I did this:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.Field;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) throws Exception {
final JFrame frame = new JFrame("frame");
final JButton button = new JButton("button");
removeMulticlickThreshold(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
System.out.println("Button Pressed!");
}
});
frame.add(button);
frame.setSize(200, 200);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(final WindowEvent e) {
System.exit(0);
}
});
}
private static void removeMulticlickThreshold(final JButton button) throws Exception {
final Field multiClickThreshhold = AbstractButton.class.getDeclaredField("multiClickThreshhold");
multiClickThreshhold.setAccessible(true);
multiClickThreshhold.set(button, Long.MIN_VALUE);
}
}
I would like to create a JButton that changes its text periodically after the first click. I'm not really familiar with Swing library. What would be a good starting point? May I update its text without an action?
Thank you.
for all periodical events in Swing I only suggest javax.swing.Timer
output by using Timer should be, for example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;
public class CrazyButtonTimer {
private JFrame frame = new JFrame(" Crazy Button Timer");
private JButton b = new JButton("Crazy Colored Button");
private Random random;
public CrazyButtonTimer() {
b.setPreferredSize(new Dimension(250, 35));
frame.getContentPane().add(b);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
javax.swing.Timer timer = new Timer(500, new TimerListener());
timer.setInitialDelay(250);
timer.start();
}
private class TimerListener implements ActionListener {
private TimerListener() {
}
#Override
public void actionPerformed(final ActionEvent e) {
Color c = b.getForeground();
if (c == Color.red) {
b.setForeground(Color.blue);
} else {
b.setForeground(Color.red);
}
}
}
public static void main(final String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CrazyButtonTimer crazyButtonTimer = new CrazyButtonTimer();
}
});
}
}
If you to change it on every fixed amount of time then you can use Swing Timer or Thread to do this. But for this you have to listen at least one action so that you can initialize and start it.
You can also use TimerTask class from java.util like follow:
java.util.TimerTask timerTask = new java.util.TimerTask() {
#Override
public void run() {
//change button text here using button.setText("newText"); method
}
};
java.util.Timer myTimer = new java.util.Timer();
myTimer.schedule(timerTask, 3 * 1000, 3* 1000); // This will start timer task after 3 seconds and repeat it on every 3 seconds.
I suggest you to create a timer (here you can find some doc)
Timer timer = new Timer(100,this);
Your class has to extend action listener ed implements the following method which allow you to change the text of your JButton(I called it ``button).
public void actionPerformed(ActionEvent e) {
if(e.getSource.equals(timer)){
button.setText("newText");
}
}
Luca
All the other answers fail to mention how to update non-periodically. If you need it to update irregularly, you can make a method in your GUI class called something like: updateButton(); and just call that every time you want it to change your text.
public void updateButton(String newText)
{
Button.setText(newText);
}
Just thought I'd add this in case someone wanted to set it irregularly.
If you want to change it periodically (e.g. every 5th second) you could create a new Thread which sets the text of the button to the desired value and repaints it (if necessary).