Drag and Drop from JTable to JLayeredPane - java

How to create Drag and drop between JTable and JLayeredPane.
Does anyone have any ideas how to implement this?
I need transfer object by Drag and drop between JTable and JLayeredPane.

You have to do a few things at minimum to get this to work:
Call setDragEnabled(true) on your JTable instance
Set the JTables and JLayeredPanes DropTarget
Create a draggable Component to add to the JLayeredPane
To set a Components DropTarget, call the setDropTarget(DropTarget d) method and pass an anonymous inner class as the argument. Code that drops the Transferables data into the Component should be located in the drop(DropTargetDropEvent dtde) method.
The below snippet shows how to receive a Transferable and insert it into the row of a JTable where the drop was initiated:
table.setDropTarget(new DropTarget() {
#Override
public synchronized void drop(DropTargetDropEvent dtde) {
try {
// get row to put new item in
int row = table.rowAtPoint(dtde.getLocation());
// inserting row:
((DefaultTableModel) table.getModel()).insertRow(
//if the row wasn't found, add it to the end of the JTable
row == -1 ? table.getRowCount() : row,
// pass string flavor of transferable data as row data parameter
new Object[] {dtde.getTransferable()
.getTransferData(DataFlavor.stringFlavor)});
} catch(UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
});
This below snippet again receives a Transferable but instead adds it to the end of a JLayeredPane. Note that components are added to the end of the JLayeredPane because I assign a BoxLayout(SwingConstants.VERTICAL) to it.
layeredPane.setDropTarget(new DropTarget() {
#Override
public synchronized void drop(DropTargetDropEvent dtde) {
try {
// create draggable label to add to layered pane
// creating this class will be explained next
final DraggableLabel label = new DraggableLabel(
(String) dtde.getTransferable()
.getTransferData(DataFlavor.stringFlavor));
// add label to layered pane
layeredPane.add(label, JLayeredPane.DEFAULT_LAYER);
layeredPane.revalidate();
layeredPane.repaint();
} catch(UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
});
To create a draggable Component (In this example a JLabel), you must:
Create a new class that extends JLabel and implements DragGestureListener and DragSourceListener
Override all the necessary methods
In the constructor:
Create a new DragSource
Create a DragGestureRecognizer and assign it to this the JLabel subclass and this the DragGestureListener
Start a drag using the DragSource in the dragGestureRecognized(DragGestureEvent evt) method
class DraggableLabel extends JLabel implements DragGestureListener, DragSourceListener {
private DragSource dragSource;
DraggableLabel(String text) {
super(text);
// create the drag source
dragSource = new DragSource();
// assign this component a DragGestureRecognizer
dragSource.createDefaultDragGestureRecognizer(
this, DnDConstants.ACTION_COPY_OR_MOVE, this);
// for contrast with other items in layered pane
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
}
#Override
public void dragGestureRecognized(DragGestureEvent evt) {
dragSource.startDrag(
evt, //trigger event
DragSource.DefaultMoveDrop, // icon
new StringSelection(getText()), // transferable data
this); // this the DragSourceListener
}
#Override
public void dragEnter(DragSourceDragEvent evt) {}
#Override
public void dragOver(DragSourceDragEvent evt) {}
#Override
public void dragExit(DragSourceEvent evt) {}
#Override
public void dropActionChanged(DragSourceDragEvent evt) {}
#Override
public void dragDropEnd(DragSourceDropEvent evt) {}
}
Full working example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.io.IOException;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JTable;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
class DragDropExample {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
final JFrame frame = new JFrame("JLabel Text Example");
final JTable table = new JTable(new DefaultTableModel(
new Object[][] {
{"Item 1"},
{"Item 2"},
{"Item 3"},
{"Item 4"},
{"Item 5"}},
new String[] {"Column Name"}));
table.setDragEnabled(true);
table.setDropTarget(new DropTarget() {
#Override
public synchronized void drop(DropTargetDropEvent dtde) {
try {
// get row to put new item in
int row = table.rowAtPoint(dtde.getLocation());
// inserting row:
((DefaultTableModel) table.getModel()).insertRow(
//if the row wasn't found, add it to the end of the JTable
row == -1 ? table.getRowCount() : row,
// pass string flavor of transferable data as row data parameter
new Object[] {dtde.getTransferable()
.getTransferData(DataFlavor.stringFlavor)});
} catch(UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
});
final JLayeredPane layeredPane = new JLayeredPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 300);
}
};
layeredPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
layeredPane.setLayout(new BoxLayout(layeredPane, BoxLayout.Y_AXIS));
layeredPane.setDropTarget(new DropTarget() {
#Override
public synchronized void drop(DropTargetDropEvent dtde) {
try {
// create draggable label to add to layered pane
// creating this class will be explained next
final DraggableLabel label = new DraggableLabel(
(String) dtde.getTransferable()
.getTransferData(DataFlavor.stringFlavor));
// add label to layered pane
layeredPane.add(label, JLayeredPane.DEFAULT_LAYER);
layeredPane.revalidate();
layeredPane.repaint();
} catch(UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
}
});
frame.getContentPane().add(table, BorderLayout.WEST);
frame.getContentPane().add(layeredPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
static class DraggableLabel extends JLabel implements DragGestureListener, DragSourceListener {
private DragSource dragSource;
DraggableLabel(String text) {
super(text);
// create the drag source
dragSource = new DragSource();
// assign this component a DragGestureRecognizer
dragSource.createDefaultDragGestureRecognizer(
this, DnDConstants.ACTION_COPY_OR_MOVE, this);
// for contrast with other items
setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
}
#Override
public void dragGestureRecognized(DragGestureEvent evt) {
dragSource.startDrag(
evt, //trigger event
DragSource.DefaultMoveDrop,
new StringSelection(getText()),
this);
}
#Override
public void dragEnter(DragSourceDragEvent evt) {}
#Override
public void dragOver(DragSourceDragEvent evt) {}
#Override
public void dragExit(DragSourceEvent evt) {}
#Override
public void dropActionChanged(DragSourceDragEvent evt) {}
#Override
public void dragDropEnd(DragSourceDropEvent evt) {}
}
}

DropTarget dt = new DropTarget(Droptargetobject, new DropTargetAdapter() {
#Override
public void dragEnter(DropTargetDragEvent dtde) {
//executed if mouse with items enters object
}
#Override
public void drop(DropTargetDropEvent dtde) {
//executed if you drop the item
}
});
and to implement the drag use a java.awt.dnd.DragGestureEvent;.
i hope you understand what i mean
imports i used:
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;

Related

How to override the JPopupMenu method show?

my goal is to highlight a jlist item after a rightclick then show a jpopupmenu..
I read advice that overriding the method show is the way..
in my case i declare my jpopupmenu at the beginning of my class
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem masterlist,settings;
then i have a method to set up my menuItems
public void setPopupMenu(int depth//ignore this var){
//popupMenu = new JPopupMenu();
popupMenu.removeAll();
masterlist = new JMenuItem("Masterlist");
settings = new JMenuItem("Settings");
//action for marsterlist
masterlist.addActionListener(new ActionListener(){
//stuff here
}
});
//action for settings
settings.addActionListener(new ActionListener(){
//stuff here
}
});
popupMenu.add(masterlist);
popupMenu.add(settings);
}
and my list is in a different method
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(-1);
list.setComponentPopupMenu(popupMenu);
I tried putting this on a mouseAdapter of my list but the popupmenu fires first and ignores highlighting...
if ( SwingUtilities.isRightMouseButton(mouseEvent) )//highlight the right clicked item
{
int row = list.locationToIndex(mouseEvent.getPoint());
list.setSelectedIndex(row);
String val = (String)list.getSelectedValue();
System.out.println(val);
}
i know that overriding is something like this
popupmenu = new JPopupMenu(){
#Override
public void show(){}
}
but i cant do that because i am manipulating the menuitems on a method...
or is there any other approach that anyone can suggest...
Rather then trying to modify the state of the JPopupMenu, why not simply modify the state of the menu item when you detect a right click...
So, basically, I make use of the Actions API to define a menu item for a JPopupMenu, which allows it to register a ListSelectionListener to the underlying JList...
public class ShowItemAction extends AbstractAction {
private JList list;
public ShowItemAction(JList list) {
this.list = new JList();
putValue(NAME, "Showing ...");
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
int index = list.getSelectedIndex();
String value = list.getSelectedValue().toString();
putValue(NAME, "Showing " + value + " # " + index);
}
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
// The actual action to be performed when selected
}
}
All this does is, when the selection is changed, is change the text (NAME) of the action, which changes the text of the menu item, based on the currently selected row.
When I create the JList, I assign it a JPopupMenu via the setComponentPopupMenu method, which means I no longer need to care about it and it will be displayed appropriately based on the current look and feel requirements
JList list = new JList(model);
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new ShowItemAction(list));
list.setComponentPopupMenu(popupMenu);
I then add a MouseListener to the JList which I use to change the row selection when you right click on the JList...
list.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
JList list = (JList)e.getComponent();
if (SwingUtilities.isRightMouseButton(e)) {
int row = list.locationToIndex(e.getPoint());
list.setSelectedIndex(row);
}
}
});
This not entirely fool proof, as if you right click the JList while the popup is visible, the MouseListener doesn't appear to get notified :P
Runnable example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import static javax.swing.Action.NAME;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DefaultListModel model = new DefaultListModel();
model.addElement("One");
model.addElement("Two");
model.addElement("Three");
model.addElement("Four");
JList list = new JList(model);
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new ShowItemAction(list));
list.setComponentPopupMenu(popupMenu);
list.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int row = list.locationToIndex(e.getPoint());
list.setSelectedIndex(row);
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(list));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ShowItemAction extends AbstractAction {
private JList list;
public ShowItemAction(JList list) {
this.list = new JList();
putValue(NAME, "Showing ...");
list.addListSelectionListener(new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
int index = list.getSelectedIndex();
String value = list.getSelectedValue().toString();
putValue(NAME, "Showing " + value + " # " + index);
}
}
});
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
}

