I'm building simple chat application with simple GUI, but a I have a problem assigning Enter key to Send button. Right now it is quite unpractical pressing Alt+Enter.
public void buildInterface() {
//some other components
btnSend = new JButton("Send");
btnExit = new JButton("Exit");
btnSearch=new JButton("Search");
btnSend.setMnemonic(KeyEvent.VK_ENTER);
JPanel box=new JPanel();
add(box, BorderLayout.SOUTH);
box.add(tfInput);
box.add(btnSend);
box.add(btnExit);
box.add(btnSearch);
}
When the button is focused, under most look and feels the Enter will activate the button.
You can, however, assign a button to be the "default" button for the window, which will be activated when the Enter key pressed, so long as the focused component does not consume it.
See How to Use Root Panes and JRootPane#setDefaultButton for more details
Add following code to your Util class
public static void bindKeyStroke(final JButton btn, String ks) {
final ActionListener[] alist = btn.getActionListeners();
if (alist.length != 0) {
AbstractAction action = new AbstractAction(btn.getText(), btn.getIcon()) {
#Override
public void actionPerformed(ActionEvent e) {
for (ActionListener al : alist) {
ActionEvent ae = new ActionEvent(e.getSource(), e.getID(), Action.ACCELERATOR_KEY);
al.actionPerformed(ae);
}
}
};
KeyStroke keyStroke = KeyStroke.getKeyStroke(ks);
btn.setAction(action);
btn.getActionMap().put(Action.ACCELERATOR_KEY, action);
btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, Action.ACCELERATOR_KEY);
}
}
Goto frame, dialog or panel constructor and add after initComponent();
Util.bindKeyStroke(<your button>, "alt enter");
Fix double action, in action performed
if (evt.getActionCommand().equals(Action.ACCELERATOR_KEY)) {
// Your send action here
}
Related
I want to change appearance of Button on JOptionPane.ShowMessageDialog.
I have managed to change Button caption with
UIManager.put("OptionPane.okButtonText", "Text I want");
Now, my next goal is to make Button work same as buttons in rest of my app. That is, when hovering mouse over it, it changes background and font color.
On rest of my buttons I added mouse listener like this one:
//setting change color on hover
private final MouseListener mouseAction = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(163, 184, 204));
rollOver.setForeground(Color.WHITE);
rollOver.setFont(b);
}
};
#Override
public void mouseExited(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(230, 230, 230));
rollOver.setForeground(Color.BLACK);
rollOver.setFont(f);
}
};
};
Previously in code I have Font varibles set:
Font f = new Font("System", Font.PLAIN, 12);
Font b = new Font("System", Font.BOLD, 12);
I could make new dialogs from scratch and implent this behaviour but that would be overkill.
Is there some way to access Button on JOptionPane and add mouse listener
to it?
UIManager.put("OptionPane.okButtonText", "Text I want");
The above will change the text for all "Ok" buttons on all JOptionPanes that you create.
If you want to change the text on an individual button on a specific JOptionPane then
read the section from the Swing tutorial on Customizing Button Text.
Is there some way to access Button on JOptionPane and add mouse listener to it?
When you use the static showXXX(...) methods a modal JDialog is created so you don't have access to the dialog or its components until the dialog is closed which is too late.
So instead you need to manually create the JOptionPane and add it to a JDialog. The basics of doing this can be found by reading the JOptionPane API and looking at the section titled "Direct Use".
Once you have created the JOptionPane (and before you make the dialog visible) you can then search the option pane for the buttons and add a MouseListener to each button. To help you with this you can use the Swing Utils class. It will do a recursive search of the option pane and return the buttons to you in a List. You can then iterate through the List and add the MouseListener.
The basic code using this helper class would be:
JOptionPane optionPane = new JOptionPane(
"Are you sure you want to exit the application",
JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_CANCEL_OPTION);
List<JButton> buttons = SwingUtils.getDescendantsOfType(JButton.class, optionPane, true);
for (JButton button: buttons)
{
System.out.println( button.getText() );
}
If you want to see the same effect inside all OptionPanels, I think the override BasicOptionPaneUI is a good solution
This is a minimal example
public class MyOptionPaneUI extends BasicOptionPaneUI {
#SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
public static ComponentUI createUI(JComponent c) {
return new MyOptionPaneUI();
}
private static final MyMouseListener m = new MyMouseListener();
#Override
public void update(Graphics g, JComponent c) {
super.update(g, c);
}
#Override
protected void installListeners() {
JButton button = (JButton) getButtons()[0];
button.addMouseListener(m);
super.installListeners();
}
#Override
protected void uninstallListeners() {
JButton button = (JButton) getButtons()[0];
button.removeMouseListener(m);
super.uninstallListeners();
}
public static class MyMouseListener extends MouseAdapter{
#Override
public void mouseEntered(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(163, 184, 204));
rollOver.setForeground(Color.WHITE);
}
};
#Override
public void mouseExited(MouseEvent e) {
JButton rollOver = (JButton)e.getSource();
if (rollOver.isEnabled()) {
rollOver.setBackground(new Color(230, 230, 230));
rollOver.setForeground(Color.BLACK);
}
};
}
}
inside your frame your main class you can add this code for load the class inside the UIDefoult
static{
UIManager.put("OptionPaneUI", MyOptionPaneUI.getClass().getCanonicalName());
}
Because getButtons()[0], because I see this code inside the BasicOptionPaneUI
else if (type == JOptionPane.OK_CANCEL_OPTION) {
defaultOptions = new ButtonFactory[2];
defaultOptions[0] = new ButtonFactory(
UIManager.getString("OptionPane.okButtonText",l),
getMnemonic("OptionPane.okButtonMnemonic", l),
(Icon)DefaultLookup.get(optionPane, this,
"OptionPane.okIcon"), minimumWidth);
defaultOptions[1] = new ButtonFactory(
UIManager.getString("OptionPane.cancelButtonText",l),
getMnemonic("OptionPane.cancelButtonMnemonic", l),
(Icon)DefaultLookup.get(optionPane, this,
"OptionPane.cancelIcon"), minimumWidth);
} else {
defaultOptions = new ButtonFactory[1];
defaultOptions[0] = new ButtonFactory(
UIManager.getString("OptionPane.okButtonText",l),
getMnemonic("OptionPane.okButtonMnemonic", l),
(Icon)DefaultLookup.get(optionPane, this,
"OptionPane.okIcon"), minimumWidth);
}
inside the method protected Object[] getButtons()
If you want the effect mouse hover on the button I'm working on this library and have the solution for the mouse over.
If you have a possibility to personalize the DefaoultButton inside the library with this constant
UIManager.put("Button[Default].background", new Color(163, 184, 204));
UIManager.put("Button[Default].foreground", Color.WHITE);
UIManager.put("Button[Default].mouseHoverColor", new Color(230, 230, 230));
ps: this is only information if you need to add the mouse hover inside the you project
I want to remove JButton when user click JButton.
I know that I should use remove method, but it did not work.
How can I do this?
Here is my code:
class Game implements ActionListener {
JFrame gameFrame;
JButton tmpButton;
JLabel tmpLabel1, tmpLabel2, tmpLabel3, tmpLabel4;
public void actionPerformed(ActionEvent e) {
gameFrame.remove(tmpLabel1);
gameFrame.getContentPane().validate();
return;
}
Game(String title) {
gameFrame = new JFrame(title);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setBounds(100, 100, 300, 500);
gameFrame.setResizable(false);
gameFrame.getContentPane().setLayout(null);
tmpLabel4 = new JLabel(new ImageIcon("./images/bomber.jpg"));
tmpLabel4.setSize(200, 200);
tmpLabel4.setLocation(50, 100);
tmpButton = new JButton("Play");
tmpButton.setSize(100, 50);
tmpButton.setLocation(100, 350);
tmpButton.addActionListener(this);
gameFrame.getContentPane().add(tmpLabel4);
gameFrame.getContentPane().add(tmpButton);
gameFrame.setVisible(true);
}
}
If hiding the button instead of removing works for your code then you can use:
public void actionPerformed(ActionEvent event){
tmpButton.setVisible(false);
}
for the button.But the button is just hidden not removed.
The simplest solution might be to...
Attach an ActionListener to the button, see How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listeners for more details
When the ActionListener is clicked, extract the source of the event, JButton buttonThatWasClicked = (JButton)actionEvent.getSource()
Remove it from it's parent...
For example...
Container parent = buttonThatWasClicked.getParent();
parent.remove(buttonThatWasClicked);
parent.revaidate();
parent.repaint();
As some ideas...
First of all in your actionPerformed method you need to check that the button is clicked or not. And if the button is clicked, remove it. Here's how :
if(e.getSource() == tmpButton){
gameFrame.getContentPane().remove(tmpButton);
}
add this to your actionPerformed Method
don't add your button to jframe but add each component you want!
public void actionPerformed(ActionEvent event)
{
//gameFrame.getContentPane().add(tmpButton); -=> "Commented Area"
gameFrame.getContentPane().validate();
}
or hide your button like this
public void actionPerformed(ActionEvent event)
{
tmpButton.setVisible(false);
}
I'm trying to display a name in a textlabel after it is entered in a textfield and pressed a 'Play' button.
The text field and button
private JTextField nameEnter = new JTextField("Enter name here");
private JButton saveName = new JButton("Play");
private JLabel namelabel = new JLabel("Player 1");
To add to board and position
getContentPane().add(nameEnter);
getContentPane().add(saveName);
getContentPane().add(namelabel);
nameEnter.setBounds(80,80+gize*bsize,200,50);
saveName.setBounds(100,100+gsize*bsize,200,50);
namelabel.setBounds(40,40+gsize*bsize,200,50);
This displays fine.
public void UpdateName() {
JButton saveName = new JButton("Play");
saveName.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
final String pName = nameEnter.getText();
namelabel.setText(pName);
}
});
}
I tried to create the above method to store it but this doesn't seem to do anything at all.
Any help appreciated.
Your UpdateName() method is creating its own local JButton saveName button and adding ActionListener to it. Problem is that this button is not the same as button you added to your content pane.
I am not sure why you even need this method. Simplest solution would be placing code responsible for adding this listener
saveName.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
namelabel.setText(nameEnter.getText());
}
});
in initializing method (somewhere after getContentPane().add(saveName);)
The method does:
Create a new button
Attach a listener
On action (click), update the name
To reuse the existing saveName button you already added to your layout,
drop the line that creates a new button, that is:
public void UpdateName() {
saveName.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
final String pName = nameEnter.getText();
namelabel.setText(pName);
}
});
}
I have a program that, put in short, advances upon the pressing of a button. During certain execution phases the button is temporarily deactivated to prevent it from firing in code at the wrong point in time. I have now created some Key Bindings to act as shortcuts for the pressing of the buttons, but need to disable them during the same aforementioned times, or else they will cause my array to be trashed and wiped before I even use it.
Any tips, methods, or Java methods I can use to [very] easily but a hold via disablement?
Have the bound key press the JButton with doClick(). Then when the button needs to be deactivated, call setEnabled(false) on the button.
As an aside, I suppose your button and key binding could share the same action, but I don't know if calling setEnabled(false) on the Action will prevent the key from running the Action's actionPerformed method. Time to test.... Be right back...
Edit: yep you can just have the JButton and the bound key share the same Action that is enabled/disabled:
import java.awt.event.*;
import javax.swing.*;
public class TestBoundAbstractActions {
public static void main(String[] args) {
final MyAction myAction = new MyAction();
final JButton actionButton = new JButton(myAction);
JRadioButton enableRadioButton = new JRadioButton("Enabled", true);
enableRadioButton.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
myAction.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
}
});
JPanel panel = new JPanel();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
String mKey = "m key";
panel.getInputMap(condition).put(KeyStroke.getKeyStroke(KeyEvent.VK_M, 0), mKey);
panel.getActionMap().put(mKey, myAction);
panel.add(new JLabel("Press \"m\" to activate key-bound action"));
panel.add(actionButton);
panel.add(enableRadioButton);
JOptionPane.showMessageDialog(null, panel);
}
}
class MyAction extends AbstractAction {
public MyAction() {
super("My Action");
putValue(MNEMONIC_KEY, KeyEvent.VK_M);
}
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("boo!");
}
}
I am making an applet and as part of my applet, I want this to happen: When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
However, I cannot figure out how to add a new component to the applet after it has started. I made the problem simpler by ignoring the removal part (Which I know how to do) and just adding a simple JLabel instead, but even that won't add!
Here is my code so far:
// imports omitted
public class Class extends Applet implements ActionListener
{
Button okButton;
CheckboxGroup radioGroup;
Checkbox radio1;
Checkbox radio2;
Checkbox radio3;
JLabel j;
public void init()
{
setLayout(new FlowLayout());
okButton = new Button("OK");
j = new JLabel("hello");
radioGroup = new CheckboxGroup();
radio1 = new Checkbox("Red", radioGroup,false);
radio2 = new Checkbox("Blue", radioGroup,true);
radio3 = new Checkbox("Green", radioGroup,false);
add(okButton);
add(radio1);
add(radio2);
add(radio3);
okButton.addActionListener(this);
}
public void repaint(Graphics g)
{
if (radio1.getState()) add(j);
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) repaint();
}
}
What am I doing wrong?
You shouldn't override the repaint method, and certainly not add a component in this method. Just remove the radio buttons from the applet (using its remove method) and add the label in the applet in your actionPerformed method, the same way you add them in the init method.
You might have to call validate after.
Add components and then call validate() of your container. In this case yourApplet.validate(). This will trigger repainting and rearranging of all elements.
you could do something like
JFrame fr= new JFrame(); // global variables
JPanel panelToBeAdded = new JPanel();
JPanel initialPanel = new JPanel();
JTextField fieldToBeAdded = new JTextField();
panelToBeAdded.setPreferredSize( new Dimension(400,400));
initialPanel.setPreferredSize( new Dimension(400,400));
initialPanel.setVisible(true);
fr.add(initialPanel);
fr.setVisible(true);
fr.pack();
public void actionPerformed(ActionEvent ae) {
initialPanel.setVisible(false);
//radiobuttons.setVisible(false);---> hide the radio buttons
panelToBeAddedd.add(fieldToBeAddedd);
panelToBeAddedd.setVisible(true);
fr.add(panelToBeAddedd);
}
public void repaint( Graphics g ) {
// do something
}
What am I doing wrong?
Your repaint(Graphics) method is not the same method you are calling in your actionPerformed method.
Also, repaint is a pretty bad name for a method which is adding a new component.
public void swapComponents()
{
if (radio1.getState()) {
remove(radio1);
remove(radio2);
remove(radio3);
add(j);
validate();
}
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) {
swapComponents();
}
}
When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
Use a CardLayout, as shown here. It is perfect for situations like this.