I have a simple JTabbedPane that shows text files. Each tab contains a JList wrapped in a JScrollPane I would like to be able to close the individual tabs with a right click, but I can't get this seemingly simple behavior to work.
Here is what I've tried so far:
Adding a listener to the Pane
public class RightClickListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
remove(getComponentAt(e.getPoint()));
}
}
}
Adding to the individual tabs
public class RightClickListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
remove((Component) e.getSource());
}
}
}
I've tried several other variations, and nothing seems to work. Does anyone know why these components aren't being removed? I'd be happy to provide any additional details as necessary.
UPDATE More detail:
public void loadCode(String cFile, String cLine) {
Scanner scan = null;
try {
scan = new Scanner(new File(cFile));
} catch (FileNotFoundException e) { e.printStackTrace();}
DefaultListModel<String> model = new DefaultListModel<String>();
JList<String> list = new JList<String>(model);
while(scan.hasNext()) {
model.addElement(scan.nextLine());
}
JScrollPane newTab = new JScrollPane(list);
tp.add(cFile, newTab);
tp.addMouseListener(new RightClickListener());
}
public class RightClickListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
remove(indexAtLocation(e.getX(), e.getY()));
}
}
}
Right now in your listener, you're using getComponentAt - which will return the component at the point which was clicked (if you're clicking on the tab titles, you're going to get the JTabbedPane back). Since the JTabbedPane was never added to itself, it can't remove that component...
Try using the indexAtLocation method instead - this will check if the x/y coordinates of the click correspond to a tab heading and return that tab's index (see http://docs.oracle.com/javase/7/docs/api/javax/swing/JTabbedPane.html for more details)
public class RightClickListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
tp.remove(tp.indexAtLocation(e.getX(), e.getY()));
}
}
}
Related
I have:
class extended from JFrame;
an list of JTextField's elements - JTextField[] pix.
When clicking on pix[i] - JFrame must iconified and next click at any point of screen must changes exactly that textField (pix[i]) without any influence on another textFields, then frame must normalized and any mouseClicks after that (not on textField) couldn't influenced on that elements.
Clicks outside of JFrame processed with jnativehook library.
That part of code here:
for (int i = 0; i < pix.length; i++){
int tmp = i;
pix[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
setState(Frame.ICONIFIED);
GlobalScreen.addNativeMouseListener(new NativeMouseAdapter(){
public void nativeMouseClicked(NativeMouseEvent e){
pixelChoose(pix[tmp]);
setState(Frame.NORMAL);
}
});
}
});
P.S.: I've tried to use
GlobalScreen.removeNativeMouseListener(new NativeMouseAdapter() {
public void nativeMouseClicked(NativeMouseEvent e) {
}
});
but don't actually know how to use this correctly.
P.S.[2]: if you have another solution of that question, you are welcome to type it into the answers - it will be great :>
EDIT!
I was buisy and now I'm here with solution:
NativeMouseAdapter adapter = new NativeMouseAdapter(){
public void nativeMouseClicked(NativeMouseEvent e){
pixelChoose(pix[tmp]);
setState(Frame.NORMAL);
GlobalScreen.removeNativeMouseListener(this);
}
};
MouseListener listener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
setState(Frame.ICONIFIED);
GlobalScreen.addNativeMouseListener(adapter);
}
};
pix[i].addMouseListener(listener);
Add (after the setState) code to remove the MouseListener.
setState(Frame.NORMAL);
for (int i = 0; i < pix.length; i++){
pix[i].removeMouseListener(MouseAdapter::this);
}
pix must be effectively final, and I hope MouseAdapter::this works for the anonymous MouseListener.
MouseAdapter::this fails
Instead of
pix[i].addMouseListener(new MouseAdapter() {
hold the MouseListener in its own variable:
MouseListener cat = new MouseAdapter() { ... };
pix[i].addMouseListener(cat);
And later do in the inner callback do
pix[i].removeMouseListener(cat);
In the code where you create the mouse listener, you need to keep a reference.
NativeMouseAdapter adapter = new NativeMouseAdapter(){
public void nativeMouseClicked(NativeMouseEvent e){
pixelChoose(pix[tmp]);
setState(Frame.NORMAL);
}
}
GlobalScreen.addNativeMouseListener(adapter);
Then when you want to remove it, you use that reference.
GlobalScreen.removeNativeMouseListener(adapter);
NativeMouseAdapter adapter = new NativeMouseAdapter(){
public void nativeMouseClicked(NativeMouseEvent e){
pixelChoose(pix[tmp]);
setState(Frame.NORMAL);
GlobalScreen.removeNativeMouseListener(this);
}
};
MouseListener listener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
setState(Frame.ICONIFIED);
GlobalScreen.addNativeMouseListener(adapter);
}
};
pix[i].addMouseListener(listener);
i am constructing a word processor program as an assignment for my Java class in school and i am having a really hard time getting the popupmenu to work when i right click on my text area. I have already constructed the popup menu and have my textarea listening to my popuplistener and i have overridden the mouse pressed and mouse released functions with
class popupframe extends JFrame{
JMenuItem copy;
JMenuItem paste;
JTextArea textarea = new JTextArea();
JPopupMenu pop;
popupframe(){
Container cpane = getContentPane();
setSize(300 , 300);
setLocation(300, 300);
setTitle("Test");
JPopupMenu pop = new JPopupMenu();
copy = new JMenuItem("copy");
paste = new JMenuItem("paste");
textarea = new JTextArea("something goes here", 5, 5);
pop.add(copy);
pop.add(paste);
PopupListener popuplistener = new PopupListener();
textarea.addMouseListener(popuplistener);
}
class PopupListener extends MouseAdapter{
public void MousePressed(MouseEvent e){
popit(e);
}
public void MouseReleased(MouseEvent e){
popit(e);
}
private void popit(MouseEvent e){
if(e.isPopupTrigger()){
pop.show(e.getComponent(), e.getX(), e.getY());
}
}
}
}
I cannot see why it is not working but perhaps i am missing something crucial, please help!! much appreciated
Add the #Override annotation to the methods you think your are overriding...
class PopupListener extends MouseAdapter {
#Override
public void MousePressed(MouseEvent e) {
System.out.println("Pressed");
popit(e);
}
#Override
public void MouseReleased(MouseEvent e) {
System.out.println("Pressed");
popit(e);
}
You will now find that this fails to compile, but why? Because Java is case sensitive, and by convention, method names start with a lower case character
You'll find that something like...
class PopupListener extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
popit(e);
}
#Override
public void mouseReleased(MouseEvent e) {
popit(e);
}
#Override
public void mouseClicked(MouseEvent e) {
popit(e);
}
private void popit(MouseEvent e) {
if (e.isPopupTrigger()) {
pop.show(e.getComponent(), e.getX(), e.getY());
}
}
}
will work better. But having said that, you'll generally find
textarea.setComponentPopupMenu(pop);
significantly easier and less error prone (and it won't cause a NullPointerException like your example code will.
I have a big panel with 6 JScrollPane inside, each JScrollPane contain a JList.
I am trying to add a MouseListener event to every single JList on the panel, how can i get access to it? to better understand, this is my code:
private void agregarDobleClick() {
for (Component c : jPanel1.getComponents()) {
c.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
JList list = (JList) evt.getSource();
if (evt.getClickCount() == 2) {
Rectangle r = list.getCellBounds(0, list.getLastVisibleIndex());
if (r != null && r.contains(evt.getPoint())) {
modCitaPOPUP modcita = new modCitaPOPUP((Cita) list.getSelectedValue());
modcita.setVisible(true);
}
}
}
});
}
}
when i run this, it add the mouseListener to the JScrollPane, and when i double-click on a JList item, nothing happen because the mouseListener event isnt there.
thanks.
It "looks" like, from your description, you're adding the MouseListener to the JScrollPane and not the JList.
The simple solution would be to make a speciality MouseListener...
public class ListMouseListener extends MouseAdapter {
private JList list;
public ListMouseListener (JList list) {
this.list = list;
}
#Override
public void mouseClicked(MouseEvent evt) {
// Know you're self out with the list instance variable...
}
}
And apply it to each JList when you create it...
JList list = new JList();
list.addMouseListener(new ListMouseListener(list));
Now, if you're worried that they might be inefficient or consuming to much memory (which based on your example, you're not), you could instead, create a generic MouseListener which used the event source to determine who triggered it...
public class ListMouseListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof JList) {
JList list = (JList)source;
}
}
}
Then create a single instance and apply it all your instances of JList...
ListMouseListener singleInstance = new ListMouseListener();
//...
JList list = new JList();
list.addMouseListener(singleInstance);
for(int k=0;k< dtm.getRowCount();k++) //dtm is object of default table model
{
if(String.valueOf(dtm.getValueAt(k,1)).equalsIgnoreCase("Today") && check==0 )
{
cnt++;
JLabel jp=new JLabel();
panel.add(jp);
panel.setLayout(null);
if(cnt<=12)
{
jp.setBounds(j,500,100,100);
j=j+115;
jp.addMouseListener(this);
}
else
{
j=j-115;
jp.setBounds(j,400,100,100);
}
String b="<html><body text=#FDFA0B>"+String.valueOf(dtm.getValueAt(k,0))+"'s Birthday";
jp.setText(b);
jp.setFont(new java.awt.Font("comicbd",Font.ITALIC+Font.BOLD, 14));
}
}
It will not work mouselister only apply for last placed Label...
I want to apply mouse listener for all label how can I do that ..
please help me ....
Without SSCCE I can tell you that you're adding listener on 3 conditions:
String.valueOf(dtm.getValueAt(k,1)).equalsIgnoreCase("Today")
check == 0
and if(cnt<=12)
Other JLabels (that don't pass these conditions) haven't assigned your listener.
Make sure that you're clicking correct labels.
Or move jp.addMouseListener(this); just after JLabel creation (if you want to add listener to all your JLabels).
You certainly can add the same MouseListener to multiple components - here's an example in it's simplest form:
MouseListener ml = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {System.out.println("Released!");}
#Override
public void mousePressed(MouseEvent e) {System.out.println("Pressed!");}
#Override
public void mouseExited(MouseEvent e) {System.out.println("Exited!");}
#Override
public void mouseEntered(MouseEvent e) {System.out.println("Entered!");}
#Override
public void mouseClicked(MouseEvent e) {System.out.println("Clicked!");}
};
JLabel j1 = new JLabel("Label1");
j1.addMouseListener(ml);
JLabel j2 = new JLabel("Label2");
j2.addMouseListener(ml);
BUT according to your code, you're messing with a JTable - and JTable's act differently than you're thinking. The labels you're trying to edit are actually part of a TableCellEditor. The JTable uses the single TableCellEditor (read: single JLabel) to display every cell in the JTable. This is why you're only seeing the Listener applied to the last cell (because that's the only the last cell has a full component any more - the rest are just ghosts of where the component was applied before).
The good news is you can add a MouseListener to the JTable, and obtain information from there:
final JTable table = new JTable();
MouseListener ml = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {
System.out.println(table.getModel().getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
#Override
public void mousePressed(MouseEvent e) {
System.out.println(table.getModel().getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
#Override
public void mouseExited(MouseEvent e) {
System.out.println(table.getModel().getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
#Override
public void mouseEntered(MouseEvent e) {
System.out.println(table.getModel().getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
#Override
public void mouseClicked(MouseEvent e) {
System.out.println(table.getModel().getValueAt(table.getSelectedRow(), table.getSelectedColumn()));
}
};
table.addMouseListener(ml);
One Option is to add another inner class:
class MListener extends MouseAdapter{
public void mouseReleased(MouseEvent e) {}
//other mouse evetns
}
then rather then:
jp.addmousListener(this);
do:
jp.addMouseListener(new MListener());
I have two JLists, jltCategories and jltSubcategories, belonging to the same JPanel. Double clicking on the jltCategories causes the jltSubcategories to be populated with the corresponding subcategories, and jltSubcategories is removed from the JPanel, added back and revalidated.
Double clicking the jltSubcategories AFTER it has been removed/added back does not fire anything. Yet, If I open the program and double click on the jltSubcategories, it will fire its mouse event: It will fire if it hasn't been removed/added back, but it will not fire if it has been removed/added back. Same for jltCategories: if I cause it to be removed/added, it will stop firing. Why is this so? Thank you!
jltCategories.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
jbtNavigate.doClick();
}
}
});
jltSubcategories.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
jbtLoad.doClick();
}
}
});
jbtNavigate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String catName = jltCategories.getSelectedValue();
try {
jpLists.remove(jltSubcategories);
jltSubcategories = new JList<String>(SQL.populateSubcategories(catName));
jpLists.add(jltSubcategories);
jpLists.revalidate();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
});
jbtLoad.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Testing Testing 213");
}
});
It is not enough to revalidate() the view; you must also let the model notify the view that new data is available.
DefaultListModel model = (DefaultListModel ) jltSubcategories.getModel();
model.fireContentsChanged(0, model.getSize());
If this is ineffective, please edit your question to include an sscce that exhibits the problem you describe.
Addendum: It's not clear why you use a MouseListener to effect the update; use a ListSelectionListener, shown here.