Possible to detect double click on a JComboBox item? - java

I have a question for school that states I should change the background color of my JFrame when "an item in the JComboBox is double clicked".
Is this possible using an ItemListener or ActionListener? Or would I need to implement using a MouseListener?
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
public class ColorSelection extends JFrame {
String[] colorNames = {
"Black", "Blue"
};
Color colors[] = {
Color.BLACK, Color.BLUE
};
JComboBox coloursComboBox = new JComboBox(colorNames);
ColorItemListener colorItemListener = new ColorItemListener(this);
public ColorSelection() {
super("My color combobox");
coloursComboBox.addItemListener(colorItemListener);
add(coloursComboBox, BorderLayout.NORTH);
setSize(600, 600);
setVisible(true);
}
public class ColorItemListener implements ItemListener {
ColorSelection colorSelection;
public ColorItemListener(ColorSelection colorSelection) {
this.colorSelection = colorSelection;
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (e.getItem().toString().equals("Black")) {
colorSelection.getContentPane().setBackground(Color.BLACK);
} else {
colorSelection.getContentPane().setBackground(Color.BLUE);
}
}
}
}
public static void main(String[] args) {
new ColorSelection();
}
}

Don't know if it is possible because the popup of the checkbox is closed after a single mouse click.
However, if it is possible, I would suggest you would need to add a MouseListener to the JList that has been added to the popup of the combo box.
After creating the combo box you can add a MouseListener to the JList with code like:
JComboBox comboBox = new JComboBox(...);
Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
if (child instanceof BasicComboPopup)
{
BasicComboPopup popup = (BasicComboPopup)child;
JList list = popup.getList();
list.addMouseListener(...);
}

Related

JPopupMenu only for entries of JList, not all space of the JList

I want to display a JPopupMenu on right click on elements of a JList.
jList.setComponentPopupMenu(...) works fine and displays the context menu (JPopupMenu) if I right click the JList.
But my JList often is larger (taller) than needed for its entries (as the JList is expanded to window height).
And the context menu always appears, even if I click on the blank area of the JList.
I want the context-menu (JPopupMenu) to only show up, if the user right-clicks an entry, not if the user clicks on the blank space below the last list entry.
The menu options are only applicable to a certain entry, not to the JList in its entirety.
I tried setComponentPopupMenu on a custom ListCellRenderer instead of on the list but that doesn't show a menu at all.
How could I get an only-on-entry context menu for my JList?
Use the following method to get the component renderer (renders the items on the list)
https://docs.oracle.com/javase/7/docs/api/javax/swing/JList.html#getCellRenderer()
Then fetch the component. Then attach a mouselistener, and upon right click, perform whatever action you want.
EDIT - Here's an even better way. I wasn't aware of this solution at the time of creating this answer.
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class SOQ_20220416
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Title");
frame.setSize(500, 500);
frame.setLocation(200, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createPanelAndList());
frame.setVisible(true);
}
public static JPanel createPanelAndList()
{
enum Fruit
{
APPLE,
BANANA,
CHERRY,
;
}
JPanel panel = new JPanel();
JList<Fruit> list = new JList<>(Fruit.values());
panel.add(list);
MouseListener mouseListener =
new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int index = list.locationToIndex(e.getPoint());
System.out.println("Right clicked on Item " + index);
}
}
};
list.addMouseListener(mouseListener);
return panel;
}
}
Another option is to override JPopupMenu#show(Component, int, int) method. Since it is possible to get the coordinates of the click, you can control whether the JPopupMenu is shown or hidden by doing super.show(c, x, y); only if those coordinates are in a JList cell.
import java.awt.*;
import javax.swing.*;
public class ListPopupMenuTest {
private Component makeUI() {
String[] model = {"Entry 1", "Entry 2", "Entry 3"};
JList<String> list = new JList<>(model);
list.setComponentPopupMenu(new ListPopupMenu());
return new JScrollPane(list);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new ListPopupMenuTest().makeUI());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class ListPopupMenu extends JPopupMenu {
protected ListPopupMenu() {
super();
add("Item 1").addActionListener(System.out::println);
add("Item 2").addActionListener(System.out::println);
addSeparator();
add("Item 3").addActionListener(System.out::println);
}
#Override public void show(Component c, int x, int y) {
if (c instanceof JList) {
JList<?> list = (JList<?>) c;
Point pt = new Point(x, y);
int idx = list.locationToIndex(pt);
Rectangle r = list.getCellBounds(idx, idx);
if (r != null && r.contains(pt)) { // && !list.isSelectionEmpty()) {
super.show(c, x, y);
}
}
}
}