JButton default cursor

Is there a way to set default cursor of JButton components?
This is how to set cursor for a one JButton:
JButton btn = new JButton("Click me");
btn.setCursor(new Cursor(Cursor.HAND_CURSOR));
According lookAndFeel Nimbus defaults there's no a property like "Button.cursor".
I'd like to set default cursor once so all the JButtons in the app have the same hand-cursor when the mouse cursor moves over.
You can have a custom button that extends the JButton and use that. Some thing like :
MyCustomJButton.java
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
#SuppressWarnings("serial")
public class MyCustomJButton extends JButton implements MouseListener
{
private Cursor defaultCursor;
private Cursor handCursor;
public MyCustomJButton()
{
super();
init();
}
public MyCustomJButton(Action a)
{
super(a);
init();
}
public MyCustomJButton(Icon icon)
{
super(icon);
init();
}
public MyCustomJButton(String text, Icon icon)
{
super(text, icon);
init();
}
public MyCustomJButton(String text)
{
super(text);
init();
}
#Override
public void mouseClicked(MouseEvent e)
{
}
#Override
public void mousePressed(MouseEvent e)
{
}
#Override
public void mouseReleased(MouseEvent e)
{
}
#Override
public void mouseEntered(MouseEvent e)
{
this.setCursor(handCursor);
}
#Override
public void mouseExited(MouseEvent e)
{
this.setCursor(defaultCursor);
}
private void init()
{
defaultCursor = this.getCursor();
handCursor = new Cursor(Cursor.HAND_CURSOR);
addMouseListener(this);
}
}
Once you have implemented your own custom button, you can instantiate it like you would instantiate the JButton.
MyCustomJButton myButton = new MyCustomJButton("My Button");

