问题
I have a class "Map" which extends JPanel. I add it to a class that extends a JFrame.
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = Math.abs(startX - endX);
int height= Math.abs(startY - endY);
g.setColor(Color.RED);
g.fillRect(startX, startY, width, height);
}
My class "Map" also contains a label with an image in it. If the image is smalled than the window, when I draw a rectangle it is seen. In short, it is under the label.
回答1:
paintComponent
is the "bottom" of the paint chain, so anything painted here will appear below everything else.
A better solution might be to add the Map
panel to the label (setting the JLabel
's layout manager appropriately).
Or, create a "base" panel, set it's layout manager to use a OverlayLayout
manager and add the JLabel
and Map
panel to it.
This will, of course, all depend on what it is you want to achieve...
Updated with "Panel on Label" example
Basically, this takes a JLabel
, sets an icon (as the background image), set it's layout as BorderLayout
and then adds a JPanel
on to it.
Remember, JPanel
is opaque by default, so you need to make it transparent ;)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class OverlayLabel {
public static void main(String[] args) {
new OverlayLabel();
}
public OverlayLabel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JLabel background = new JLabel(new ImageIcon(ImageIO.read(new File("/path/to/image"))));
background.setLayout(new BorderLayout());
background.add(new TestPane());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(background);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setOpaque(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics g2d = (Graphics2D) g.create();
int x = (getWidth() - 20) / 2;
int y = (getHeight() - 20) / 2;
g2d.setColor(Color.RED);
g2d.fillRect(x, y, 20, 20);
g2d.dispose();
}
}
}
Updated with example of OverlayLayout
OverlayLayout
basically uses the components x/y alignment to make determinations about how best it should place the individual components
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.OverlayLayout;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class OverlayLabel {
public static void main(String[] args) {
new OverlayLabel();
}
public OverlayLabel() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JLabel background = new JLabel(new ImageIcon(ImageIO.read(new File("/path/to/image"))));
background.setAlignmentX(0.5f);
background.setAlignmentY(0.5f);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new OverlayLayout(frame.getContentPane()));
frame.add(new TestPane());
frame.add(background);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setOpaque(false);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics g2d = (Graphics2D) g.create();
int x = (getWidth() - 20) / 2;
int y = (getHeight() - 20) / 2;
g2d.setColor(Color.RED);
g2d.fillRect(x, y, 20, 20);
g2d.dispose();
}
}
}
And finally, if none of that is working for you, you could use JLayeredPane
as the base, which will allow you to determine the z-order of each component...
See How to use layered panes for more details...
来源:https://stackoverflow.com/questions/20578028/rectangle-is-not-drawn-on-top