Java Forum / GUI / March 2005
Floating Label Component in JScrollPane
reinhard.engels@gmail.com - 15 Mar 2005 16:48 GMT I have an app that displays stacked rectangular glyphs representing data in a jscrollpane. It works fine.
Problem: I'd like to add labels to the rows of data glyphs. I'd like these labels to float as you scroll horizontally, sort of like column headers in excel, except the other direction. This doesn't work, as I've coded it. When I scroll, there is some kind of repaint issue and visual artifacts from the labels trace across the screen.
What I'm doing is calling setBounds on the floating label component in the data panel paintComponent. I'm assuming this is wrong, but I don't know what else to do. See code below for a short but full "working" applet that displays the problem. If it looks hideous in your newreader here are urls for the code and the applet:
code url:
http://www.everydaysystems.com/testjava/float_in_scroll/FloatInScrollTest.java.txt
applet url:
http://www.everydaysystems.com/testjava/float_in_scroll/FloatInScrollTest.html
I'm hoping this is an embarrassingly simple problem.
Thanks (and embarrassed) in advance,
Reinhard
*******************************************************
import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics;
import javax.swing.JApplet; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JViewport;
public class FloatInScrollTest extends JApplet {
public void init() { setSize(500, 100); JPanel dataPanel = new DataPanel(); JScrollPane scrollPane = new JScrollPane(dataPanel); scrollPane
.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); scrollPane
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.setPreferredSize(new Dimension(500, 100)); getContentPane().add(scrollPane); }
class FloatingLabelGlyph extends JComponent { public FloatingLabelGlyph(String label, Color color) { this.color = color; this.label = label; setVisible(true); }
public void paintComponent(Graphics g) { g.setColor(color); g.drawString(label, 0, g.getFont().getSize()); }
Color color; String label; }
class DataGlyph extends JComponent { public DataGlyph(Color color, int x, int y, int width) { this.color = color; setBounds(x, y, width, height); setVisible(true); }
public void paintComponent(Graphics g) { g.setColor(color); g.fillRect(0, 0, getWidth(), getHeight()); }
private int height = 10; private Color color; }
class DataPanel extends JPanel { public DataPanel() { super(); setLayout(null); setSize(new Dimension(1000, 1000)); setPreferredSize(new Dimension(1000, 1000)); floatingLabels = new FloatingLabelGlyph[labels.length]; for (int i = 0; i < labels.length; i++) { add(floatingLabels[i] = new FloatingLabelGlyph(labels[i], colors[i])); } add(new DataGlyph(colors[0], 150, rowYs[0], 50)); add(new DataGlyph(colors[0], 170, rowYs[1], 75)); add(new DataGlyph(colors[0], 220, rowYs[0], 100)); add(new DataGlyph(colors[1], 160, rowYs[2], 55)); add(new DataGlyph(colors[1], 960, rowYs[2], 35)); add(new DataGlyph(colors[1], 220, rowYs[2], 25)); add(new DataGlyph(colors[1], 200, rowYs[3], 33)); add(new DataGlyph(colors[2], 600, rowYs[4], 100)); add(new DataGlyph(colors[2], 900, rowYs[4], 88)); setVisible(true); }
public void paintComponent(Graphics g) { // TODO: update label positions. This is the broken part. g.clearRect(0,0,getWidth(),getHeight()); for (int i = 0; i < floatingLabels.length; i++) { g.clearRect(floatingLabels[i].getX(), floatingLabels[i].getY(), floatingLabels[i].getWidth(), floatingLabels[i] .getHeight()); floatingLabels[i].setBounds((int) ((JViewport) getParent()) .getViewPosition().getX(), labelYs[i], 80, 15); } super.paintComponent(g); }
private String[] labels = new String[] { "Red Data", "Green Data", "Blue Data" }; private Color[] colors = new Color[] { Color.RED, Color.GREEN, Color.BLUE }; private FloatingLabelGlyph[] floatingLabels; private int[] rowYs = new int[] { 10, 25, 40, 55, 70 }; private int[] labelYs = new int[] { 10, 40, 70 }; }
}
*******************************************************
John McGrath - 17 Mar 2005 06:03 GMT > What I'm doing is calling setBounds on the floating label component in > the data panel paintComponent. I'm assuming this is wrong, but I don't > know what else to do. One thing I noticed is that the paintComponent() methods do not all call super.paintComponent(), which they generally should. However, I don't think that is the cause of your problems.
Moving components in the paintComponent() method is definitely not a good idea. I think a much better approach would be to place the "floating" glyphs on a stationary, transparent panel that is placed above the JScrollPane.
 Signature Regards,