java drop and drag label to join correct image

this code is only allowing me to reject a string the second time to try to drop in a textArea where there is all ready a string.
public GridLayoutTest() {
JFrame frame = new JFrame("GridLayout test");
connection = getConnection();
try {
statement = (PreparedStatement) connection
result = statement.executeQuery();
while (result.next()) {
byte[] image = null;
image = result.getBytes("image");
JPanel cellPanel = new JPanel(new BorderLayout());
cellPanel.add(cellLabel, BorderLayout.NORTH);
cellPanel.add(droplabel, BorderLayout.CENTER);
gridPanel.add(cellPanel);
}
}
catch (SQLException e) {
e.printStackTrace();}
}
So, two things, first...
public void DropTargetTextArea(String string1, String string2) {
Isn't a constructor, it's a method, note the void. This means that it is never getting called. It's also the reason why DropTargetTextArea textArea = new DropTargetTextArea(); works, when you think it shouldn't.
Second, you're not maintaining a reference to the values you pass in to the (want to be) constructor, so you have no means to references them later...
You could try using something like...
private String[] values;
public DropTargetTextArea(String string1, String string2) {
values = new String[]{string1, string2};
DropTarget dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);
}
And then use something like...
if (values[0].equals(dragContents) || values[1].equals(dragContents)) {
In the drop method.
In your dragEnter, dragOver and dropActionChanged methods you have the oppurtunity to accept or reject the drag action using something like dtde.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE); or dtde.rejectDrag();
Updated with test code
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class DragAndDropExample {
public static void main(String[] args) {
ImageIcon ii1 = new ImageIcon("C:\\Users\\Desktop\\home.jpg");
ImageIcon ii = new ImageIcon("C:\\Users\\Desktop\\images (2).jpg");
// Create a frame
JFrame frame = new JFrame("test");
JLabel label = new JLabel(ii);
JLabel label1 = new JLabel(ii1);
JPanel panel = new JPanel(new GridLayout(2, 4, 10, 10));
JLabel testLabel = new DraggableLabel("test");
JLabel testingLabel = new DraggableLabel("testing");
panel.add(testLabel);
panel.add(testingLabel);
panel.add(label);
panel.add(label1);
Component textArea = new DropTargetTextArea("test", "testing");
frame.add(textArea, BorderLayout.CENTER);
frame.add(panel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static class DraggableLabel extends JLabel implements DragGestureListener, DragSourceListener {
DragSource dragSource1;
public DraggableLabel(String text) {
setText(text);
dragSource1 = new DragSource();
dragSource1.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
}
public void dragGestureRecognized(DragGestureEvent evt) {
Transferable transferable = new StringSelection(getText());
dragSource1.startDrag(evt, DragSource.DefaultCopyDrop, transferable, this);
}
public void dragEnter(DragSourceDragEvent evt) {
System.out.println("Drag enter");
}
public void dragOver(DragSourceDragEvent evt) {
System.out.println("Drag over");
}
public void dragExit(DragSourceEvent evt) {
System.out.println("Drag exit");
}
public void dropActionChanged(DragSourceDragEvent evt) {
System.out.println("Drag action changed");
}
public void dragDropEnd(DragSourceDropEvent evt) {
System.out.println("Drag action End");
}
}
public static class DropTargetTextArea extends JLabel implements DropTargetListener {
private String[] values;
public DropTargetTextArea(String string1, String string2) {
values = new String[]{string1, string2};
DropTarget dropTarget = new DropTarget(this, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void dragEnter(DropTargetDragEvent evt) {
if (!getText().isEmpty()) {
System.out.println("Reject drag enter");
evt.rejectDrag();
} else {
evt.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
}
public void dragOver(DropTargetDragEvent evt) {
if (!getText().isEmpty()) {
System.out.println("Reject drag over");
evt.rejectDrag();
} else {
evt.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
}
public void dragExit(DropTargetEvent evt) {
System.out.println("Drop exit");
}
public void dropActionChanged(DropTargetDragEvent evt) {
if (!getText().isEmpty()) {
System.out.println("Reject dropActionChanged");
evt.rejectDrag();
} else {
evt.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
}
}
public void drop(DropTargetDropEvent evt) {
if (!getText().isEmpty()) {
evt.rejectDrop();
} else {
try {
Transferable transferable = evt.getTransferable();
if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String dragContents = (String) transferable.getTransferData(DataFlavor.stringFlavor);
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
if (values[0].equals(dragContents) || (values[1]).equals(dragContents)) {
System.out.println("Accept Drop");
setText(getText() + " " + dragContents);
evt.getDropTargetContext().dropComplete(true);
} else {
System.out.println("Reject Drop");
}
}
} catch (IOException e) {
evt.rejectDrop();
evt.dropComplete(false);
} catch (UnsupportedFlavorException e) {
}
}
}
}
}

JTree & JButtons - Wrong Rendering when mouse hovers over Button

I have a Problem with JTree and JButton
It seems like when entering the Edit modus and hovering over the Buttons on the TreeCells, it Renderes some Part of the Tree inside the Button.
Even when Dragging from one Button to another in the Same Row it Renderes the one Button over the other one.
Here a Short Selfexplaining Sample that you can copy paste to See what i mean.
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.EventObject;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
public class MyProblemWithTree {
public static void main(String...args) {
JFrame frame = new JFrame("Panel");
JScrollPane scroll = new JScrollPane();
DefaultMutableTreeNode node = new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode nodeChild = new DefaultMutableTreeNode("childcaretaker1");
nodeChild.add(new DefaultMutableTreeNode("child1"));
nodeChild.add(new DefaultMutableTreeNode("child2"));
node.add(nodeChild);
final JTree tree = new JTree(node);
tree.setCellRenderer(new MyTreeCellRenderer());
tree.setEditable(true);
tree.setCellEditor(new MyTreeCellEditor(tree));
tree.addMouseMotionListener(new MouseMotionListener() {
#Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
if (tree.getRowForLocation(e.getX(), e.getY()) != -1)
{
tree.startEditingAtPath(tree.getPathForLocation(e.getX(), e.getY()));
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
scroll.setViewportView(tree);
frame.add(scroll);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
class MyTreeCellEditor extends DefaultTreeCellEditor {
JPanel leafPanel;
JLabel colorIcon;
PlayButton play;
PauseButton pause;
JLabel name;
public MyTreeCellEditor(JTree tree) {
super(tree, (MyTreeCellRenderer)tree.getCellRenderer());
leafPanel = new JPanel(new FlowLayout());
colorIcon = new JLabel(UIManager.getIcon("OptionPane.informationIcon"));
play = new PlayButton();
pause = new PauseButton();
name = new JLabel();
play.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
System.out.println("Playbutton klickt");
}
});
leafPanel.add(colorIcon);
leafPanel.add(name);
leafPanel.add(pause);
leafPanel.add(play);
}
#Override
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean selected, boolean expanded, boolean leaf, int row) {
name.setText((String)((DefaultMutableTreeNode)value).getUserObject());
pause.setVisible(!leaf);
return leafPanel;
}
#Override
public boolean isCellEditable(EventObject arg0) {
return true;
}
}
class MyTreeCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 3691823996133806942L;
JPanel leafPanel;
JLabel colorIcon;
PlayButton play;
PauseButton pause;
JLabel name;
DefaultTreeCellRenderer defaultRenderer = new DefaultTreeCellRenderer();
Color backgroundSelectionColor;
Color backgroundNonSelectionColor;
public MyTreeCellRenderer() {
leafPanel = new JPanel(new FlowLayout());
colorIcon = new JLabel(UIManager.getIcon("OptionPane.informationIcon"));
play = new PlayButton();
pause = new PauseButton();
name = new JLabel();
leafPanel.add(colorIcon);
leafPanel.add(name);
leafPanel.add(pause);
leafPanel.add(play);
backgroundSelectionColor = new Color(200,200,255,50);
backgroundNonSelectionColor = new Color(0,0,0,0);
}
#Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
name.setText((String)((DefaultMutableTreeNode) value).getUserObject());
if (selected) {
leafPanel.setBackground(backgroundSelectionColor);
} else {
leafPanel.setBackground(backgroundNonSelectionColor);
}
leafPanel.setEnabled(tree.isEnabled());
pause.setVisible(!leaf);
return leafPanel;
}
}
class PlayButton extends JButton{
private static final long serialVersionUID = 550654173835539853L;
Dimension size = new Dimension(140,28);
public PlayButton() {
setIcon(UIManager.getIcon("OptionPane.informationIcon"));
setPressedIcon(UIManager.getIcon("OptionPane.errorIcon"));
setBackground(new Color(0,0,0,0));
setBorderPainted(false);
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
}
}
class PauseButton extends JButton{
private static final long serialVersionUID = -5877843953696256070L;
Dimension size = new Dimension(140,28);
public PauseButton() {
setIcon(UIManager.getIcon("OptionPane.warningIcon"));
setPressedIcon(UIManager.getIcon("OptionPane.questionIcon"));
setBackground(new Color(0,0,0,0));
setBorderPainted(false);
setPreferredSize(size);
setMaximumSize(size);
setMinimumSize(size);
}
}
Even when i erase this Part. and i must click a Cell to enter the Edit Modus i still can get the Effect by leaving the Cell witzh the mouse and go back.
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
if (tree.getRowForLocation(e.getX(), e.getY()) != -1)
{
tree.startEditingAtPath(tree.getPathForLocation(e.getX(), e.getY()));
}
}
I spend already 4 days into this JTree Customizing. But it really confuses me, how i could stop the rendering by entering the Button.
I don't know how to fix this, but it helps to use invokeLater and setRowHeight().
public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Panel");
...
tree.setRowHeight(icon.getIconHeight());
...
frame.setVisible(true);
}
});
}

