JTextArea swallowing JButton action listener Java - java

I have an action listener on a JButton and a JTextArea in the button. However when I click the button the text area swallows the event, and nothing happens to the button.
How can I click through the area?
Thank you
Button code
public class CustomFoodItemButton extends JButton{
public JTextArea buttonTitle;
/**
* Public constructor
* #param title
*/
public CustomFoodItemButton(String title) {
//Set button text by using a text area
buttonTitle = new JTextArea();
buttonTitle.setText(title);
buttonTitle.setFont(new Font("Helvetica Neue", Font.PLAIN, 15));
buttonTitle.setEditable(false);
buttonTitle.setWrapStyleWord(true);
buttonTitle.setLineWrap(true);
buttonTitle.setForeground(Color.white);
buttonTitle.setOpaque(false);
//Add the text to the center of the button
this.setLayout(new BorderLayout());
this.add(buttonTitle,BorderLayout.CENTER);
//Set the name to be the title (to track actions easier)
this.setName(title);
//Clear button so as to show image only
this.setOpaque(false);
this.setContentAreaFilled(false);
this.setBorderPainted(false);
//Set not selected
this.setSelected(false);
//Set image
setImage();
}
GUI Class code
private void addFoodItemButtons (JPanel panel){
//Iterate over menu items
for (FoodItem item : menuItems) {
//Create a new button based on the item in the array. Set the title to the food name
CustomFoodItemButton button = new CustomFoodItemButton(item.foodName);
//Add action listener
button.addActionListener(this);
}
}

EDIT For multiline JComponents, check out this answer: https://stackoverflow.com/a/5767825/2221461
It seems to me as if you're overcomplicating things. Why are you using a TextArea on a button if you can't edit the TextArea's text?
There is another constructor for JButtons:
JButton button = new JButton(item.foodname);
This will create a button with the value of 'item.foodname' as text.
You could then simplify your constructor:
public class CustomFoodItemButton extends JButton {
public CustomFoodItemButton(String title) {
super(title);
setName(title);
setOpaque(false);
setContentAreaFilled(false);
setBorderPainted(false);
setSelected(false);
setImage();
}
}
Please let me know if I misinterpreted your question.

Related

How to add mouse listener to JOptionPane button?

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

How to make JButton know on which panel it has been clicked on?

I'm trying to simulate a car renting system on a GUI.
Since I'm not very experienced with Swing components I decided to create a car list using GridBagLayout.
Each row has different panels each having different rental prices and car names.
CarList
The "Details" button is shared through all the panels in the list. I'm looking for a way in which "Details" gets the title and price text from the panel were it was pressed, then saves them inside variables.
so far whenever I press it, it only saves and sends the text from the last panel in the list even if I pressed the first button in the list.
CarDetails
This is the button's Event:
JButton btnNewButton = new JButton("details");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String Car, price;
Car = Name.getText();
price = Price.getText();
Main.add(new CarD(Car,price), "2");
cl.show(Main, "2");
add.setVisible(false);
}
});
EDIT:
Following camickr's example, all that was left was to get the labels from the parent Panel using the location where they are placed within it.
JButton btnNewButton = new JButton("Details");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String Car, price;
JButton button = (JButton)e.getSource();
JPanel panel = (JPanel)button.getParent();
JLabel N = (JLabel)panel.getComponentAt(202, 62);
JLabel P = (JLabel)panel.getComponentAt(202, 24);
Car = N.getText();
price = P.getText();
Main.add(new CarD(Car,price), "2");
cl.show(Main, "2");
add.setVisible(false);
}
});
In the ActionListener of your "Details" button you can get the button from the ActionEvent and the panel from the button:
JButton button = (JButton)e.getSource();
JPanel panel = (JPanel)button.getParent();
In ActionListener try this :
public void actionListener(ActionEvent evt)
{
if(evt.getSource()==b1) // b1 is button variable
{
//code
// this will run if you click on b1 button
}
if(evt.getSource()==b2) // b2 is another button variable
{
//code
// this will run if you click on b2 button
}
}

Swing Actions - Linking Menus and Toolbar