John McGrath
reinhard.engels@gmail.com - 17 Mar 2005 15:26 GMT > One thing I noticed is that the paintComponent() methods do not all call > super.paintComponent(), which they generally should. However, I don't > think that is the cause of your problems. Thank you, John. I tried adding super.paintComponent(g) methods but, as you predicted, no luck.
> Moving components in the paintComponent() method is definitely not a good > idea. I think a much better approach would be to place the "floating" > glyphs on a stationary, transparent panel that is placed above the > JScrollPane. The problem with putting the labels on a stationary panel is that I *do* want them to scroll vertically (so they stay above the vertically scrolling data glyphs they are labeling) but not horizontally (or they'd disappear as you scrolled to view rightward data glyphs). Naively, I'd think the floating label repositioning should be called by a listener triggered whenever a scroll event took place, but from my poking around, it doesn't seem there is such a listener.
Thanks again! Brute force or the kindness of strangers will eventually yield a solution and I'll be sure to post it here.
Reinhard
reinhard.engels@gmail.com - 17 Mar 2005 15:56 GMT Got it!
scrollPane.getHorizontalScrollBar().addAdjustmentListener(new FloatingLabelAdjustmentListener(dataPanel));
Full revised code below. The scroll is still a little flickery, but no more artifacts tracing all over the screen. Hope this is of use to someone somewhere sometime...
Reinhard
**************************************************************
import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener;
import javax.swing.JApplet; import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JViewport;
public class FloatInScrollTest extends JApplet {
public void init() { setSize(500, 100); DataPanel dataPanel = new DataPanel(); JScrollPane scrollPane = new JScrollPane(dataPanel); scrollPane
.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); scrollPane
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.setPreferredSize(new Dimension(500, 100)); scrollPane.getHorizontalScrollBar().addAdjustmentListener(new FloatingLabelAdjustmentListener(dataPanel)); getContentPane().add(scrollPane); }
class FloatingLabelGlyph extends JComponent { public FloatingLabelGlyph(String label, Color color, int y) { this.color = color; this.label = label; this.y = y; setVisible(true); }
public void paintComponent(Graphics g) { g.setColor(color); g.drawString(label, 0, g.getFont().getSize()); super.paintComponent(g); }
public int getY(){ return y; } int y; Color color; String label; }
class DataGlyph extends JComponent { public DataGlyph(Color color, int x, int y, int width) { this.color = color; setBounds(x, y, width, height); setVisible(true); }
public void paintComponent(Graphics g) { g.setColor(color); g.fillRect(0, 0, getWidth(), getHeight()); super.paintComponent(g); }
private int height = 10; private Color color; }
class FloatingLabelAdjustmentListener implements AdjustmentListener { public FloatingLabelAdjustmentListener(DataPanel dataPanel){ super(); this.dataPanel = dataPanel; } public void adjustmentValueChanged(AdjustmentEvent e){ FloatingLabelGlyph[] floatingLabels = dataPanel.getFloatingLabels(); for (int i = 0; i < floatingLabels.length; i++) { floatingLabels[i].setBounds((int) ((JViewport) dataPanel.getParent()) .getViewPosition().getX(), floatingLabels[i].getY(), 80, 15); } } private DataPanel dataPanel; }
class DataPanel extends JPanel { public DataPanel() { super(); setLayout(null); setSize(new Dimension(1000, 1000)); setPreferredSize(new Dimension(1000, 1000)); floatingLabels = new FloatingLabelGlyph[labels.length]; for (int i = 0; i < labels.length; i++) { add(floatingLabels[i] = new FloatingLabelGlyph(labels[i], colors[i],labelYs[i])); } add(new DataGlyph(colors[0], 150, rowYs[0], 50)); add(new DataGlyph(colors[0], 170, rowYs[1], 75)); add(new DataGlyph(colors[0], 220, rowYs[0], 100)); add(new DataGlyph(colors[1], 160, rowYs[2], 55)); add(new DataGlyph(colors[1], 960, rowYs[2], 35)); add(new DataGlyph(colors[1], 220, rowYs[2], 25)); add(new DataGlyph(colors[1], 200, rowYs[3], 33)); add(new DataGlyph(colors[2], 600, rowYs[4], 100)); add(new DataGlyph(colors[2], 900, rowYs[4], 88)); setVisible(true); }
public FloatingLabelGlyph[] getFloatingLabels(){ return floatingLabels; }
private String[] labels = new String[] { "Red Data", "Green Data", "Blue Data" }; private Color[] colors = new Color[] { Color.RED, Color.GREEN, Color.BLUE }; private FloatingLabelGlyph[] floatingLabels; private int[] rowYs = new int[] { 10, 25, 40, 55, 70 }; private int[] labelYs = new int[] { 10, 40, 70 }; }
}
********************************************************************
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|