Fixing JPopupMenu separators (GTK LaF) and items highlighting

yesterday I've been using for the first time Swing for a quick desktop application (I'm a fan of swt indeed...).
BTW I came across a couple of problems with JPopupMenu:
1) With GTK LaF, separators are not showing due to a bug.
2) While moving the mouse over menu items, they do not highlight (seen on linux and win)
Here's a variation using MouseAdapter, as well as an sscce for future reference.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
/** #see http://stackoverflow.com/questions/7254488 */
public class JPopupMenuEx extends JPopupMenu {
private MouseAdapter mouseListener = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
((JMenuItem) e.getSource()).setArmed(true);
}
#Override
public void mouseExited(MouseEvent e) {
((JMenuItem) e.getSource()).setArmed(false);
}
};
#Override
public void addSeparator() {
add(new JSeparatorEx());
}
#Override
public JMenuItem add(JMenuItem menuItem) {
menuItem.addMouseListener(mouseListener);
return super.add(menuItem);
}
private static class JSeparatorEx extends JSeparator {
#Override
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if (d.height == 0) {
d.height = 4;
}
return d;
}
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JPopupMenuEx popup = new JPopupMenuEx();
popup.add(new JCheckBoxMenuItem("Item 1"));
popup.addSeparator();
popup.add(new JMenuItem("Item 2"));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
p.add(new JLabel("Right click for context menu."));
p.setComponentPopupMenu(popup);
f.add(p);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
I decided to extend JPopupMenu class in order to fix the two issues above and now I just want to share the code, just in case someone faces the same problem.
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
public class JPopupMenuEx
extends JPopupMenu
implements MouseListener {
/**
*
*/
private static final long serialVersionUID = -5352058505305990803L;
#Override
public void addSeparator() {
add(new JSeparatorEx());
}
#Override
public JMenuItem add(JMenuItem menuItem) {
menuItem.addMouseListener(this);
return super.add(menuItem);
}
#Override
public void mouseEntered(MouseEvent e) {
((JMenuItem)e.getSource()).setArmed(true);
}
#Override
public void mouseExited(MouseEvent e) {
((JMenuItem)e.getSource()).setArmed(false);
}
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
public class JSeparatorEx extends JSeparator{
/**
*
*/
private static final long serialVersionUID = 3477309905456341629L;
public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
if (d.height==0)
d.height = 4;
return d;
}
}
}
So you can use it just like using JPopupMenu, like this:
JPopupMenuEx popup = new JPopupMenuEx();
popup.add(new JCheckBoxMenuItem("Item 1"));
popup.addSeparator();
popup.add(new JMenuItem("Item 2"));

Categories