ComboBox not listening to events

This application shows a frame that contains different JComboBoxes and a JLabel.
An event should be generated when the user clicks the last one(style combobox) and the text in the JLabel should be formatted according to the selected choices in each combobox.
When I click on the Style combobox nothing happens.
There's also another error that I couldn't figure out:(
OUTPUT
package labtasksix;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MyFrame extends JFrame {
String NameO []= {"Select name:","TimesRoman","Serif","SansSerif","Monospaced"};
String ColorO[]={"Select color:","RED","BLUE","GREEN"};
String SizeO []={"Select size:","8","12","16","20"};
String StyleO[]={"Select style:","BOLD","ITALIC","PLAIN"};
JLabel lbl= new JLabel("Text Formatted");
JComboBox Name= new JComboBox(NameO);
JComboBox Colour= new JComboBox(ColorO);
JComboBox Size= new JComboBox(SizeO);
JComboBox Style= new JComboBox(StyleO);
public MyFrame() {
super("Format Frame");
setLayout(new FlowLayout());
add(Name);
add(Size);
add(Style);
add(Colour);
add(lbl);
Name.setMaximumRowCount(3);
Size.setMaximumRowCount(3);
Style.setMaximumRowCount(3);
Colour.setMaximumRowCount(3);
EventHandler handler= new EventHandler();
Style.addItemListener(handler);
}
class EventHandler implements ItemListener{
#Override
public void itemStateChanged(ItemEvent e) {
//When user chooses from the last combobox (style)
if(e.getSource()==Style)
{
if(Name.getSelectedItem().equals("BOLD"))
{
lbl.setFont(new Font((String)Name.getSelectedItem(),Font.BOLD, (int) Size.getSelectedItem()));
}
if(Name.getSelectedItem().equals("ITALIC"))
{
lbl.setFont(new Font((String)Name.getSelectedItem(),Font.ITALIC, (int) Size.getSelectedItem()));
}
if(Name.getSelectedItem().equals("PLAIN"))
{
lbl.setFont(new Font((String)Name.getSelectedItem(),Font.PLAIN, (int) Size.getSelectedItem()));
}
if(Colour.getSelectedItem().equals("RED"))
{
lbl.setForeground(Color.red);
}
if(Colour.getSelectedItem().equals("BLUE"))
{
lbl.setForeground(Color.BLUE);
}
if(Colour.getSelectedItem().equals("GREEN"))
{
lbl.setForeground(Color.GREEN);
}
}
}
}
}
It is listening, but you're checking the ComboBox.getSelectedItem(), which hasn't been updated at the time the event is fired. The item the event relates to is referenced in the event itself; call e.getItem() to retrieve it:
Object item = e.getItem();
if (item.equals("BOLD")) {
lbl.setFont(new Font((String) item, Font.BOLD, /* wrong: (int) Size.getSelectedItem() */ 8));
}
Your size calculation (commented above) is wrong too. Your size selection box holds Strings, so you'll have to parse them (or change the model to ints).
Also... you'll get two events for each change, ItemEvent.DESELECTED first (for the old item), then ItemEvent.SELECTED. You should check for the event you're interested in:
if (e.getSource() == Style && e.getStateChange() == ItemEvent.SELECTED) {

How do I change the background color of a JPanel with a JButton?

I need to have three buttons in my program (the last one is an exit button and it already works) the other two need to change the color of the JPanel background between blue and red.
I need to know what goes in the AtionListeners so that when the buttons are pressed it changes the background color.
This is the class so far :
package myPackageNameGoesHere;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class EventPanel extends JPanel {
private static final long serialVersionUID = 123796234;
private JButton blueButton;
private JButton redButton;
private JButton exitButton;
public EventPanel() {
this.setPreferredSize(new Dimension(200, 300));
this.blueButton = new JButton("Blue");
this.add(this.blueButton);
this.redButton = new JButton("Red");
this.add(this.redButton);
this.exitButton = new JButton("Exit");
this.exitButton.addActionListener(new ExitListener());
this.add(this.exitButton);
}
private class BlueListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent blue) {
// What goes here?????
}
}
private class RedListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent red) {
// What goes here????
}
}
private class ExitListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent exit) {
System.exit(0);
}
}
}
You don't have to declare a listener class for each button, you can just use the same one and add if statement to determine from which button the action come from.
if (e.getSource() == blueButton) {// e is the ActionEvent
blueButton.getParent().setBackground(Color.BLUE);
} else if(e.getSource() == redButton) {
redButton.getParent().setBackground(Color.RED);
}
You could set the background color of the button's parent component
Component component = (Component) event.getSource();
component.getParent().setBackground(Color.BLUE);

