i am trying to set a different background color for different nodes of a JTree . The user can right click on a node, push a button and choose a color from a JColorChooser . I made a custom treecellrenderer(Chromatizer()) and overriden the method .getTreeCellRendererComponent() in order to set the BackgroundNonSelectionColor with the chosen color. What happens is that even though this happens beggining from current selection , it expands if selections changes . Is there any way to change the color of just the selected node?
public class TreeExample extends JFrame
{
private JTree tree;
private JButton btn;
public TreeExample()
{
btn = new JButton ("Choose a color");
Chromatizer chroma = new Chromatizer();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Letters");
DefaultMutableTreeNode parent1 = new DefaultMutableTreeNode("uppercase");
DefaultMutableTreeNode parent2 = new DefaultMutableTreeNode("lowercase");
DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("A");
DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("B");
DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("C");
DefaultMutableTreeNode child4 = new DefaultMutableTreeNode("a");
DefaultMutableTreeNode child5 = new DefaultMutableTreeNode("b");
DefaultMutableTreeNode child6 = new DefaultMutableTreeNode("c");
root.add(parent1);
root.add(parent2);
parent1.add(child1);
parent1.add(child2);
parent1.add(child3);
parent2.add(child4);
parent2.add(child5);
parent2.add(child6);
tree = new JTree(root);
ImageIcon imageIcon = new ImageIcon(TreeExample.class.getResource("./leaf.jpg"));
chroma.setLeafIcon(imageIcon);
tree.setCellRenderer(chroma);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
add(new JScrollPane(tree)
);
/*
Start of btn
*/
btn.addActionListener(
new ActionListener(){
private DefaultMutableTreeNode dmt;
#Override
public void actionPerformed(ActionEvent event){
dmt = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
Color clr = null;
clr =JColorChooser.showDialog(null, "Επιλογή χρώματος", clr);
chroma.getTreeCellRendererComponent(tree, dmt, rootPaneCheckingEnabled, rootPaneCheckingEnabled, rootPaneCheckingEnabled, ERROR, rootPaneCheckingEnabled, clr);
( (DefaultTreeModel) tree.getModel()).nodeChanged(dmt);
}
);
/*end of btn */
/*right mouse click menu*/
tree.addMouseListener(new MouseAdapter ()
{
public void mousePressed(MouseEvent e)
{
if ( SwingUtilities.isRightMouseButton ( e ) )
{
int row = tree.getClosestRowForLocation(e.getX(), e.getY());
tree.setSelectionRow(row);
TreePath path = tree.getPathForLocation ( e.getX (), e.getY () );
Rectangle pathBounds = tree.getUI ().getPathBounds ( tree, path );
if ( pathBounds != null && pathBounds.contains ( e.getX (), e.getY () ) )
{
JPopupMenu menu = new JPopupMenu ();
menu.add (btn) ;
menu.show ( tree, pathBounds.x, pathBounds.y + pathBounds.height );
}
}
}
} );
/*end of menu*/
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("JTree Example");
this.setSize(200, 200);
this.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TreeExample();
}
});
}
}
And the Custom renderer
public class Chromatizer extends DefaultTreeCellRenderer {
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus,
Color color)
{
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
if(node.getParent() != null){
super.setBackgroundNonSelectionColor(color);
super.setBackgroundSelectionColor(color);
}
return this;
}
};
Images(couldn't upload due to being a new member ! : )
First Screen[1] http://i.stack.imgur.com/lNrKA.jpg
After right-clicking and pushing button "Choose a color"[2] http://i.stack.imgur.com/XICRp.jpg
Result after clicking ok[3]
http://i.stack.imgur.com/l48ft.jpg
If I left-click there(arrow) then tree nodes are filled with color[4]
http://i.stack.imgur.com/1CEkS.jpg
maybe you can use this
DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
//do something with one of this parameter
//tree, value, selected, expanded, leaf, row, hasFocus
Component returnValue = defaultRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
return returnValue;
Related
I'm doing a project for school and my goal here is to design a gallery on Swing. One of the features is the possibility to add new images to my gallery and display the new picture. I created a card where you can add your picture by browsing the file explorer on your computer and then it will copy and add the file to the folder of the app. For the moment this part works fine, but when I go back to my GalleryPage CardLayout the image is not displayed (because I don't know how to add it directly). What I'm trying to do is add this new image to the bottomPanel of my GalleryPage java class from newImg [JLabel] on my NewImage java class. Is there a way to do that? I've been browsing the Internet to find an answer but I can't find a solution.
Here is my code:
Gallery.java
public class Gallery extends JPanel {
private GalleryPage panelGalleryPage;
private NewImage newImage;
protected static CardLayout cardGal;
public Gallery() {
super();
setLayout(new CardLayout());
cardGal = (CardLayout) this.getLayout();
panelGalleryPage = new GalleryPage();
newImage = new NewImage();
add(panelGalleryPage, "GalleryPage");
add(newImage, "NewImage");
}
}
GalleryPage.java
public class GalleryPage extends JPanel {
// preparing my grid of images by sorting the filepath of each image.
File directory = new File("oop_2022/src/main/java/com/phone/common/png/Galery_images");
int fileCount = directory.list().length;
private JButton addImg, delImg;
private JLabel title;
private JLabel[] cache = new JLabel[fileCount];
private ImageIcon[] imgGrid = new ImageIcon[fileCount];
private ImageIcon imgTitle, imgAdd, imgDel;
private JSplitPane splitPanel;
private JPanel bottomPanel, topPanel;
private List<String> results;
public GalleryPage() {
super();
setBackground(PowerOn.userInterface.DARK_GREY);
initComponents();
}
public void initComponents() {
// create a split pane
splitPanel = new JSplitPane();
topPanel = new JPanel(); // top component
bottomPanel = new JPanel(); // bottom component
// configure splitPanel
splitPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
splitPanel.setDividerLocation(100);
splitPanel.setDividerSize(0);
splitPanel.setTopComponent(topPanel);
splitPanel.setBottomComponent(bottomPanel);
// create title
imgTitle = new ImageIcon("oop_2022/src/main/java/com/phone/common/png/images.png");
imgTitle.setImage(imgTitle.getImage().getScaledInstance(80, 80, Image.SCALE_DEFAULT));
title = new JLabel(imgTitle);
// create add Button
imgAdd = new ImageIcon("oop_2022/src/main/java/com/phone/common/png/add.png");
imgAdd.setImage(imgAdd.getImage().getScaledInstance(40, 40, Image.SCALE_DEFAULT));
addImg = new JButton(imgAdd);
addImg.setPreferredSize(new Dimension(60, 40));
// add Actionlisteneer to addImg Button
addImg.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Gallery.cardGal.show(PowerOn.gallery, "NewImage");
}
});
// create delete Button
imgDel = new ImageIcon("oop_2022/src/main/java/com/phone/common/png/trash.png");
imgDel.setImage(imgDel.getImage().getScaledInstance(40, 40, Image.SCALE_DEFAULT));
delImg = new JButton(imgDel);
delImg.setPreferredSize(new Dimension(60, 40));
// Add title and buttons to the topPanel
topPanel.add(title);
topPanel.add(addImg);
topPanel.add(delImg);
// add the splitPanel to the frame
this.add(splitPanel);
// set top and bottom panel Background
topPanel.setBackground(PowerOn.userInterface.DARK_GREY);
bottomPanel.setBackground(PowerOn.userInterface.DARK_GREY);
// set a GridLayout for the bottomPanel
this.setLayout(new GridLayout());
GridLayout layout = new GridLayout(0, 3, 10, 10);
bottomPanel.setLayout(layout);
// creating an array of file
results = new ArrayList<String>();
File[] files = new File("oop_2022/src/main/java/com/phone/common/png/Galery_images").listFiles();
// retrieving the name of each images
for (File file : files) {
if (file.isFile()) {
results.add(file.getName());
}
}
// create an array of images
for (int i = 0; i < fileCount; i++) {
imgGrid[i] = new ImageIcon(files[i].toString());
}
// loop to sale and add the images to the bottomPanel
for (int i = 0; i < files.length; i++) {
// scaling the images
imgGrid[i].setImage(imgGrid[i].getImage().getScaledInstance(120, 120,
Image.SCALE_SMOOTH));
// add the images to the grid
cache[i] = new JLabel(imgGrid[i]);
bottomPanel.add(cache[i]);
}
}
}
NewImage.java
public class NewImage extends JPanel {
private JLabel title, newImg;
private ImageIcon cacheImg;
private JPanel display;
private JButton choose, back;
private JFileChooser file;
private File selectedFile;
private Gallery addNew;
public NewImage() {
super();
setBackground(PowerOn.userInterface.DARK_GREY);
initComponents();
}
public void initComponents() {
// configure title JLabel
title = new JLabel("Choose a new image to add (jpg or png only)");
title.setHorizontalAlignment(title.CENTER);
// configurin choose JButton + Actionlistener
choose = new JButton("Explore");
file = new JFileChooser();
choose.setPreferredSize(new Dimension(60, 60));
choose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
int result = file.showOpenDialog(display);
if (result == JFileChooser.APPROVE_OPTION) {
selectedFile = file.getSelectedFile();
// check the type of the file only jpg and png accepted
String check = selectedFile.getAbsolutePath()
.substring(selectedFile.getAbsolutePath().length() - 3);
System.out.println(check);
// if the fil is ok add the file to the gallery directory
if (check.equals("png") || check.equals("jpg")) {
// retrieving the name of the file and copy on the galery folder
try {
String[] parts = selectedFile.getAbsolutePath().split(Pattern.quote(File.separator));
String dest = "oop_2022/src/main/java/com/phone/common/png/Galery_images/"
+ parts[parts.length - 1];
copyFile(selectedFile, new File(dest));
cacheImg = new ImageIcon(dest);
cacheImg.setImage(cacheImg.getImage().getScaledInstance(120, 120, Image.SCALE_DEFAULT));
newImg = new JLabel(cacheImg);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
JOptionPane.showMessageDialog(null, "Your image as been succesfully uploaded");
}
// if the file is not a png or a jpg display an error message
else {
JOptionPane.showMessageDialog(null, "You must choose a png or jpg file");
}
}
}
});
// configuring back JButton + Actionlistener
back = new JButton("Return to home page");
back.setPreferredSize(new Dimension(60, 60));
back.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Gallery.cardGal.show(PowerOn.gallery, "GalleryPage");
}
});
// configure layout of panel
this.setLayout(new GridLayout());
// add panels
display = new JPanel();
display.setLayout(new GridLayout(0, 1));
this.add(display);
display.add(title);
display.add(choose);
display.add(back);
}
public static void copyFile(File from, File to) throws IOException {
Files.copy(from.toPath(), new FileOutputStream(to));
}
}
What I want is that the image I added is directly displayed without running the code again when I go back to my gallery page.
my gallery page
We are creating a web application using Vaadin. Our application contains alot of drag and drop features.
We have an object which is drag-able.
We can click on it to open its menu as well.
Sometimes that when we click that item it behaves as if it is dragged.
When this happens we are unable to open its menu because the component is in dragmode.
All components with the same functionality behave the same however in development environment, when we restart the tomcat the problem disappeared?
I noticed that when the components start showing me this behavior the webpage in FireFox the behavior is fine there?
A simple solution to this could be to introduce a drag mode/edit button which would allow the user to switch the drag mode on and off.
This would mean the user could interact with the components and then enter this "drag mode" when they wished to drag them. Hence reducing the frustration of trying to interact with the component and it starting to "drag" instead.
I've create a simple example program to try out below.
public class DemoUI extends UI {
HorizontalSplitPanel splitPanel;
DragAndDropWrapper wrapperA;
DragAndDropWrapper wrapperB;
DragAndDropWrapper splitPaneWrapper;
Button buttonA;
Button buttonB;
private boolean isDragMode = false;
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = DemoUI.class)
public static class Servlet extends VaadinServlet {
}
#Override
protected void init(VaadinRequest request) {
final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
Button buttonA = new Button("Button A");
Button buttonB = new Button("Button B");
final DragAndDropWrapper wrapperA = new DragAndDropWrapper(buttonA);
final DragAndDropWrapper wrapperB = new DragAndDropWrapper(buttonB);
final VerticalLayout leftPanel = new VerticalLayout();
final VerticalLayout rightPanel = new VerticalLayout();
DragAndDropWrapper leftPanelWrapper = new DragAndDropWrapper(leftPanel);
DragAndDropWrapper rightPanelWrapper = new DragAndDropWrapper(rightPanel);
buttonA.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Notification.show("Button A was clicked");
}
});
buttonB.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Notification.show("Button B was clicked");
}
});
leftPanelWrapper.setDropHandler(new DropHandler() {
#Override
public void drop(DragAndDropEvent event) {
leftPanel.addComponent(event.getTransferable().getSourceComponent());
}
#Override
public AcceptCriterion getAcceptCriterion() {
return AcceptAll.get();
}
});
rightPanelWrapper.setDropHandler(new DropHandler() {
#Override
public void drop(DragAndDropEvent event) {
rightPanel.addComponent(event.getTransferable().getSourceComponent());
}
#Override
public AcceptCriterion getAcceptCriterion() {
return AcceptAll.get();
}
});
final Button dragMode = new Button("Drag Mode On");
dragMode.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
isDragMode = !isDragMode;
if (isDragMode) {
dragMode.setCaption("Drag Mode Off");
wrapperA.setDragStartMode(DragStartMode.WRAPPER);
wrapperB.setDragStartMode(DragStartMode.WRAPPER);
} else {
dragMode.setCaption("Drag Mode On");
wrapperA.setDragStartMode(DragStartMode.NONE);
wrapperB.setDragStartMode(DragStartMode.NONE);
}
}
});
leftPanel.setSizeFull();
rightPanel.setSizeFull();
leftPanelWrapper.setSizeFull();
rightPanelWrapper.setSizeFull();
leftPanel.addComponent(wrapperA);
rightPanel.addComponent(wrapperB);
splitPanel.setFirstComponent(leftPanelWrapper);
splitPanel.setSecondComponent(rightPanelWrapper);
splitPanel.setSizeFull();
VerticalLayout layout = new VerticalLayout();
layout.addComponent(dragMode);
layout.addComponent(splitPanel);
layout.setSizeFull();
this.setContent(layout);
this.setSizeFull();
}
.
All the best.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a list of JComponents each having a visibility time. I have to pick each component from the List, use a swing timer, display it for the specifed visibility time after which remove the displayed component from the panel, take the next component from the list and display and so on. At a particular time I should display only one component. Please help
testList.add(new JLabel());
testList.add(new JButton());
java.util.Timer timer;
TimerTask task;
for (Iterator<> it = testList.iterator(); it.hasNext(); ) {
final JComponent comp= it.next();
comp.setSize(new Dimension(200, 200));
for(int index=0; index==getComponents().length;index++) {
if(getComponents().length==0)
add(not.getComponent(), BorderLayout.CENTER);
}
timer= new java.util.Timer();
task= new TimerTask() {
public void run() {
validate();
try {
remove(comp);
} catch (Exception e) {
e.printStackTrace();
}
validate();
repaint();
}
};
timer.schedule( task ,30*1000);
it.remove();
}
Try your hands on this code, will this do to satisfy your needs :-)
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.*;
public class ListAndTimer
{
private JButton button;
private JToggleButton toggleButton;
private JLabel label;
private JCheckBox cbox;
private JRadioButton rButton;
private Object[] data;
private JList myList;
private List<JComponent> components;
private JComponent lastComponent;
private JPanel contentPane;
private Timer timer;
public ListAndTimer()
{
contentPane = new JPanel();
button = new JButton("BUTTON");
button.setName("2");
toggleButton = new JToggleButton("TOGGLE BUTTON");
toggleButton.setName("3");
label = new JLabel("LABEL");
label.setName("4");
cbox = new JCheckBox("CHECKBOX", false);
cbox.setName("2");
rButton = new JRadioButton("RADIOBUTTON", false);
rButton.setName("3");
components = new ArrayList<JComponent>();
components.add(button);
components.add(toggleButton);
components.add(label);
components.add(cbox);
components.add(rButton);
data = new Object[]{
"Button", "Toggle Button", "Label",
"CheckBox", "RadioButton"
};
myList = new JList(data);
myList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
myList.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent lse)
{
int index = myList.getSelectedIndex();
int time = 0;
System.out.println("Index : " + index);
lastComponent = components.get(index);
contentPane.add(lastComponent);
time = Integer.parseInt(lastComponent.getName());
contentPane.revalidate();
contentPane.repaint();
timer = new Timer(time * 1000, timerAction);
timer.setRepeats(false);
timer.start();
}
});
myList.setVisibleRowCount(5);
myList.setLayoutOrientation(JList.VERTICAL_WRAP);
}
private ActionListener timerAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
contentPane.remove(lastComponent);
contentPane.revalidate();
contentPane.repaint();
}
};
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("List And Timer");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.getContentPane().add(contentPane, BorderLayout.CENTER);
frame.getContentPane().add(myList, BorderLayout.LINE_END);
frame.setSize(300, 300);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ListAndTimer().createAndDisplayGUI();
}
});
}
}
You could do it for example like this:
private static int current = 0;
public static void main ( String[] args )
{
final List<Component> components = new ArrayList<Component> ();
components.add ( new JButton ( "Button" ) );
components.add ( new JToggleButton ( "Toggle" ) );
components.add ( new JLabel ( "Label" ) );
components.add ( new JCheckBox ( "Check" ) );
components.add ( new JRadioButton ( "Radio" ) );
final JPanel panel = new JPanel ();
panel.setBorder ( BorderFactory.createEmptyBorder ( 50, 50, 50, 50 ) );
panel.add ( components.get ( current ) );
JFrame frame = new JFrame ();
frame.add ( panel );
frame.pack ();
frame.setLocationRelativeTo ( null );
frame.setVisible ( true );
new Timer ( 2000, new ActionListener ()
{
public void actionPerformed ( ActionEvent e )
{
current = current < components.size () - 1 ? current + 1 : 0;
panel.removeAll ();
panel.add ( components.get ( current ) );
panel.revalidate ();
panel.repaint ();
}
} ).start ();
}
There are a few important things here:
1. Remove old component from the panel (i just remove all existing to simplify the code)
2. Add new one on the same location in layout
3. Revalidate container (JPanel) so it updates its childs bounds
4. Repaint container so you will see the changes properly
Also this (i mean the part of code, that changes JPanel content) should be done in Swing-worker thread. In my example javax.swing.Timer action is performed in that thread, so i don't need to worry about it.
In other cases you should execute code inside:
SwingUtilities.invokeLater ( new Runnable ()
{
public void run ()
{
// Code here
}
} );
or:
SwingUtilities.invokeAndWait ( new Runnable ()
{
public void run ()
{
// Code here
}
} );
Depending on the situation.
It is not necessary but highly recommended, since Swing is not Thread-safe and you could get lots of problems later, when your application will grow wide.
I am making an mp3 player, with several JLists in my JFrame. When I right click on a JList item, a popup with some options for that song appears. But when this popup is visible, and I minimise my JFrame, this popup stays visible! Also, when the popup is visible, and I drag my JFrame to somewhere else on the screen, the popup stays on it's original position (so it does not stay on the same position relative to the JFrame)... Can someone please help me out with this? I tried to strip down this class as much as possible :)
I would be really grateful if someone could help me out !!
Joe
public class playListPanel extends JPanel implements MouseListener {
private DefaultListModel model;
private Interface interFace;
private JList list;
private boolean emptyPlaylist;
private ArrayList<Song> currentPlayList;
private Song rightClickedSong;
private JPopupMenu popup;
private Point panelLocation;
public playListPanel(Interface interFace) // Interface extends JFrame,
// playListPanel is a part of
// this JFrame.
{
this.interFace = interFace;
this.panelLocation = new Point(559, 146);
setBackground(SystemColor.controlHighlight);
setBorder(new TitledBorder(null, "", TitledBorder.LEADING,
TitledBorder.TOP, null, null));
setBounds((int) panelLocation.getX(), (int) panelLocation.getY(), 698,
368);
setLayout(null);
currentPlayList = new ArrayList<Song>();
model = new DefaultListModel();
list = new JList(model);
list.setVisible(true);
list.addMouseListener(this);
JScrollPane scrollPane = new JScrollPane(list);
scrollPane.setBounds(5, 5, 688, 357);
add(scrollPane);
emptyPlaylist = true;
}
private void openMenuPopup(Point point)
{
removePopup();
popup = new JPopupMenu();
int x = (int) point.getX();
int y = (int) point.getY();
popup.setLocation((int) (x+panelLocation.getX()),(int) (y+panelLocation.getY()));
//popup.setLabel("popup voor playlist");
JMenuItem removeSong;
popup.add(removeSong = new JMenuItem("Remove Song from Playlist", new ImageIcon("image.jpg")));
ActionListener menuListener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if(event.getActionCommand().equals("Remove Song from Playlist"))
{
System.out.println("Remove Song from Playlist");
interFace.getPlaylistManager().removeOneSong(rightClickedSong);
removePopup();
}
};
//ADD THE LISTENERS TO THE MENU ITEMS
removeSong.addActionListener(menuListener);
popup.setVisible(true);
}
public void removePopup()
{
if(popup!==null)
{
popup.setVisible(false);
System.out.println("popup removed");
}
}
private int getRow(Point point) {
return list.locationToIndex(point);
}
public void refreshPlayList(ArrayList<Song> playlist) {
this.currentPlayList = playlist;
model.clear();
for (Song song : playlist) {
model.add(model.getSize(), song.getPlaylistString());
}
list.setVisible(true);
}
public void highlightSong(int index) {
list.setSelectedIndex(index);
}
public int getRowOfList(Point point) {
return list.locationToIndex(point);
}
#Override
public void mouseClicked(MouseEvent e) {
interFace.getPlaylistManager().doubleClickOnPlaylist(e);
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
rightClickedSong = currentPlayList.get(getRow(e.getPoint()));
openMenuPopup(e.getPoint());
System.out.println("should open popup at "
+ e.getPoint().toString());
}
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
There are some basic flaws in the way you are handling click for showing popup.
It is not advisable to call popup.setVisible in simple scenarios like this. Instead, you may rely on its default behavior. Also, better to use e.isPopupTrigger() than to check SwingUtilities.isRightMouseButton(e) to show popup.
You may do something like the following :
//at classlevel,
private JPopupMenu popup = new JPopupMenu();
//create a Popuplistener
PopupListener pl = new PopupListener();
list.addMouseListener(pl);
//Implementation of your popuplistener
class PopupListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger())
//e.getSource - and construct your popup as required.
//and then.
popup.show(((JApplet) e.getComponent()).getContentPane(), e
.getX(), e.getY());
}
}
I'm trying to use the JTree and implement different drop downs for all the parent nodes and the children nodes.
Here's what I've done:
pmTree.addMouseListener(new java.awt.event.MouseAdapter() {
#Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
try {
if(evt.getButton() == evt.BUTTON1) {
}
else if (evt.getButton() == evt.BUTTON3) {
TreePopup(evt);
//pmTree.updateUI();
}
}catch (Exception e) {}
}
});
and PopupCode:
public void TreePopup(java.awt.event.MouseEvent evt) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) pmTree.getLastSelectedPathComponent();
popup = new JPopupMenu();
popup.setInvoker(pmTree);
PopupHandler handler = new PopupHandler(pmTree, popup);
if(node.getLevel() == 1)
{
popup.add(getMenuItem("Parent Node", handler));
}
else if(node.getLevel() == 2)
{
popup.add(getMenuItem("Child", handler));
}
}
and PopUpHandler:
public class PopupHandler extends javax.swing.JFrame implements ActionListener {
JPopupMenu popup;
Point loc;
public PopupHandler(JTree tree, JPopupMenu popup) {
//this.tree = NewJFrame.pmTree;
this.popup = popup;
tree.addMouseListener(ma);
}
and also the
public void actionPerformed(java.awt.event.ActionEvent evt)
for the Child or Parent node being clicked.
However, when I run the program, I get the SAME right click popups for both the child and parent node.
Sorry for the huge chunk of code. I've been stuck with it for 2 days and yet not successful.
Thanks!
Don't go as low-level as a MouseListener, instead use the api around componentPopupMenu. Doing so, the general approach is dynamically configure the componentPopup in the getPopupLocation method, some simple example snippet:
JPopupMenu popup = new JPopupMenu();
final Action action = new AbstractAction("empty") {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
};
popup.add(action);
JTree tree = new JTree() {
/**
* #inherited <p>
*/
#Override
public Point getPopupLocation(MouseEvent e) {
if (e != null) {
// here do your custom config, like f.i add/remove menu items based on context
// this example simply changes the action name
TreePath path = getClosestPathForLocation(e.getX(), e.getY());
action.putValue(Action.NAME, String.valueOf(path.getLastPathComponent()));
return e.getPoint();
}
action.putValue(Action.NAME, "no mouse");
return null;
}
};
tree.setComponentPopupMenu(popup);
You check the selected node:
DefaultMutableTreeNode node = (DefaultMutableTreeNode)pmTree.getLastSelectedPathComponent();
to see if you have a "parent" or a "child" node. You should select the node at the mouse position first, otherwise it will not be the right node. Call
TreePath path = pmTree.getPathForLocation(evt.getX(), evt.getY());
if (path != null) {
pmTree.setSelectionPath(path);
} else {
return;
}
at the beginning of treePopup. (methods in Java should start with a lower case letter!)
Awesome. I was successfully able to put the setSelectionPath() call inside the override of getPopupLocaiton(). I had been trying to do it inside the ActionListener of my JMenuItem to no avail.
public Point getPopupLocation( MouseEvent e ) {
Point point = null;
if( e != null ) {
TreePath path = getClosestPathForLocation( e.getX(), e.getY() );
setSelectionPath( path );
point = e.getPoint();
}
return point;
}