I want the image to stay in the upper left corner of jscrollpane, while scrolling

I have a JPanel in JScrollpane. I am drawing a BufferedImage that I am displaying on a JPanel. In the upper left corner of JScrollpane, I want an image that always stays in that corner when I scroll down to see the rest of my JPanel. Here is the paintComponent method for Jpanel:

@Override public void paintComponent(Graphics g){ super.paintComponent(g); if (bufferedImage != null){ g.drawImage(bufferedImage, 0, 0, this); Point p = parent.getViewPosition(); System.out.println("paintComponent(): "+ px + "," + py); g.setColor(Color.RED); g.fillRect(px + 20, py + 20, 200, 200); } } 

Where parent.getViewPosition () gives me scrollPane.getViewport (). getViewPosition (). When I start, I see a buffered image with a red rectangle in the upper left corner. When I scroll down, I see the rest of the buffered image, but the red rectangle moves up and then disappears and does not come back again when I scroll up. In the console, I see that the p point changes when I scroll:

 paintComponent(): 0,0 paintComponent(): 0,10 paintComponent(): 0,20 paintComponent(): 0,30 paintComponent(): 0,40 paintComponent(): 0,50 

Can someone help me with this problem?

+4
source share
5 answers

You can use the glass panel to do this and tell it to draw its image in a place that depends on the location of the viewing area. For instance:

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import javax.swing.*; @SuppressWarnings("serial") public class ScrollImgGlass extends JPanel { private static final int BI_W = 40; private static final int BI_H = BI_W; private static final String[] DATA = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Zero" }; private BufferedImage img = null; private JViewport viewport; public ScrollImgGlass(JViewport viewport) { setOpaque(false); this.viewport = viewport; img = new BufferedImage(BI_W, BI_H, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setColor(Color.red); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.fillOval(0, 0, BI_W, BI_H); g2.dispose(); } @Override protected void paintComponent(Graphics g) { Point vpLocation = viewport.getLocationOnScreen(); Point gpLocation = getLocationOnScreen(); int x = vpLocation.x - gpLocation.x; int y = vpLocation.y - gpLocation.y; super.paintComponent(g); if (img != null) { g.drawImage(img, x, y, this); } } private static void createAndShowGui() { JList<String> jList = new JList<String>(DATA); jList.setOpaque(false); JViewport viewport = new JViewport(); JScrollPane scrollpane = new JScrollPane(); scrollpane.setViewport(viewport); viewport.setView(jList); ScrollImgGlass glass = new ScrollImgGlass(viewport); JFrame frame = new JFrame("ScrollImg"); frame.setGlassPane(glass); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(scrollpane, BorderLayout.CENTER); // just to show that this works if the viewport is shifted over frame.getContentPane().add(Box.createRigidArea(new Dimension(20, 20)), BorderLayout.NORTH); frame.getContentPane().add(Box.createRigidArea(new Dimension(20, 20)), BorderLayout.WEST); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); glass.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } 

What would be displayed as:

enter image description here

+4
source

As MadProgrammer suggested, JLayer really works:

 import java.awt.*; import javax.swing.*; import javax.swing.plaf.*; public class FixedImageLayerUI extends LayerUI<JComponent> { @Override public void paint(Graphics g, JComponent c) { super.paint(g, c); Graphics2D g2 = (Graphics2D) g.create(); g2.setColor( Color.RED ); g2.fillOval(0, 0, 10, 10); g2.dispose(); } private static void createAndShowUI() { String[] data = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; JList<String> list = new JList<String>( data ); JScrollPane scrollPane = new JScrollPane( list ); LayerUI<JComponent> layerUI = new FixedImageLayerUI(); JLayer<JComponent> layer = new JLayer<JComponent>(scrollPane, layerUI); JFrame frame = new JFrame("FixedImage"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add( layer ); frame.pack(); frame.setLocationByPlatform( true ); frame.setVisible( true ); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } 

Also, as MadProgrammer noted, overriding the JScrollPane drawing method does not work. However, if you make the JList opaque, it works:

 import java.awt.*; import javax.swing.*; import javax.swing.plaf.*; public class FixedImageScrollPane { private static void createAndShowUI() { String[] data = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; JList<String> list = new JList<String>( data ); list.setOpaque( false ); JScrollPane scrollPane = new JScrollPane( list ) { @Override public void paint(Graphics g) { super.paint(g); g.setColor( Color.RED ); g.fillOval(0, 0, 10, 10); } }; JFrame frame = new JFrame("FixedImage"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add( scrollPane ); frame.pack(); frame.setLocationByPlatform( true ); frame.setVisible( true ); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { createAndShowUI(); } }); } } 
+4
source

Do not place the image in a panel that scrolls. Place it in another panel and place the two panels with the layout manager.

I suggest looking at BorderLayout; it has areas in n, s, e, and w and one in the center, but you don't have to use all of them (very rarely all of them are used). You can create a JPanel, set its layout manager to BorderLayout, place the panel containing your image in the NORTH part of it, and put your scroll panel in CENTER. As a free bonus, your center JPanel will stretch in both dimensions when / if the window size changes because BorderLayout works.

+1
source

Somewhere in your code you are creating a JScrollPane.

Change

  final JScrollPane scrollpane = new JScrollPane(); 

To:

  final JScrollPane scrollpane = new JScrollPane() { @Override public void paint(final Graphics g) { super.paint(g); // Put you drawing here...example, draw a geen dot... g.setColor(Color.GREEN); g.fillOval(0, 0, 30, 30); } }; 

EDIT: For comments, setOpaque (false) must be done for the object placed in JScrollPane.

Example:

  list.setOpaque(false); scrollpane.setViewportView(list); 
+1
source

OK, the following code works with JTabbedPane. I had to add a component panel to a panel in a tabbed panel because I get an exception from the getLocationOnScreen () method when the panel is not displayed on the screen.

 public class GlassFrame { private JPanel panel; private JScrollPane scrollPane; private BufferesImage img; public GlassFrame() { panel = new JPanel(){ @Override public void paintComponent(Graphics g){ super.paintComponent(g); img = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setPaint(Color.WHITE); Rectangle2D rect = new Rectangle2D.Float(0, 0, 420, 420); g2.fill(rect); g2.setPaint(Color.BLACK); for (int i = 0; i <= 10; i++) { g2.draw(new Line2D.Float(10 + i * 40,10,10 + i * 40,410)); g2.draw(new Line2D.Float(10,10 + i * 40,410,10 + i * 40)); } g2.dispose(); g.drawImage(img, 0, 0, this); } }; panel.setPreferredSize(new Dimension(420, 420)); panel.setOpaque(false); scrollPane = new JScrollPane(panel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); scrollPane.getVerticalScrollBar().setUnitIncrement(10); JFrame frame = new JFrame("ScrollPane and GlassPane"); final GlassPane glass = new GlassPane(scrollPane.getViewport()); frame.setGlassPane(glass); JTabbedPane tab = new JTabbedPane(); JPanel panelInTab = new JPanel(); panelInTab.setLayout(new BorderLayout()); tab.add("first tab", panelInTab); tab.add("second tab", new JPanel()); panelInTab.add(scrollPane, BorderLayout.CENTER); panelInTab.add(new JButton("testbutton"), BorderLayout.NORTH); panelInTab.addComponentListener(new ComponentAdapter() { @Override public void componentShown(ComponentEvent arg0) { glass.setVisible(true); } @Override public void componentHidden(ComponentEvent arg0) { glass.setVisible(false); } }); frame.getContentPane().add(tab); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setPreferredSize(new Dimension(300, 400)); frame.pack(); frame.setLocation(200, 200); frame.setVisible(true); glass.setVisible(true); } class GlassPane extends JPanel{ private JViewport viewport; private BufferedImage image = null; public GlassPane(JViewport viewport){ setOpaque(false); this.viewport = viewport; image = new BufferedImage(58, 58, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); g2.setColor(Color.red); g2.setStroke(new BasicStroke(3.0f)); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.drawOval(5, 5, 50, 50); g2.dispose(); } @Override protected void paintComponent(Graphics g) { Point vpLocation = viewport.getLocationOnScreen(); Point gpLocation = getLocationOnScreen(); int x = vpLocation.x - gpLocation.x; int y = vpLocation.y - gpLocation.y; super.paintComponent(g); if (image != null) { g.drawImage(image, x, y, this); } } } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { GlassFrame frame = new GlassFrame(); } }); } } 
0
source

All Articles