Find selected item of a JList and display it in real time

I have a JList, where i am displaying some ID's. I want to capture the ID the user clicked and dis play it on a JLabel.
String selected = jlist.getSelectedItem().toString();
The above code gives me the selected JList value. But this code has to be placed inside a button event, where when i click the button it will get the JList value an assign it to the JLabel.
But, what i want to do is, as soon as the user clicks an item of the JList to update the JLabel in real time. (without having to click buttons to fire an action)
A simple example would be like below using listselectionlistener
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class JListDemo extends JFrame {
public JListDemo() {
setSize(new Dimension(300, 300));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());
final JLabel label = new JLabel("Update");
String[] data = { "one", "two", "three", "four" };
final JList dataList = new JList(data);
dataList.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent arg0) {
if (!arg0.getValueIsAdjusting()) {
label.setText(dataList.getSelectedValue().toString());
}
}
});
add(dataList);
add(label);
setVisible(true);
}
public static void main(String args[]) {
new JListDemo();
}
}
Why don't you put a ListSelectionListener on your JList, and add your above code in to it.
I'm assuming you already know how to create listeners on JButtons, based on your question, so you just need to tweak it to create a ListSelectionListener instead, then assign the listener to your JList using jlist.addListSelectionListener(myListener);
There is a nice tutorial here that should get you started, or refer to the documentation
You should be aiming for something like this...
jlist.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
if (!event.getValueIsAdjusting()){
JList source = (JList)event.getSource();
String selected = source.getSelectedValue().toString();
}
}
});
Use a ListSelectionListener:
JList list = new JList(...);
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
if (!evt.getValueIsAdjusting()) {
// code here
}
}
});

how to stop JPopupMenu show() from visually un-selecting the list item clicked on

Right now when a user right clicks on a selected JList item in my program the resulting JPopupMenu clears the selection (at least visually) until the popup menu is closed. This isn't consistent with the native look and feel of any platform I know of. The item should stay visually selected or have a selected-color border around it. But I can't find anythin in the API about popup menus changing selection appearance. Is there any way I can control this behavior?
How are you implementing your Mouse Listener that shows the popup? I have created a test application to demonstrate the behaviour of List selections and popup menus that I would typically expect. On Windows with Java 1.5/6 this behaves correctly.
Maybe this will help you with your particular problem.
package jlist;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Test extends JPanel implements ListSelectionListener {
private static final String ACTION_FEED = "Feed";
private JList list;
private JPopupMenu menu;
// Initialise a JList and add to JPanel.
public Test() {
super(new BorderLayout());
list = new JList(new Object[]{"Badger", "Ferret", "Stoat", "Weasel"});
initActions();
list.addListSelectionListener(this);
// Add mouse listener
list.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) showPopup(e);
}
#Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) showPopup(e);
}
private void showPopup(MouseEvent e) {
menu.show(e.getComponent(), e.getX(), e.getY());
}
});
add(new JScrollPane(list), BorderLayout.CENTER);
valueChanged(null);
}
// Triggered when List Selection changes. Used to control Actions enabled state.
public void valueChanged(ListSelectionEvent e) {
boolean selected = list.getSelectedValue() != null;
getActionMap().get(ACTION_FEED).setEnabled(selected);
}
// Initialise Actions and Popup Menu
private void initActions() {
menu = new JPopupMenu();
Action feed = new AbstractAction(ACTION_FEED) {
public void actionPerformed(ActionEvent e) {
String value = (String) list.getSelectedValue();
JOptionPane.showMessageDialog(Test.this, "Fed " + value);
}
};
getActionMap().put(ACTION_FEED, feed);
menu.add(feed);
}
public static void main(String [] args) {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(new Test());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}

Categories