I'm trying to change to appearance of my JButton so that the button have no up state.
Currently i have something like this:
And i would like something like this:(comming from NetBeans)
In other words, I only want the image of the button to be visible when the button does not have any kind of focus. But when the user click or roll over it, it should act exactly the same as a regular button.
more examples:
no focus
roll over
click
I use a inner class for my button. It look like this:
private class CustumJButton extends JButton
{
public CustumJButton(Icon icon)
{
super(icon);
int size = 30;
setPreferredSize(new Dimension(size, size));
setFocusable(false);
}
}
Thanks ayoye.
You can achieve this using setBorderPainted() and setContentAreaFilled() methods. Here is the short Demo of what you are looking for. I hope it would give you rough figure to how to achieve your task.:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class CustomJButton extends JButton
{
public CustomJButton(String icon)
{
super(icon);
/*int size = 30;
setPreferredSize(new Dimension(size, size));*/
addFocusListener(new ButtonFocusAdapter());
addMouseListener(new ButtonMouseAdapter());
setContentAreaFilled(false);
setBorderPainted(false);
//setFocusable(false);//Don't use this method. This would avoid the focus event on JButton
}
private void decorateButton()
{
setContentAreaFilled(true);
setBorderPainted(true);
}
private void unDecorateButton()
{
setContentAreaFilled(false);
setBorderPainted(false);
}
private class ButtonFocusAdapter extends FocusAdapter
{
#Override
public void focusGained(FocusEvent evt)
{
decorateButton();
}
#Override
public void focusLost(FocusEvent evt)
{
unDecorateButton();
}
}
private class ButtonMouseAdapter extends MouseAdapter
{
#Override
public void mouseEntered(MouseEvent evt)
{
decorateButton();
}
#Override
public void mouseExited(MouseEvent evt)
{
unDecorateButton();
}
}
}
public class ButtonFrame extends JFrame
{
public void createAndShowGUI()
{
Container c = getContentPane();
c.setLayout(new FlowLayout());
for (int i = 0; i < 4 ; i++ )
{
CustomJButton cb = new CustomJButton("Button "+i);
c.add(cb);
}
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String st[])
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
ButtonFrame bf = new ButtonFrame();
bf.createAndShowGUI();
bf.setLocationRelativeTo(null);
}
});
}
}
I guess you need to use these two things to make it work, setBorderPainted(boolean) and setContentAreaFilled(boolean)
buttonObject.setBorderPainted(false);
buttonObject.setContentAreaFilled(false);
as cited in this example for changing appearance of JButton by #mKorbel
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ButtonDemo
{
private JButton demoButton;
private ImageIcon buttonImage;
private void displayGUI()
{
JFrame frame = new JFrame("Button Demo Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
try
{
//buttonImage = new ImageIcon(ImageIO.read(
// getClass().getResource("/image/bulb.gif")));
buttonImage = new ImageIcon(ImageIO.read(
new URL("http://gagandeepbali.uk.to/"
+ "gaganisonline/swing/downloads/"
+ "images/bulb.gif")));
}
catch(Exception e)
{
e.printStackTrace();
}
demoButton = new JButton(buttonImage);
setExceptionalState(demoButton);
demoButton.addMouseListener(new MouseAdapter()
{
#Override
public void mouseEntered(MouseEvent me)
{
setNormalState(demoButton);
}
#Override
public void mouseExited(MouseEvent me)
{
setExceptionalState(demoButton);
}
});
contentPane.add(demoButton);
frame.setContentPane(contentPane);
frame.setSize(300, 100);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void setExceptionalState(JButton button)
{
button.setBorderPainted(false);
button.setContentAreaFilled(false);
}
private void setNormalState(JButton button)
{
button.setBorderPainted(true);
button.setContentAreaFilled(true);
}
public static void main(String[] args)
{
Runnable runnable = new Runnable()
{
#Override
public void run()
{
new ButtonDemo().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
You would set the default state for the button as:
button.setBorderPainted(false);
Then you would need to use a MouseListener:
on mouseEntered you would use
button.setBorderPainted(true);
and on mouse exited you would use
button.setBorderPainted(false);
You should check out the skinnable "Synth Look and Feel", but also be aware that Swing will be deprecated and replaced by JavaFX in the long run. If you are building a new application, you might want to consider using JavaFX which can be skinned with CSS to achieve the effect you are looking for.
Related
I'm trying to change the color of a JButton when you click on it, but a blue color appears instead of the one I wrote about.
Goal: The goal is that when you click on the button the color change
I did several searches, but each time a blue font appeared.
I tried overide paintComponent, several alternatives such as this.getModel, but nothing works.
My button class:
package com.tralamy.lancherX.display;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TButton extends JButton {
private Color hoverColor = Display.LIGHT_GRAY;
private Color pressColor = Display.LIGHT_DARK;
private Color firstColor;
private Color basic;
private MouseAdapter hoverAdapter = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
basic = firstColor;
TButton.this.setBackground(hoverColor);
}
#Override
public void mouseExited(MouseEvent e) {
TButton.this.setBackground(basic);
}
};
private MouseAdapter pressAdapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
TButton.this.setBackground(pressColor);
super.mousePressed(e);
}
#Override
public void mouseReleased(MouseEvent e) {
TButton.this.setBackground(basic);
super.mouseReleased(e);
}
};
public TButton (String text){
super(text);
init();
}
public TButton (Icon icon){
super(icon);
init();
}
public TButton (){
super();
init();
}
private void init()
{
firstColor = this.getBackground();
setBorder(null);
setBorderPainted(false);
setContentAreaFilled(false);
setOpaque(false);
setFocusPainted(false);
setPressedIcon(new ImageIcon());
}
#Override
public void setBackground(Color bg) {
super.setBackground(bg);
firstColor = bg;
}
public void setHover()
{
this.addMouseListener(hoverAdapter);
}
public void removeHover()
{
this.removeMouseListener(hoverAdapter);
}
public void setPress()
{
this.addMouseListener(pressAdapter);
}
public void removePress()
{
this.removeMouseListener(pressAdapter);
}
public void setHoverColor(Color color)
{
hoverColor = color;
}
public Color getHoverColor()
{
return hoverColor;
}
public Color getPressColor() {
return pressColor;
}
public void setPressColor(Color pressColor) {
this.pressColor = pressColor;
}
}
Main menu panel:
private JPanel menuPanel() {
mp = new JPanel();
setPercentWidth(mp, 25);
mp.setBackground(LIGHT_GRAY);
mp.setLayout(new BorderLayout());
JPanel userSection = new JPanel();
userSection.setLayout(new GridBagLayout());
setPercentHeight(userSection, 5);
userSection.setPreferredSize(new Dimension(userSection.getWidth(), 0));
userSection.setBackground(LIGHT_DARK);
userIconButton.setHorizontalAlignment(SwingConstants.CENTER);
userName.setHorizontalAlignment(SwingConstants.CENTER);
userIconButton.setBorder(new EmptyBorder(0,0,0,10));
userSection.add(userIconButton);
userSection.add(userName);
menuButtons.add(new TButton("Library"));
menuButtons.add(new TButton("Store"));
menuButtons.add(new TButton("Friends"));
menuButtons.add(new TButton("News"));
JPanel menuSection = new JPanel();
menuSection.setLayout(new BoxLayout(menuSection, BoxLayout.Y_AXIS));
menuSection.setOpaque(false);
for (TButton button : menuButtons) {
button.setAlignmentX(TButton.CENTER_ALIGNMENT);
button.setFont(App.setSemiBoldNunito(48));
button.setForeground(SUPER_SUPER_LIGHT_GRAY);
button.setBackground(SUPER_LIGHT_GRAY);
button.setBorder(null);
button.setBorderPainted(true);
button.setContentAreaFilled(true);
button.setOpaque(true);
button.setHoverColor(DARK_GRAY);
button.setHover();
button.setPressColor(LIGHT_DARK);
button.setPress();
TButton marginLabel = new TButton();
marginLabel.setSize(MAIN_MENU_MARGIN, MAIN_MENU_MARGIN);
marginLabel.setMaximumSize(new Dimension(MAIN_MENU_MARGIN, MAIN_MENU_MARGIN));
marginLabel.setMinimumSize(new Dimension(MAIN_MENU_MARGIN, MAIN_MENU_MARGIN));
setPercentWidth(button, 20);
menuSection.add(marginLabel);
menuSection.add(button);
}
mp.add(menuSection);
mp.add(userSection, BorderLayout.SOUTH);
return mp;
}
And then some image:
My bug
And thank you in advance
If you want to change the background of the button with a persistent color when the user clicks on the button, then you can use setContentAreaFilled(false) on it. Then it is required to reset the opaque property to true because according to the docs of setContentAreaFilled: "This function may cause the component's opaque property to change.", for example:
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class MainPersist {
private static void createAndShowGUI() {
final JButton button = new JButton("Click to change color");
button.addActionListener(e -> {
button.setContentAreaFilled(false);
button.setOpaque(true); //Reset the opacity.
button.setBackground(Color.CYAN.darker()); //Set your desired color as the background.
});
final JFrame frame = new JFrame("Button bg on click");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(MainPersist::createAndShowGUI);
}
}
Otherwise, if you want the button to only change its color when clicked and then return back to normal when released, then take a look at this question which is about exactly that. It has no accepted answers yet (it is very recent as of the time this answer itself is posted), but there is at least one/my answer (which suggests to modify the ButtonUI of the button) and there should be more answers coming I guess.
I created custom buttons for maximize, minimize and exit. And everything is working, with one exception, program does not remember in which state window was, before minimization. So my question is, is there a way, program to remember window state before minimization, and restore that state, and not to return only on NORMAL state?
My solution for:
maximize:
JButton btnO = new JButton("O");
btnO.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (frame.getExtendedState() == JFrame.MAXIMIZED_BOTH) {
frame.setExtendedState(JFrame.NORMAL);
} else {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
});
and Minimize:
JButton btnMinimize = new JButton("-");
btnMinimize.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.setExtendedState(JFrame.ICONIFIED);
}
});
You can take the ComponentListener approach and restore its state when the component (in your case, the frame), is resized. Some extra comments inside the code.
Take a look at this example:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class FrameState extends JFrame {
private static final long serialVersionUID = 1965751967944243251L;
private int state = -1; // Variable to keep the last state.
public FrameState() {
super("Nothing :)");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton b = new JButton("-");
b.addActionListener(e -> {
state = getExtendedState(); //Store the state before "-" is pressed
setExtendedState(JFrame.ICONIFIED);
});
JButton o = new JButton("O");
o.addActionListener(e -> {
if (getExtendedState() == JFrame.MAXIMIZED_BOTH) {
setExtendedState(JFrame.NORMAL);
} else {
setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
getContentPane().setLayout(new FlowLayout());
getContentPane().add(o);
getContentPane().add(b);
setSize(new Dimension(300, 300));
setLocationRelativeTo(null);
addComponentListener(new ComponentListener() {
#Override
public void componentShown(ComponentEvent arg0) {
}
#Override
public void componentResized(ComponentEvent arg0) {
if (state != -1) {
setExtendedState(state); //Restore the state.
state = -1; //If it is not back to -1, window won't be resized properly by OS.
}
}
#Override
public void componentMoved(ComponentEvent arg0) {
}
#Override
public void componentHidden(ComponentEvent arg0) {
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
FrameState f = new FrameState();
f.setVisible(true);
});
}
}
You can use this code in JButton to maximize and restore JFrame.
In order to perform this function, you have import JFrame even though the JFrame has been extended in your java class.
if(getExtendedState()==NORMAL)
{
setExtendedState(MAXIMIZED_BOTH);
}
else
{
setExtendedState(NORMAL);
}
I'm fairly new to Java and could do with some help. I trying to make a Timer countdown from a set time to 0. I have this functionality working fine, but I want to add functionality to allow me to stop the Timer as it's counting down.
Here is my code (I'm trying to achieve this using MVC)
This is the control part:
import java.awt.event.*;
import javax.swing.*;
public class StartButton extends JButton implements ActionListener
{
private TimerModel model;
private Timer timer;
private boolean isStarted;
public StartButton(String buttonText, TimerModel model)
{
super(buttonText);
addActionListener(this);
this.model = model;
isStarted = false;
}
public void actionPerformed(ActionEvent evt)
{
if(!isStarted)
{
timer = new Timer(1000, this);
timer.start();
isStarted = true;
}
model.timerCountdown();
}
public void stopTimer()
{
timer.stop();
}
}
I have looked at some other similar issues online and I tried this within the constructor (Note: I didn't use implements ActionListener, and removed the actionPerformed method I had above):
if(buttonText.equals("Start"))
{
addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(!isStarted)
{
timer = new Timer(1000, this);
timer.start();
isStarted = true;
}
model.timerCountdown();
}
});
}
if(buttonText.equals("Stop"))
{
addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timer.stop();
}
});
}
Now this part handles the counting down ok, but when I click the stop button it shows an exception(See stack trace here), and it continues to count down.
I have limited knowledge, but I guess it's something to do with the way I'm trying to stop the Timer.
I would appreciate it if someone could point me in the right direction, or at least explain to me why this happens.
Again, if you're not changing the basic behavior of the JButton itself, such as how it is drawn, but instead are only changing the button's title and behavior when pressed, then don't extend JButton. Instead give each button its own Action, an object from a class that extends from AbstractAction. Consider these guys as similar to ActionListeners on steroids. They have the same abilities as ActionListeners and then some since they can easily change the button's title, whether it is enabled or not, its mnemonic, icon,...
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyTimerGui {
private static final String TITLE = "Flashing Label";
private static final int TIMER_DELAY = 200;
private static final int GAP = 3;
private static final float LABEL_POINTS = 32F;
private JPanel mainPanel = new JPanel();
private JLabel flashyLabel = new JLabel(TITLE, SwingConstants.CENTER);
private Timer timer = new Timer(TIMER_DELAY, new TimerListener());
public MyTimerGui() {
Font font = flashyLabel.getFont();
font = font.deriveFont(LABEL_POINTS);
flashyLabel.setFont(font);
flashyLabel.setOpaque(true);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
buttonPanel.add(new JButton(new StartAction(this, "Start", KeyEvent.VK_S)));
buttonPanel.add(new JButton(new StopAction(this, "Stop", KeyEvent.VK_T)));
buttonPanel.add(new JButton(new ExitAction(this, "Exit", KeyEvent.VK_X)));
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.setLayout(new BorderLayout());
mainPanel.add(flashyLabel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.PAGE_END);
}
public JComponent getMainComponent() {
return mainPanel;
}
public void start() {
timer.start();
}
public void stop() {
timer.stop();
flashyLabel.setForeground(null);
flashyLabel.setBackground(null);
}
public void exit() {
timer.stop();
Window win = SwingUtilities.getWindowAncestor(mainPanel);
win.dispose();
}
private class TimerListener implements ActionListener {
private final Color foreground1 = Color.green;
private final Color background1 = Color.red;
#Override
public void actionPerformed(ActionEvent aEvt) {
Color fg = flashyLabel.getForeground();
if (foreground1.equals(fg)) {
flashyLabel.setForeground(null);
flashyLabel.setBackground(null);
} else {
flashyLabel.setForeground(foreground1);
flashyLabel.setBackground(background1);
}
}
}
private class StartAction extends AbstractAction {
private MyTimerGui myTimerGui;
public StartAction(MyTimerGui myTimerGui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myTimerGui = myTimerGui;
}
#Override
public void actionPerformed(ActionEvent e) {
myTimerGui.start();
}
}
private class StopAction extends AbstractAction {
private MyTimerGui myTimerGui;
public StopAction(MyTimerGui myTimerGui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myTimerGui = myTimerGui;
}
#Override
public void actionPerformed(ActionEvent e) {
myTimerGui.stop();
}
}
private class ExitAction extends AbstractAction {
private MyTimerGui myTimerGui;
public ExitAction(MyTimerGui myTimerGui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.myTimerGui = myTimerGui;
}
#Override
public void actionPerformed(ActionEvent e) {
myTimerGui.exit();
}
}
private static void createAndShowGui() {
MyTimerGui myTimerGui = new MyTimerGui();
JFrame frame = new JFrame("MyTimer");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(myTimerGui.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I agree with the comments that say you shouldn't be extending a JButton. Maybe the logic should be carried out in the main class of your application, the same class that class that deals with the creation and storage of the components.
But I digress. To answer your question, I think there are really two ways to approach this. Either (A) have the actionListener stored within your class as you did in your code or (B) write an actionListener outside of the object itself.
Was the constructor you tried to implement this in the main class constructor?
I think you need something like the following (this, again, is in the main class):
StartButton start = new JButton("Start");
StopButton stop = new JButton("Stop");
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// called when the button is pressed
buttonPressed();
}
});
stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// called when the button is pressed
buttonPressed();
}
});
Then you would write this method in the same class:
private void buttonPressed() {
System.out.println("Button pressed!");
}
I just whipped up a quick test of this, so I can confirm that this method works.
PS: I would also suggest having the button contain a boolean state instead of checking for the text of the button, if you do intend to keep using the StartButton and associated classes.
When I add a JtextField in a JPopupMenu, I can't edit the text when the popup is displayed. Anyone know why?
Here's a code example:
public static void main(String[] args) {
JFrame frame = new JFrame();
JPopupMenu popup = new JPopupMenu();
JTextField field = new JTextField("My text");
popup.insert(field, 0);
popup.setVisible(true);
}
Seems to work alright for me:
Check out this example (right click anywhere on the content pane to make the popup visible:
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class Main {
protected void initUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPopupMenu popup = new JPopupMenu();
final JTextField field = new JTextField(20);
field.setText("My text");
popup.insert(field, 0);
popup.addPopupMenuListener(new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
field.requestFocusInWindow();
field.selectAll();
}
});
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
#Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
((JComponent) frame.getContentPane()).setComponentPopupMenu(popup);
frame.setSize(300, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Main().initUI();
}
});
}
}
to avoiding any speculations
I can't edit the text when the popup is displayed. Anyone know why?
JPopup nested JPopupMenu must has a parent, my code example (reason why is there hardcodes frame.setLocation(150, 100);)
in this form works correctly, JPopup accepting JFrames coordinates
change this code inside Swing Action
from
//popupMenu.setVisible(true);
popupMenu.show(frame, (frame.getHeight() / 4), (frame.getWidth() / 4));
to
popupMenu.setVisible(true);
//popupMenu.show(frame, (frame.getHeight() / 4), (frame.getWidth() / 4));
then PopupMenuListener firing and events, but JMenuItems aren't repainted too
from code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class PopupSample {
private JPopupMenu popupMenu = new JPopupMenu();
private javax.swing.Timer timer = null;
private JFrame frame = new JFrame("Popup Example");
public PopupSample() {
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
System.out.println("Selected: "
+ actionEvent.getActionCommand());
}
};
PopupMenuListener popupMenuListener = new PopupMenuListener() {
#Override
public void popupMenuCanceled(PopupMenuEvent popupMenuEvent) {
System.out.println("Canceled");
}
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent popupMenuEvent) {
System.out.println("Becoming Invisible");
}
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent popupMenuEvent) {
System.out.println("Becoming Visible");
}
};
popupMenu.addPopupMenuListener(popupMenuListener);
JSeparator jSeparator = new JSeparator(JSeparator.VERTICAL);
jSeparator.setPreferredSize(new Dimension(2, 100));
jSeparator.setBackground(Color.red);
popupMenu.add(jSeparator);
JMenuItem cutMenuItem = new JMenuItem("Cut");
cutMenuItem.addActionListener(actionListener);
popupMenu.add(cutMenuItem);
cutMenuItem.setBorder(null);
JMenuItem copyMenuItem = new JMenuItem("Copy");
copyMenuItem.addActionListener(actionListener);
popupMenu.add(copyMenuItem);
JMenuItem pasteMenuItem = new JMenuItem("Paste");
pasteMenuItem.addActionListener(actionListener);
pasteMenuItem.setEnabled(false);
popupMenu.add(pasteMenuItem);
popupMenu.addSeparator();
JMenuItem findMenuItem = new JMenuItem("Find");
findMenuItem.addActionListener(actionListener);
popupMenu.add(findMenuItem);
JTextField text = new JTextField("text");
popupMenu.add(text);
MouseListener mouseListener = new JPopupMenuShower(popupMenu);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addMouseListener(mouseListener);
frame.setLocation(150, 100);
frame.setSize(350, 250);
frame.setVisible(true);
start();
}
private void start() {
timer = new javax.swing.Timer(1000, updateCol());
timer.start();
}
public Action updateCol() {
return new AbstractAction("text load action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
//popupMenu.setVisible(true);
popupMenu.show(frame, (frame.getHeight() / 4), (frame.getWidth() / 4));
}
});
}
};
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
PopupSample popupSample = new PopupSample();
}
});
}
static class JPopupMenuShower extends MouseAdapter {
private JPopupMenu popup;
public JPopupMenuShower(JPopupMenu popup) {
this.popup = popup;
}
private void showIfPopupTrigger(MouseEvent mouseEvent) {
if (popup.isPopupTrigger(mouseEvent)) {
popup.show(mouseEvent.getComponent(), mouseEvent.getX(),
mouseEvent.getY());
}
}
#Override
public void mousePressed(MouseEvent mouseEvent) {
showIfPopupTrigger(mouseEvent);
}
#Override
public void mouseReleased(MouseEvent mouseEvent) {
showIfPopupTrigger(mouseEvent);
}
}
}
I've got an interface with 2 JFormattedTextFields for which I need the values (not just the displayed text) to be identical. Ideally they should both be editable, with a change in one being mirrored in the other.
I started by just sharing a single Document between the two, but quickly ran into the problem that this only links the displayed text, not the underlying value. (Silly me!)
I haven't tried adding reciprocal PropertyChangeListeners for the "value" property because I would expect that to set up an infinite loop of modification.
Am I missing something? Is there some way to do this? Or am I stuck with only allowing users to edit one of the two and only having the value propagate in one direction?
Thank you!
I need the values (not just the displayed text) to be identical.
Ideally they should both be editable, with a change in one being
mirrored in the other.
use DocumentListener,
for example (only the one directions)
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class TextLabelMirror {
private JPanel mainPanel = new JPanel();
private JTextField field = new JTextField(20);
private JTextField field1 = new JTextField(20);
public TextLabelMirror() {
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void insertUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
updateLabel(e);
}
private void updateLabel(DocumentEvent e) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
field1.setText(field.getText());
}
});
}
});
mainPanel.setLayout(new GridLayout(1, 0, 10, 0));
mainPanel.add(field);
mainPanel.add(field1);
}
public JComponent getComponent() {
return mainPanel;
}
private static void createAndShowUI() {
JFrame frame = new JFrame("TextLabelMirror");
frame.getContentPane().add(new TextLabelMirror().getComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
}
You can use a key listener. You simply add a key listener to both fields using the below code. the reason you need the other events is it will throw errors unless you have them in the code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class CreateGrid
{
JFrame thisframe;
JFormattedTextField jFormattedTextField1, jFormattedTextField2;
public CreateGrid()
{
GridLayout thislayout = new GridLayout(0,2);
thisframe = new JFrame();
thisframe.setLayout(thislayout);
jFormattedTextField1 = new JFormattedTextField();
jFormattedTextField2 = new JFormattedTextField();
jFormattedTextField1.addKeyListener(new KeyAdapter()
{
public void keyReleased(KeyEvent e)
{
JFormattedTextField textField = (JFormattedTextField) e.getSource();
String text = textField.getText();
jFormattedTextField2.setText(text);
}
public void keyTyped(KeyEvent e)
{
}
public void keyPressed(KeyEvent e)
{
}
});
jFormattedTextField2.addKeyListener(new KeyAdapter()
{
public void keyReleased(KeyEvent e)
{
JFormattedTextField textField = (JFormattedTextField) e.getSource();
String text = textField.getText();
jFormattedTextField1.setText(text);
}
public void keyTyped(KeyEvent e)
{
}
public void keyPressed(KeyEvent e)
{
}
});
thisframe.add(jFormattedTextField1);
thisframe.add(jFormattedTextField2);
thisframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
thisframe.setVisible(true);
thisframe.pack();
}
public static void main(String args[])
{
new CreateGrid();
}
}
I have tested this out and it works perfectly what ever you type into one field will show up in the other as you type it.