Article View: borland.public.jbuilder.java.swing
Article #8560Re: JTable question
From: Ian Atkinson
Date: Mon, 07 Aug 2000 00:00
Date: Mon, 07 Aug 2000 00:00
362 lines
10778 bytes
10778 bytes
what you're looking for is called hottracking under windows. i have
done this with a JTree by doing the following:
- create a custom JTree which registers itself as a MouseMotionListener.
- listen to mouseMotion events and use the getRowAtPoint() to check the
current row you're over and compare against the last row (which you
should have saved last time)
- when the row changes fire off some new event (mouseOverRowChange or
something)
- add a member function to retrieve the current row the mouse is over
(getMouseOverRow)
- create a custom TreeCellRenderer which can listen for this new event
(mouseOverRowChange)
- when the rowOver event fires, just repaint the renderer
- have the renderer check if the row passed to
getTreeCellRendererComponent is the same as tree.getMouseOverRow(), if
so, set the color to your hottrack color, otherwise use what you would
have
- go back to you new tree class and override the setCellRenderer method,
you'll need to check if the new renderer is an instance of the new
renderer you made, if so, add this renderer to the new event listern
list (so it will be notified of mouseOverRowChange events) - also make
sure that the renderer you'r replacing gets removed from that list if it
was added.
the end result for me is that i can add hottracking to a tree without
any extra code in my project (except for createing the objects, setting
the renderer, ...)
the tracking works well, it highlights the current row the mouse is over
and changes quickly. this could be changed for more feedback (font
change, text change, ...)
that is pretty much it, i would think that you could adapt the concept
to a JTable pretty easy.
if you're doing Dnd in the table, this will complicate things a bit -
just be prepared
ian
here is a streamlined version of my Tree, JExtendedTree - i tried to
stip out what you don't need, but if it left/took something i should not
- don't be surprised
hope some of this helps
the Tree:
-----------------------------------------------------------------------------------
public class JExtendedTree extends JTree implements MouseMotionListener,
MouseListener
{
private EventListenerList _listeners = new EventListenerList();
private int _mouseRow = -1;
public JExtendedTree()
{
super();
// we want to listen to mouse motion events
// and mouse events so that hottracking
// can be done
this.addMouseMotionListener(this);
this.addMouseListener(this);
}
public void setCellRenderer(TreeCellRenderer r)
{
// first, check if the old cell renderer was an
ExtendedTreeRenderer
// if it was, then remove it
if(this.getCellRenderer() instanceof ExtendedTreeRenderer)
{
this.removeExtendedTreeListener((ExtendedTreeListener)this.getCellRenderer());
}
super.setCellRenderer(r);
// check to see if the renderer is an ExtendedTreeRenderer
// these can act as an ExtnededTreeListener
if(r instanceof ExtendedTreeRenderer)
{
this.addExtendedTreeListener((ExtendedTreeListener)r);
}
}
public int getMouseOverRow()
{
return _mouseRow;
}
protected void setMouseOverRow(int value)
{
// called internally, used to update the value in _mouseRow
// and will fire event if it is changed from prior value
int oldRow = _mouseRow;
_mouseRow = value;
if(oldRow!=_mouseRow)
{
fireMouseOverRowChange(oldRow, _mouseRow);
}
}
// implementation of MouseMotionListener and MouseListener
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
// the mouse is not over any position
setMouseOverRow(-1);
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseDragged(MouseEvent e)
{
// record the mouse position for hottracking
setMouseOverRow(this.getClosestRowForLocation(e.getX(),
e.getY()));
}
public void mouseMoved(MouseEvent e)
{
// record the mouse position for hottracking
setMouseOverRow(this.getClosestRowForLocation(e.getX(),
e.getY()));
}
// event fire methods
public void fireMouseOverRowChange(int oldRow, int newRow)
{
// Guaranteed to return a non-null array
Object[] listeners = _listeners.getListenerList();
// the event will be lazily created
MouseOverRowChangeEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for(int i = listeners.length-2; i>=0; i-=2)
{
if(listeners[i]==ExtendedTreeListener.class)
{
if(e == null)
{
// lazily create the event
e = new MouseOverRowChangeEvent(this, oldRow,
newRow);
}
((ExtendedTreeListener)listeners[i+1]).mouseOverRowChange(e);
}
}
}
// listener implementations
public void addExtendedTreeListener(ExtendedTreeListener l)
{
_listeners.add(ExtendedTreeListener.class, l);
}
public void removeExtendedTreeListener(ExtendedTreeListener l)
{
_listeners.remove(ExtendedTreeListener.class, l);
}
}
the TreeInterface:
-----------------------------------------------------------------------------------
public interface ExtendedTreeListener extends EventListener
{
public void mouseOverRowChange(MouseOverRowChangeEvent e);
}
the Renderer:
-----------------------------------------------------------------------------------
public class ExtendedTreeRenderer extends JLabel implements
TreeCellRenderer, ExtendedTreeListener
{
private boolean _hotTrack = true;
private Color _clrBackgroundSelected= SystemColor.textHighlight;
private Color _clrTextSelected = SystemColor.textHighlightText;
private Color _clrHotTrack = SystemColor.textInactiveText;
private Font _fntSelected = Font.getFont("Dialog");
private Font _fntHotTrack = Font.getFont("Dialog");
public ExtendedTreeRenderer()
{
this.setOpaque(true);
}
public Component getTreeCellRendererComponent(JTree tree, Object
value, boolean selected, boolean expanded, boolean leaf, int row,
boolean hasFocus)
{
// use the appropriate colors based on selected...
if(selected)
{
// setup for selected
this.setBackground(_clrBackgroundSelected);
this.setForeground(_clrTextSelected);
this.setFont(_fntSelected);
}
else
{
// setup for non-selected
this.setBackground(tree.getBackground());
this.setForeground(tree.getForeground());
this.setFont(tree.getFont());
}
if(_hotTrack && tree instanceof JExtendedTree)
{
if(((JExtendedTree)tree).getMouseOverRow() == row)
{
this.setForeground(_clrHotTrack);
this.setFont(_fntHotTrack);
}
}
// set the text value based on the value's string
this.setText(value.toString());
return this;
}
public void mouseOverRowChange(MouseOverRowChangeEvent e)
{
if(_hotTrack && e.getSource() instanceof Component)
{
// force the (tree) to repaint
// this will allow hot tracking to be performed
// (if it is enabled
((Component)e.getSource()).repaint();
}
}
public boolean getHotTrack()
{
return _hotTrack;
}
public Color getBackgroundSelectedColor()
{
return _clrBackgroundSelected;
}
public Color getTextSelectedColor()
{
return _clrTextSelected;
}
public Color getHotTrackColor()
{
return _clrHotTrack;
}
public Font getSelectedFont()
{
return _fntSelected;
}
public Font getHotTrackFont()
{
return _fntHotTrack;
}
public void setHotTrack(boolean value)
{
_hotTrack = value;
}
public void setBackgroundSelectedColor(Color value)
{
_clrBackgroundSelected = value;
}
public void setTextSelectedColor(Color value)
{
_clrTextSelected = value;
}
public void setSelectedFont(Font value)
{
_fntSelected = value;
}
public void setHotTrackColor(Color value)
{
_clrHotTrack = value;
}
public void setHotTrackFont(Font value)
{
_fntHotTrack = value;
}
}
the event:
-----------------------------------------------------------------------------------
public class MouseOverRowChangeEvent extends ComponentEvent
{
public static int MOUSE_OVER_ROW_CHANGE_FIRST = 5001;
public static int MOUSE_OVER_ROW_CHANGE_LAST = 5001;
public static int MOUSE_OVER_ROW_CHANGE = 5001;
private int _oldRow;
private int _newRow;
public MouseOverRowChangeEvent(Component source, int oldRow, int
newRow)
{
super(source, MOUSE_OVER_ROW_CHANGE);
// copy the row values
_oldRow = oldRow;
_newRow = newRow;
}
public int getOldRow()
{
return _oldRow;
}
public int getNewRow()
{
return _newRow;
}
public String paramString()
{
return (new String("MOUSE_OVER_ROW_CHANGED (oldRow=" +
String.valueOf(_oldRow) + ", newRow=" + String.valueOf(_newRow) + ")"));
}
}
Technical Details
Message-ID:
<398F105F.B707514A@labs.mot.com>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailReferences:
<398eff0e$1_2@dnews>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 111d45,8a545a90f4bfa63e X-Google-Attributes: gid111d45,public From: Ian Atkinson <atkinson@labs.mot.com> Subject: Re: JTable question Date: 2000/08/07 Message-ID: <398F105F.B707514A@labs.mot.com> X-Deja-AN: 655545047 Content-Transfer-Encoding: 7bit References: <398eff0e$1_2@dnews> X-Accept-Language: en Content-Type: text/plain; charset=us-ascii X-Complaints-To: postmaster@mot.com X-Trace: schbbs.mot.com 965676927 15010 182.1.83.2 (7 Aug 2000 19:35:27 GMT) Organization: Motorola Mime-Version: 1.0 NNTP-Posting-Date: 7 Aug 2000 19:35:27 GMT Newsgroups: borland.public.jbuilder.java.swing