I have a nasty bug that I worked on for a couple of days already and I
finally managed to isolate the problem. It seems that the use of a
CellRendererPane causes the mouse cursor to flicker during drag and
drop, but only if the "validate" flag is set to true. This effect
seems to happen on Windows only (Mac works fine). I am using Windows
XP. I have written a little standalone test case that you can find
below. Simply initiate a drag and drop sequence from one panel to
another and play around with the checkbox in the upper left corner. If
selected, the renderer component that draws the button will be
validated before its paint method gets called. When this happens the
cursor starts to flicker.
I would appreciate it very much if anyone could tell me how to get rid
of this problem. My renderer components are often quite complex and I
need to have them validated before calling them, so setting "validate"
to false does not work for me.
--Dirk
www.dlsc.com
package com.dlsc.test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.datatransfer.DataFlavor;
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.CellRendererPane;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
public class DnDTestFrame extends JFrame {
private JCheckBox checkBox = new JCheckBox("Cell renderer validates",
true);
public DnDTestFrame() {
super("DnDTest");
add(BorderLayout.NORTH, checkBox);
add(BorderLayout.WEST,new DnDTestPanel("Left", this));
add(BorderLayout.EAST,new DnDTestPanel("Right", this));
pack();
setVisible(true);
}
public boolean isValidating() {
return checkBox.isSelected();
}
/**
* @param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DnDTestFrame();
}
});
}
}
class DnDTestPanel extends JPanel implements DragGestureListener,
DragSourceListener, DropTargetListener {
private String title;
private CellRendererPane rendererPane = new CellRendererPane();
private JButton rendererComp = new JButton("Renderer");
private DnDTestFrame frame;
public DnDTestPanel(String title, DnDTestFrame frame) {
this.title = title;
this.frame = frame;
setLayout(null);
add(rendererPane);
setBackground(Color.WHITE);
setPreferredSize(new Dimension(300, 300));
setBorder(new TitledBorder(title));
DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
this, DnDConstants.ACTION_COPY_OR_MOVE, this);
new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
}
@Override
protected void paintComponent(Graphics g) {
rendererPane.paintComponent(g, rendererComp, this, 20, 20, 100, 30,
frame.isValidating());
}
public void dragGestureRecognized(DragGestureEvent dge) {
dge.startDrag(null, new Transferable() {
public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException {
return null;
}
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[] { DataFlavor.plainTextFlavor };
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return true;
}
});
}
// drag source
public void dragDropEnd(DragSourceDropEvent dsde) {
}
public void dragEnter(DragSourceDragEvent dsde) {
}
public void dragExit(DragSourceEvent dse) {
}
public void dragOver(DragSourceDragEvent dsde) {
}
public void dropActionChanged(DragSourceDragEvent dsde) {
}
// drop target
public void dragEnter(DropTargetDragEvent dtde) {
repaint();
}
public void dragExit(DropTargetEvent dte) {
repaint();
}
public void dragOver(DropTargetDragEvent dtde) {
repaint();
}
public void drop(DropTargetDropEvent dtde) {
}
public void dropActionChanged(DropTargetDragEvent dtde) {
}
}
---
* Synchronet * The Whitehouse BBS --- whitehouse.hulds.com --- check it out free usenet!
--- Synchronet 3.15a-Win32 NewsLink 1.92
Time Warp of the Future BBS - telnet://time.synchro.net:24
>I would appreciate it very much if anyone could tell me how to get rid
>of this problem.
Sometimes the problem is actually a bug in the video driver that fancy
code brings to the surface, like putting a hot compress on an
infection.
Try your code on a different Windows machine with a different video
card. See if there is an update for your video card from the
manufacturer.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
>DataFlavor.plainTextFlavor
this is deprecated.
>I have a nasty bug that I worked on for a couple of days already and I
>finally managed to isolate the problem.
I have compiled the program and run it on Windows Vista on an Acer
integrated Video card.
I notice a little box gets drawn to the bottom right of the cursor and
then erased as you move the cursor. I presume this is what you mean by
"flicker".
Presumably somebody is calling setCursor back and forth for two
different cursors.
You might try an IDE like IntelliJ Idea with its integrated debugger
to find out who is doing it and why.
Hats off to you for coming up with such a succinct SSCCE.
http://mindprod.com/jgloss/sscce.html
This has been tested on dozends of machines and they all show the same
problem. It even shows up on Macs running in a virtual machine
(Parallels), which means that it is pretty far away from the actual
hardware.
Dirk
setCursor() is not being called. During a drag and drop operation the
cursor management seems to happen somewhere else but I don't know
where.
Dirk
I meant "Macs running Winodws XP in a virtual machine environment".
Dirk
>setCursor() is not being called. During a drag and drop operation the
>cursor management seems to happen somewhere else but I don't know
>where.
At least on my hardware, it seems very likely the cursor is being
redrawn back and forth between two different forms. This implies
SOMEONE, perhaps deep in the bowels or in a UI LAF is calling
setCursor.
If I were you I would put a trap on setCursor and find out if and who
is calling it.
Also, If you can get a snapshot of the variant cursor, and if you can
recognise it, that might help track down who is setting it and where.
The queasy feeling I have about this is even after you track it down
and present it to Sun, they will say it is not a bug but a feature.