I have to handle an event in a combobox when the user click the item (not when the combobox change the state).
I have four combobox:
(1Combo: Parent category)
(2 Combo: The sons of the category 1)
(3 Combo: the sons of the category 2)
(4 combo: the sons of the category 3)
Each one calls the list to add the items for the other one (the sons of the category choosed).
But my problem is that I have an itemstatechange event and I want to know if the item has been clicked NOT if the combo changes state.
public void itemStateChanged(ItemEvent e) {
if (e.getSource()==jComboBoxCategorias1) {
handleEventCombo1();
}
if (e.getSource()==jComboBoxCategorias2) {
handleEventCombo2();
}
if (e.getSource()==jComboBoxCategorias3) {
handleEventCombo3();
}
if (e.getSource()==jComboBoxCategorias4) {
handleEventCombo4();
}
}
You can add a mouse listener to the combobox and implement the mouseClicked method.
comboBox.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(comboBox.getSelectedItem());
}
});
Don't forget that comboBox is actually a container. So if you really want to have all the mouse events you should add the listener to all the components it contains.
public void addMouseListener(final MouseListener mouseListener) {
this.comboBox.addMouseListener(mouseListener);
final Component[] components = this.comboBox.getComponents();
for(final Component component : components) {
component.addMouseListener(mouseListener);
}
this.comboBox.getEditor().getEditorComponent().addMouseListener(mouseListener);
}
Please visit swing mouse listeners being intercepted by child components for more details.
Related
I am trying to call a function when a user clicks (with the mouse) on an item in a JComboBox; however, I don't want this event fired for any keyboard events - I only want this fired for a click on a particular cell of the dropdown (I know about addActionListener and addItemListener, but these are fired for more events than I want).
EDIT: I should have specified that mouseClicked doesn't work either - no events seem to be fired (however, they were at one point but when that happened, they fired for clicks on the text field as well), but I thought that was assumed from the title.
I have also tried the solution given here (also doesn't work): Editable JCombobox mouseclicked event not working
EDIT2: I tried the following, but still no output on click:
try {
Field popupInBasicComboBoxUI = BasicComboBoxUI.class.getDeclaredField("popup");
popupInBasicComboBoxUI.setAccessible(true);
BasicComboPopup popup = (BasicComboPopup)popupInBasicComboBoxUI.get(attachedCB.getUI());
Field scrollerInBasicComboPopup = BasicComboPopup.class.getDeclaredField("scroller");
scrollerInBasicComboPopup.setAccessible(true);
JScrollPane scroller = (JScrollPane)scrollerInBasicComboPopup.get(popup);
scroller.getViewport().getView().addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
System.out.println("nope");
}
});
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
You missed adding it to the scrollPane's viewport view in the link I posted in the comments.
Field scrollerInBasicComboPopup = BasicComboPopup.class.getDeclaredField("scroller");
scrollerInBasicComboPopup.setAccessible(true);
JScrollPane scroller = (JScrollPane) scrollerInBasicComboPopup.get(popup);
scroller.getViewport().getView().addMouseListener(listener);
Hope this helps,
jComboBox.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jComboBoxMouseClicked(evt);//your logic here
}
});
You should use java.awt.event.ActionEvent, which is (quoted from javadoc) a
semantic event which indicates that a component-defined action
occurred. This high-level event is generated by a component (such as a
Button) when the component-specific action occurs (such as being
pressed)...
like this:
jComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
javax.swing.JComboBox source = (javax.swing.JComboBox)evt.getSource();
// use getSelectedIndex to know the item if needed
labelTextField.setText(source.getSelectedItem().toString());
}
});
Note getSelectedItem and getSelectedIndex and getSelectedObjects methods : this allows you to know which item has been selected and process only the items you want
I have an editable JCombobox . I have already done whats required for loading data from database.
After loading the data, I add some extra data like .next. or - for a specific reason. .next. or - which only work when they are highlighted in the popup menu.I have designed their working already.
However I don't want to view/selected .next. or - in JTextField of JComboBox.
For this purpose, I override JCombobox,
searchCBX.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED
&& (".next.".equals(e.getItem()) || "-".equals(e.getItem()))) {
searchTF.setText("");
}
}
});
Here, searchCBX is my required combobox and searchTF is my textfield of searchCBX. It works fine when I try to select .next. or - by scrolling the JPopupmenu from keyboard, searchTF automatically goes to empty.
Now the problem arises when I try to select .next. or - by mouse click from visible popup menu. It gets selected automatically.
I am trying to override mouseListener but it's not working.
searchCBX.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
if ((".next.".equals(searchTF.getText()) || "-".equals(searchTF.getText()))) {
searchTF.setText("");
}
}
});
So how can I remove the selected data from searchTF after mouse click of a jComboBox popup menu where value is .next. or - . Any help would be really appreciated.
To my understand you need to remove the text of the searchTF once you select the .next. or - from the dropdown of the searchCBX. If its the case , you dont need to worry about a MouseListener here. Just the ItemStageChage event can do the work.
Here is a required part of the code :
public class Example extends JFrame {
private JComboBox searchCBX;
private JTextField searchTF;
/**
* Creates new form Example
*/
public Example() {
initComponents();
}
private void initComponents() {
searchCBX = new JComboBox();
searchTF = new JTextField();
searchCBX.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
searchCBXItemStateChanged(evt);
}
});
}
private void searchCBXItemStateChanged(ItemEvent evt) {
if (evt.getStateChange() == ItemEvent.SELECTED
&& (".next.".equals(evt.getItem()) || "-".equals(evt.getItem()))) {
searchTF.setText("");
} else {
searchTF.setText(searchCBX.getSelectedItem().toString());
}
}
}
I'm making a simple menu to delete items on a tree. However, after deleting the items, the tree does not receive a selection event, therefore, the code in the listener does not execute (the listener, in the full code, updates a part of the UI).
I have simplified the code below, leaving out details. It is something like this:
tree.addListener (SWT.Selection, new Listener(){
public void handleEvent(Event e) {
(....)
}
}
I also tried this:
tree.addSelectionListener (new SelectionListener(){
public void widgetDefaultSelected(SelectionEvent e){
(...)
}
public void widgetSelected(SelectionEvent e) {
(...)
}
}
On my menu action (delete selection), there is this:
TreeItem [] selected = tree.getSelection();
tree.deselectAll();
if (selected.length > 0)
{
for( TreeItem i : selected){
i.dispose();
}
}
After deleting the selection, my selection listener does not fire. It does fire if I deselect all itens using the ctrl+click combination.
What should I do? Is there a way to fire the SWT.Selection event to the tree after deleting the itens or should I isolate the code inside the listener to call it again? Shouldn't the tree.deselectAll() fire a Selection event?
You can send a selection event programmatically with:
Event event = new Event();
event.widget = tree;
event.display = tree.getDisplay();
event.type = SWT.Selection;
tree.notifyListeners(SWT.Selection, event);
Have same situation and found
this link mentioning, that programmatically setSelection may never send this event due to design, so always send it (if needed) programmatically after setting too
I have a situation where I have a popup menu created when a JTable is right clicked on. Standard way of creating the popup menu:
aJTable.setComponentPopupMenu(rightClickMenu);
Now afterwards in the action that gets registered, I am unable to find out which cell was right clicked on to get that popup menu to appear.
rightClickMenuItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Work out what cell was right clicked to generate the menu
}
});
Any ideas on how you do this?
Astonishing fact: with a componentPopupMenu installed, a mouseListener never sees the mouseEvent that is the popupTrigger (reason is that showing the componentPopup is handled globally by a AWTEventListener installed by BasicLookAndFeel, and that listener consumes the event).
The only place which sees the mousePosition of that trigger is the getPopupLocation(MouseEvent), so the only reliable way to get hold of it (for doing location dependent config/actions) is #Mad's suggestion to override that method and store the value somewhere for later use.
The snippet below uses a clientProperty as storage location:
final JTable table = new JTable(new AncientSwingTeam()) {
#Override
public Point getPopupLocation(MouseEvent event) {
setPopupTriggerLocation(event);
return super.getPopupLocation(event);
}
protected void setPopupTriggerLocation(MouseEvent event) {
putClientProperty("popupTriggerLocation",
event != null ? event.getPoint() : null);
}
};
JPopupMenu popup = new JPopupMenu();
Action action = new AbstractAction("show trigger location") {
#Override
public void actionPerformed(ActionEvent e) {
JPopupMenu parent = (JPopupMenu) SwingUtilities.getAncestorOfClass(
JPopupMenu.class, (Component) e.getSource());
JTable invoker = (JTable) parent.getInvoker();
Point p = (Point) invoker.getClientProperty("popupTriggerLocation");
String output = p != null ? "row/col: "
+ invoker.rowAtPoint(p) + "/" + invoker.columnAtPoint(p) : null;
System.out.println(output);
}
};
popup.add(action);
popup.add("dummy2");
table.setComponentPopupMenu(popup);
#MadProgrammer's suggestion of getPopupLocation looked promising, but I couldn't work out how to get the information across between the table and the actionEvent...
I got around this by making sure that the row was selected when you rightclicked on it -> since the popup menu prevents the selection of the row, you can add in a mouse listener that makes sure the row gets selected no matter what click (left or right) is pressed.
aTable.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
int r = aTable.rowAtPoint(e.getPoint());
if (r >= 0 && r < clt.getRowCount()) {
aTable.setRowSelectionInterval(r, r);
} else {
aTable.clearSelection();
}
}
});
This means that in the rightClickMenuItem's action listener, you can grab the table's selected cell / row
rightClickMenuItem.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
aTable.get details about the selected one....
}
});
Too easy! Thanks everyone for the help.
JTable has methods
int row = rowAtPoint(p);
int col = columnAtPoint(p);
So pass the MouseEvent's point and use the values
Add a MouseListener and store the last right click point somewhere.
I want to show a small popup menu when you right-click a tab, now this is working fine but when you right click it also selects that tab which is unwanted.
So my idea was to make a new class, extend JTabbedPane and recode those mouse events. Problem is that I have no idea where to start, I was browsing its source but I can't find what part is handeling the mouseEvents.
Tabs.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent me) {
if(me.getButton()==3){
int tabNr = ((TabbedPaneUI)Tabs.getUI()).tabForCoordinate(Tabs, me.getX(), me.getY());
Component clickedTab = EventsConfig.window.MainTabs.getComponentAt(tabNr);
newMenu(clickedTab, me.getX(), me.getY());
}
}
});
Beware: dirty hack ahead! The only reason I recommend it, is that I consider the behaviour (select on right press) a bug in the BasicTabbedPaneUI's Handler.
The basic idea is to grab the listener installed by the ui, remove it, wrap into a custom listener which delegates everything except a right pressed to the original and add that to the pane:
private void installMouseListenerWrapper(JComponent tabbedPane) {
MouseListener handler = findUIMouseListener(tabbedPane);
tabbedPane.removeMouseListener(handler);
tabbedPane.addMouseListener(new MouseListenerWrapper(handler));
}
private MouseListener findUIMouseListener(JComponent tabbedPane) {
MouseListener[] listeners = tabbedPane.getMouseListeners();
for (MouseListener l : listeners) {
if (l.getClass().getName().contains("$Handler")) {
return l;
}
}
return null;
}
public static class MouseListenerWrapper implements MouseListener {
private MouseListener delegate;
public MouseListenerWrapper(MouseListener delegate) {
this.delegate = delegate;
}
#Override
public void mouseClicked(MouseEvent e) {
delegate.mouseClicked(e);
}
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) return;
delegate.mousePressed(e);
}
#Override
public void mouseReleased(MouseEvent e) {
delegate.mouseReleased(e);
}
#Override
public void mouseEntered(MouseEvent e) {
delegate.mouseEntered(e);
}
#Override
public void mouseExited(MouseEvent e) {
delegate.mouseExited(e);
}
}
then you have to add JPopupMenu (or JToolTip on MouseHoverOver ) to the JTabbedPane
A possible workaround is to set your custom tab component for each tab - see JTabbedPane#setTabComponentAt(...). Add a mouse handler to your custom tab component and redispatch left click events to the tabbedPane as described at http://www.jyloo.com/news/?pubId=1315817317000.
The custom tab component can be a simple JLabel (used for the tab title) or a container for multiple components. Depending on your requirements you can e.g. add an arrow button which will open a popup menu by left clicking the related button.
This article will helpful for removing unwanted tab selection when you click right mouse button.
Stop right click Event on JTabbedPane
I liked to add more about removing Mouse Listeners.
Try to override the method rather than removing it. It's better for future code updates.
The problem is BasicTabbedPaneUI's have inner class called Handler. That handler class override Mouse Listener.
To stop right click tab selection and show pop up menu; we need to override this method in BasicTabbedPaneUI,
protected MouseListener createMouseListener() {
return getHandler();
}
To get better look and feel we should override SynthTabbedPaneUI class.
SynthTabbedPaneUI is extends BasicTabbedPaneUI.
So our inner class is like this,
private class SynthTabbedPaneUIWrapper extends SynthTabbedPaneUI
{
private MouseAdapter menuAdapter;
private MouseAdapter getMenuAdapter()
{
if (menuAdapter == null)
{
menuAdapter =
new MouseAdapter()
{
#Override
public void mouseReleased(final MouseEvent e)
{
//implement to stop right click tab selection
//implement to show pop up menu
}
};
}
}
#Override
protected MouseListener createMouseListener()
{
return getMenuAdapter();
}
}
After that we can set our custom UI object into TabbedPane.
tabbedPane.setUI(new SynthTabbedPaneUIWrapper());