I've been studying Java Swing and I'm working on learning actions.
I can successfully create action objects and use them to link items from a JToolBar to JMenuItems. My problem, is that the constructed actions display both icons and text in the toolbar (should only be the icons).
Check out the following code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MenuDemo{
MenuDemo(){
JFrame jfrm = new JFrame("Complete Menu Demo");
jfrm.setSize(220, 200);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar jmb = new JMenuBar();
/* Make the action object */
ImageIcon setIcon = new ImageIcon("setBP.png");
DebugAction setAct = new DebugAction("Set Breakpoint",
setIcon, KeyEvent.VK_S,
KeyEvent.VK_B, "Set Breakpoint");
/* Make the toolbar */
JButton jbtnSet = new JButton(setAct);
JToolBar jtb = new JToolBar("Breakpoints");
jtb.add(jbtnSet);
/* Make the menu */
JMenu jmDebug = new JMenu("Debug");
JMenuItem jmiSetBP = new JMenuItem(setAct);
jmDebug.add(jmiSetBP);
jmb.add(jmDebug);
jfrm.getContentPane().add(jtb, BorderLayout.NORTH);
jfrm.setJMenuBar(jmb);
jfrm.setVisible(true);
}
class DebugAction extends AbstractAction{
public DebugAction(String name, Icon image, int mnem,
int accel, String tTip){
super(name, image);
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(accel,
InputEvent.CTRL_MASK));
putValue(MNEMONIC_KEY, new Integer(mnem));
putValue(SHORT_DESCRIPTION, tTip);
}
public void actionPerformed(ActionEvent ae){
}
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new MenuDemo();
}
});
}
}
This program yields the following GUI:
I just want the green button in the JToolBar, not text. I think my problem code is in the DebugAction constructor, where I call super(name, image). For the toolbar buttons, I would only want to pass in the image. But for the menu I want both. How can I "turn off" the text for the JToolBar items? Thanks!
How can I "turn off" the text for the JToolBar items?
You turn it off using:
JButton button = new JButton( action );
button.setHideActionText( true );
Or, you can just reset the text on the button:
JButton button = new JButton( action );
button.setText("");
I accepted camickr's answer, but there is a caveat.
For identification purposes, I am grabbing the actionCommand of these buttons. Both setHideActionText(true); and button.setText("") do remove the text, but both produce errors when I try to grab the actionCommand.
To fix this, I explicitly set the actionCommand when I create the action object by adding the additional line in the constructor:
putValue(ACTION_COMMAND_KEY, sometext);
This fixed the errors.

How can I remove JButton from JFrame?

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);
}

MouseEvents for a JTabbedPane Tab component are not bleeding through

I have a JTabbedPane with a custom tab component. That component contains a JLabel (To display the tab title) and a JButton (A close button). When I change the text in the JLabel the JLabel stops receiving mouse events and I can no longer select that tab when I click directly on the label instead if I click around the label then I can select the tab. Any ideas?
A snippet of the code:
class ShellPanelTabComponent extends JPanel implements ActionListener{
private ShellPanel panel;
private JLabel label;
public ShellPanelTabComponent(final ShellPanel panel){
super(new FlowLayout(FlowLayout.LEFT, 0, 0));
this.panel = panel;
setOpaque(false);
label = new JLabel(panel.getTitle());
label.setFocusable(false);
add(label);
label.setBorder(BorderFactory.createEmptyBorder(2,0,0,5));
//now the button
CloseButton closeButton = new CloseButton(panel);
add(closeButton);
closeButton.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {
panel.getShell().removeShellPanel(panel);
}
/**
* #return the label
*/
public JLabel getLabel() {
return label;
}
}
I don't recall seeing such a problem in the TabComponentsDemo, discussed in How to Use Tabbed Panes. You might compare your code with that example as a reference.
Addendum: Re-factoring ButtonTabComponent to include getLabel(), this version of runTest() in TabComponentsDemo adds a button that evinces the desired behavior. In particular, each time the button is pressed, the tabs are redrawn to display the enlarged title.
Update: Modify correct tab component after pane.remove().
public void runTest() {
pane.removeAll();
for (int i = 0; i < tabNumber; i++) {
final int titleIndex = i;
String title = "Tab " + titleIndex;
final JButton button = new JButton("Relabel tab");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int index = pane.indexOfComponent(button);
ButtonTabComponent btc = (ButtonTabComponent)
pane.getTabComponentAt(index);
JLabel label = btc.getLabel();
pane.setTitleAt(index, label.getText() + titleIndex);
label.invalidate();
pane.repaint();
}
});
pane.add(title, button);
initTabComponent(i);
}
tabComponentsItem.setSelected(true);
pane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
scrollLayoutItem.setSelected(false);
this.setPreferredSize(new Dimension(500, 200));
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
I seem to remember a question like this recently although I can't find the posting. I believe the problem is that the "custom component" receives the mouse event so it is not passed on to the tabbed pane. The solution suggested was to use the dispatchEvent(...) method to redispatch the mouse event to the proper tab.
The problem is related to the one that I posted here after I did more digging: Workaround for setToolTipText consuming mouse events?

Categories