Related
I'm trying to make it when you click the cameraButton, the graphics show, but when clicked again, it closes.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int camButtonWidth = 500;
int camButtonHeight = 33;
int camButtonX = (width - camButtonWidth) / 2;
int camButtonY = (height - camButtonHeight) - 5;
int camWidth = width - 50;
int camHeight = (height - (camButtonHeight * 2)) - 10;
int camX = (width - camWidth) / 2;
int camY = ((height - camHeight) - camButtonHeight) / 2;
Graphics2D g1 = (Graphics2D) g;
Graphics2D g2 = (Graphics2D) g;
Graphics2D g3 = (Graphics2D) g;
RoundRectangle2D camButton = new RoundRectangle2D.Double(camButtonX, camButtonY, camButtonWidth, camButtonHeight, 25, 25);
RoundRectangle2D cameras = new RoundRectangle2D.Double(camX, camY, camWidth, camHeight, 25, 25);
// Background
g1.setColor(Color.BLACK);
g1.fillRect(0, 0, width, height);
addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
if (camButton.contains(e.getPoint())) {
camUp = !camUp;
repaint();
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
// Camera Button
g2.setColor(camColor);
g2.fill(camButton);
paintCameras = camUp;
// Cameras
g3.setColor(camColor);
if (paintCameras) {
g3.fill(cameras);
}
repaint();
}
Try to change make it when you click the camera button, a graphics object shows, but when clicked again, it closes.
To get this sort of program to work you should:
Create your MouseListener in code that is only called once, such as within a constructor
Create an instance field in the class to represent the camera button, such as a Rectangle or RoundRectangle2D and give it a viable object reference
In the mouse listener, toggle the state of a boolean variable if a click occurs within the shape that represents the camera button, e.g., camUp = !camUp; as you're doing
And then call repaint().
In the paintComponent method, check the state of the boolearn variable with an if statement, and if true, draw the image inside the if statement.
Keep the mouse listener and the painting code separate and in separate methods (or constructor).
Never call repaint() within a painting method as that will cause an uncontrolled animation. If you need a Swing animation, then use a Swing Timer so that you can fully control it. I don't see the need for it here.
For example:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class GraphicsExample extends JPanel {
private static final int IMG_WIDTH = 400;
private static final int PREF_W = (3 * IMG_WIDTH) / 2;
private static final int PREF_H = PREF_W;
private static final Color BTN_COLOR = Color.RED;
private static final Color HOVER_COLOR = new Color(255, 100, 100);
private static final Color BTN_CLK_COLOR = new Color(180, 0, 0);
private static final int IMG_X = IMG_WIDTH / 2;
private static final int IMG_Y = IMG_X;
private double camX = 10;
private double camY = camX;
private double camWidth = 200;
private double camHeight = 80;
private Color buttonColor = Color.RED;
private RoundRectangle2D cameraButton = new RoundRectangle2D.Double(camX, camY, camWidth, camHeight, 25, 25);
private Image img;
private boolean showImage = false;
private JCheckBox toggleModeChkBox = new JCheckBox("Toggle Mode");
// private boolean toggleMode = true;
public GraphicsExample() {
add(toggleModeChkBox);
setPreferredSize(new Dimension(PREF_W, PREF_H));
img = createMyImage();
MouseAdapt mouseAdapt = new MouseAdapt();
addMouseListener(mouseAdapt);
addMouseMotionListener(mouseAdapt);
}
private Image createMyImage() {
BufferedImage img = new BufferedImage(IMG_WIDTH, IMG_WIDTH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setPaint(new GradientPaint(0, 0, Color.RED, 100, 100, Color.BLUE, true));
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int gap = 10;
g2.fillOval(gap, gap, IMG_WIDTH - 2 * gap, IMG_WIDTH - 2 * gap);
g2.dispose();
return img;
}
private class MouseAdapt extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
if (cameraButton.contains(e.getPoint())) {
buttonColor = BTN_CLK_COLOR;
if (toggleModeChkBox.isSelected()) {
showImage = !showImage;
} else {
showImage = true;
}
} else {
buttonColor = BTN_COLOR;
}
repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
if (cameraButton.contains(e.getPoint())) {
buttonColor = HOVER_COLOR;
} else {
buttonColor = Color.RED;
}
if (!toggleModeChkBox.isSelected()) {
showImage = false;
}
repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
if (cameraButton.contains(e.getPoint())) {
buttonColor = HOVER_COLOR;
} else {
buttonColor = Color.RED;
}
if (!toggleModeChkBox.isSelected()) {
showImage = false;
}
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(buttonColor);
g2.fill(cameraButton);
if (showImage) {
int x = (getWidth() - IMG_WIDTH) / 2;
int y = (getHeight() - IMG_WIDTH) / 2;
g2.drawImage(img, x, y, this);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
GraphicsExample mainPanel = new GraphicsExample();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
How do I draw that semi-transparent rectangle on the screen?
That cannot be a JFrame because JFrames have the usual close, minimize, maximize options in top right.
if it is indeed a swing competent, How is it drawn in thin air? Without inserting it in a JFrame whatsoever?
Please tell me what it is and how I can implement it...
The immediate idea that comes to mind is to use java.awt.Robot to capture a screen shot, paint that to frameless window. From there you can simply draw a rectangle on it
Updated with example
... Took some time ...
public class SelectionRectangle {
public static void main(String[] args) {
new SelectionRectangle();
}
public SelectionRectangle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BackgroundPane extends JPanel {
private BufferedImage background;
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
public BackgroundPane() {
selectionPane = new SelectionPane();
try {
Robot bot = new Robot();
background = bot.createScreenCapture(getScreenViewableBounds());
} catch (AWTException ex) {
Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
selectionPane = new SelectionPane();
setLayout(null);
add(selectionPane);
MouseAdapter adapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
}
#Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(background, 0, 0, this);
g2d.dispose();
}
}
public class SelectionPane extends JPanel {
private JButton button;
private JLabel label;
public SelectionPane() {
button = new JButton("Close");
setOpaque(false);
label = new JLabel("Rectangle");
label.setOpaque(true);
label.setBorder(new EmptyBorder(4, 4, 4, 4));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(SelectionPane.this).dispose();
}
});
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight());
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(new Color(128, 128, 128, 64));
g2d.fillRect(0, 0, getWidth(), getHeight());
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3);
g2d.dispose();
}
}
public static Rectangle getScreenViewableBounds() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
return getScreenViewableBounds(gd);
}
public static Rectangle getScreenViewableBounds(GraphicsDevice gd) {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
if (gd != null) {
GraphicsConfiguration gc = gd.getDefaultConfiguration();
bounds = gc.getBounds();
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= (insets.left + insets.right);
bounds.height -= (insets.top + insets.bottom);
}
return bounds;
}
}
Update with SnipIt Example
Some people have suggested using a transparent window laid over the top of the screen, this actually won't work, as transparent windows don't actually respond to mouse clicks UNLESS they have something to be painted on them that will allow the mouse event to be trapped.
It's also been suggested that you use a Window as the selection mechanism, this is a valid answer, however, I would (personally) find that to be an unsuitable solution, as you want the user to simply click and drag the selection rectangle (IMHO).
Another approach is use something like SnipIt.
public class SnipIt {
public static void main(String[] args) {
new SnipIt();
}
public SnipIt() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setUndecorated(true);
// This works differently under Java 6
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SnipItPane());
frame.setBounds(getVirtualBounds());
frame.setVisible(true);
}
});
}
public class SnipItPane extends JPanel {
private Point mouseAnchor;
private Point dragPoint;
private SelectionPane selectionPane;
public SnipItPane() {
setOpaque(false);
setLayout(null);
selectionPane = new SelectionPane();
add(selectionPane);
MouseAdapter adapter = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mouseAnchor = e.getPoint();
dragPoint = null;
selectionPane.setLocation(mouseAnchor);
selectionPane.setSize(0, 0);
}
#Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
};
addMouseListener(adapter);
addMouseMotionListener(adapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = new Rectangle(0, 0, getWidth(), getHeight());
Area area = new Area(bounds);
area.subtract(new Area(selectionPane.getBounds()));
g2d.setColor(new Color(192, 192, 192, 64));
g2d.fill(area);
}
}
public class SelectionPane extends JPanel {
private JButton button;
private JLabel label;
public SelectionPane() {
button = new JButton("Close");
setOpaque(false);
label = new JLabel("Rectangle");
label.setOpaque(true);
label.setBorder(new EmptyBorder(4, 4, 4, 4));
label.setBackground(Color.GRAY);
label.setForeground(Color.WHITE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.getWindowAncestor(SelectionPane.this).dispose();
}
});
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
label.setText("Rectangle " + getX() + "x" + getY() + "x" + getWidth() + "x" + getHeight());
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
// I've chosen NOT to fill this selection rectangle, so that
// it now appears as if you're "cutting" away the selection
// g2d.setColor(new Color(128, 128, 128, 64));
// g2d.fillRect(0, 0, getWidth(), getHeight());
float dash1[] = {10.0f};
BasicStroke dashed =
new BasicStroke(3.0f,
BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER,
10.0f, dash1, 0.0f);
g2d.setColor(Color.BLACK);
g2d.setStroke(dashed);
g2d.drawRect(0, 0, getWidth() - 3, getHeight() - 3);
g2d.dispose();
}
}
public static Rectangle getVirtualBounds() {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
return bounds;
}
}
Update Multi Monitor Support to the Example Answer from #MadProgrammer.
Without ExtendedState(JFrame.MAXIMIZED_BOTH) and pack()
public SelectionRectangle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BackgroundPane());
frame.setResizable( false );
frame.setBounds( getScreenViewableBounds() );
frame.setVisible(true);
}
});
}
public static Rectangle getScreenViewableBounds() {
GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
int minx = Integer.MAX_VALUE;
int miny = Integer.MAX_VALUE;
int maxx = Integer.MIN_VALUE;
int maxy = Integer.MIN_VALUE;
for( GraphicsDevice device : devices ) {
for( GraphicsConfiguration config : device.getConfigurations() ) {
Rectangle bounds = config.getBounds();
minx = Math.min( minx, bounds.x );
miny = Math.min( miny, bounds.y );
maxx = Math.max( maxx, bounds.x + bounds.width );
maxy = Math.max( maxy, bounds.y + bounds.height );
}
}
return new Rectangle( new Point(minx, miny), new Dimension(maxx - minx, maxy - miny) );
}
You could use a transparent, undecorated frame in order to create a basic border.
public class ScreenRectangle extends JFrame {
public ScreenRectangle() {
this.setUndecorated(true);
this.setBackground(new Color(0, 0, 0, 0.25F));
// opacity ranges 0.0-1.0 and is the fourth paramater
this.add(new DrawPanel());
}
private class DrawPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0, 0, this.getWidth(), this.getHeight());
// any other drawing
}
}
}
The frame may also need to be setOpaque, or the panel size may need to be handled, but this is the general idea of it.
I've just recently extended JPanel for use in a project which we want to appear to be more "3D". That's my bosses' way of requiring shadowing and rounded corners on components. That's been accomplished as shown on many online examples. I did it like this:
public class RoundedPanel extends JPanel
{
protected int _strokeSize = 1;
protected Color _shadowColor = Color.BLACK;
protected boolean _shadowed = true;
protected boolean _highQuality = true;
protected Dimension _arcs = new Dimension(30, 30);
protected int _shadowGap = 5;
protected int _shadowOffset = 4;
protected int _shadowAlpha = 150;
protected Color _backgroundColor = Color.LIGHT_GRAY;
public RoundedPanel()
{
super();
setOpaque(false);
}
#Override
public void setBackground(Color c)
{
_backgroundColor = c;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int shadowGap = this._shadowGap;
Color shadowColorA = new Color(_shadowColor.getRed(), _shadowColor.getGreen(), _shadowColor.getBlue(), _shadowAlpha);
Graphics2D graphics = (Graphics2D) g;
if(_highQuality)
{
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
if(_shadowed)
{
graphics.setColor(shadowColorA);
graphics.fillRoundRect(_shadowOffset, _shadowOffset, width - _strokeSize - _shadowOffset,
height - _strokeSize - _shadowOffset, _arcs.width, _arcs.height);
}
else
{
_shadowGap = 1;
}
graphics.setColor(_backgroundColor);
graphics.fillRoundRect(0, 0, width - shadowGap, height - shadowGap, _arcs.width, _arcs.height);
graphics.setStroke(new BasicStroke(_strokeSize));
graphics.setColor(getForeground());
graphics.drawRoundRect(0, 0, width - shadowGap, height - shadowGap, _arcs.width, _arcs.height);
graphics.setStroke(new BasicStroke());
}
}
I am creating a test frame with the following code:
public class UITest
{
private static JFrame mainFrame;
private static ImagePanel mainPanel;
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
mainFrame = new JFrame();
mainFrame.setVisible(true);
try
{
mainPanel = new ImagePanel(ImageIO.read(this.getClass().getResource("/content/diamondPlate_Light.jpg")));
//mainPanel.setBounds(0, 0, 800, 600);
}
catch(IOException e)
{
}
mainPanel.setLayout(null);
RoundedPanel rPanel = new RoundedPanel();
rPanel.setBounds(10, 10, 200, 200);
rPanel.setBackground(new Color(168, 181, 224));
mainPanel.add(rPanel);
rPanel = new RoundedPanel();
rPanel.setBounds(220, 10, 560, 200);
rPanel.setBackground(new Color(168, 224, 168));
mainPanel.add(rPanel);
rPanel = new RoundedPanel();
rPanel.setBounds(10, 220, 770, 300);
rPanel.setBackground(new Color(224, 168, 168));
mainPanel.add(rPanel);
mainFrame.setSize(800, 600);
mainFrame.getContentPane().add(mainPanel);
}
});
}
}
And it results in this (sans the background image of the JFrame's contentPane:
What I would really like to do is generate the red, green, and blue panels with the rounded corners, but filled by a different image instead of the Color. I still want the properly rounded corners, but I'm unsure of how to do this.
If I've got a large texture, can I simply "clip" a piece of it out in the size and shape of the RoundedPanel? I need to evaluate this, since it just occurred to me as I typed, but if I can create a piece of geometry like what is used in graphics.fillRoundRect(...) and then clip the image, this could work.
Are there any other ways of doing this that I'm missing? I'd appreciate any feedback you might be able to offer. Thanks.
Edit:
Based upon the idea in the selected solution below, I've got the following results:
It needs to be whipped into shape for production and the background images are poorly chosen, but as a demo, the following RoundedPanel code gets us to the above results:
public class RoundedPanel extends JPanel
{
protected int strokeSize = 1;
protected Color _shadowColor = Color.BLACK;
protected boolean shadowed = true;
protected boolean _highQuality = true;
protected Dimension _arcs = new Dimension(30, 30);
protected int _shadowGap = 5;
protected int _shadowOffset = 4;
protected int _shadowAlpha = 150;
protected Color _backgroundColor = Color.LIGHT_GRAY;
protected BufferedImage image = null;
public RoundedPanel(BufferedImage img)
{
super();
setOpaque(false);
if(img != null)
{
image = img;
}
}
#Override
public void setBackground(Color c)
{
_backgroundColor = c;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
int width = getWidth();
int height = getHeight();
int shadowGap = this._shadowGap;
Color shadowColorA = new Color(_shadowColor.getRed(), _shadowColor.getGreen(), _shadowColor.getBlue(), _shadowAlpha);
Graphics2D graphics = (Graphics2D) g;
if(_highQuality)
{
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
if(shadowed)
{
graphics.setColor(shadowColorA);
graphics.fillRoundRect(_shadowOffset, _shadowOffset, width - strokeSize - _shadowOffset,
height - strokeSize - _shadowOffset, _arcs.width, _arcs.height);
}
else
{
_shadowGap = 1;
}
RoundRectangle2D.Float rr = new RoundRectangle2D.Float(0, 0, (width - shadowGap), (height - shadowGap), _arcs.width, _arcs.height);
Shape clipShape = graphics.getClip();
if(image == null)
{
graphics.setColor(_backgroundColor);
graphics.fill(rr);
}
else
{
RoundRectangle2D.Float rr2 = new RoundRectangle2D.Float(0, 0, (width - strokeSize - shadowGap), (height - strokeSize - shadowGap), _arcs.width, _arcs.height);
graphics.setClip(rr2);
graphics.drawImage(this.image, 0, 0, null);
graphics.setClip(clipShape);
}
graphics.setColor(getForeground());
graphics.setStroke(new BasicStroke(strokeSize));
graphics.draw(rr);
graphics.setStroke(new BasicStroke());
}
}
Thanks for the help.
Try "clipping area" (see the g.setClip() call):
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(new Dimension(600, 400));
f.getContentPane().setLayout(null);
RoundPanel rp = new RoundPanel();
rp.setBounds(100, 50, 400, 300);
f.getContentPane().add(rp);
f.setVisible(true);
}
static class RoundPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
// Prepare a red rectangle
BufferedImage bi = new BufferedImage(400, 300, BufferedImage.TYPE_INT_ARGB);
Graphics2D gb = bi.createGraphics();
gb.setPaint(Color.RED);
gb.fillRect(0, 0, 400, 300);
gb.dispose();
// Set a rounded clipping region:
RoundRectangle2D r = new RoundRectangle2D.Float(0, 0, 400, 300, 20, 20);
g.setClip(r);
// Draw the rectangle (and see whether it has round corners)
g.drawImage(bi, 0, 0, null);
}
}
Beware of the restrictions mentioned in the API doc for Graphics.setClip:
Sets the current clipping area to an arbitrary clip shape. Not all objects that implement the Shape interface can be used to set the clip. The only Shape objects that are guaranteed to be supported are Shape objects that are obtained via the getClip method and via Rectangle objects.
I was asking question about Translucent JFrame border (see here) and I got very good answers, but unfortunatelly, given answers work perfectly only on JDK 6, but not 7. Any ideas how to make it work with JDK 7?
In JDK 6 it looks like this:
And JDK 7:
And my code looks like this:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.border.AbstractBorder;
public class ShadowBorder extends AbstractBorder {
private static final int RADIUS = 30;
private static BufferedImage shadowTop;
private static BufferedImage shadowRight;
private static BufferedImage shadowBottom;
private static BufferedImage shadowLeft;
private static BufferedImage shadowTopLeft;
private static BufferedImage shadowTopRight;
private static BufferedImage shadowBottomLeft;
private static BufferedImage shadowBottomRight;
private static boolean shadowsLoaded = false;
public ShadowBorder() {
if (!shadowsLoaded) {
try {
shadowTop = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-top.png"));
shadowRight = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-right.png"));
shadowBottom = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-bottom.png"));
shadowLeft = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-left.png"));
shadowTopLeft = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-top-left.png"));
shadowTopRight = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-top-right.png"));
shadowBottomLeft = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-bottom-left.png"));
shadowBottomRight = ImageIO.read(getClass().getResource("/cz/vutbr/fit/assets/shadow-bottom-right.png"));
shadowsLoaded = true;
} catch (IOException ex) {
Logger.getLogger(ShadowBorder.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
#Override
public boolean isBorderOpaque() {
return false;
}
#Override
public Insets getBorderInsets(Component c) {
return new Insets(RADIUS, RADIUS, RADIUS, RADIUS);
}
#Override
public Insets getBorderInsets(Component c, Insets insets) {
insets.top = RADIUS;
insets.left = RADIUS;
insets.bottom = RADIUS;
insets.right = RADIUS;
return insets;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, 1f));
int recWidth = width - (2 * RADIUS);
int recHeight = height - (2 * RADIUS);
int recX = width - RADIUS;
int recY = height - RADIUS;
//edges
g2d.drawImage(shadowTop.getScaledInstance(recWidth, RADIUS, Image.SCALE_REPLICATE), RADIUS, 0, null);
g2d.drawImage(shadowRight.getScaledInstance(RADIUS, recHeight, Image.SCALE_REPLICATE), recX, RADIUS, null);
g2d.drawImage(shadowBottom.getScaledInstance(recWidth, RADIUS, Image.SCALE_REPLICATE), RADIUS, recY, null);
g2d.drawImage(shadowLeft.getScaledInstance(RADIUS, recHeight, Image.SCALE_REPLICATE), 0, RADIUS, null);
//corners
g2d.drawImage(shadowTopLeft, 0, 0, null);
g2d.drawImage(shadowTopRight, recX, 0, null);
g2d.drawImage(shadowBottomLeft, 0, recY, null);
g2d.drawImage(shadowBottomRight, recX, recY, null);
}
}
Thanks a lot!
I've just solved my problem. The problem was, that JDK 7 implements AWTUtilities.setWindowOpaque() method from JDK6 in setBackground() method and I was (NetBeans did :-)) setting default background for JFrame in different place, so setting background to new Color(0, 0, 0, 0); makes JFrame transparent and all goes well now.
For whoever stumbles upon this thread and wants his own transparent window, I devised this example. With how little information is available on the web, I almost had to break a leg to come up with something just works, and doesn't use image files or anything. (Combined from different examples on this site)
public class GradientTranslucentWindowDemo
{
public static void main(String[] args)
{
// Create the GUI on the event-dispatching thread
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
final JFrame f = new JFrame("Per-pixel translucent window");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setUndecorated(true);
f.setBackground(new Color(0, 0, 0, 0));
final BufferedImage backrgoundImage = makeBackrgoundImage(400, 400);
JPanel panel = new JPanel()
{
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (g instanceof Graphics2D)
{
g.drawImage(backrgoundImage, 0, 0, null);
}
}
};
panel.setOpaque(false);
f.setContentPane(panel);
f.setLayout(new GridBagLayout()); // Centers the button
f.add(new JButton(new AbstractAction("Close")
{
#Override
public void actionPerformed(ActionEvent e)
{
f.dispose();
}
}));
f.setBounds(100, 100, 400, 400);
f.setVisible(true);
}
});
}
static BufferedImage makeBackrgoundImage(int w, int h)
{
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// Draw something transparent
Graphics2D g = img.createGraphics();
g.setPaint(new RadialGradientPaint(new Point2D.Float(w / 2, h / 2), (w + h) / 4, new float[]{0, 1}, new Color[]{Color.RED, new Color(1f, 0, 0, 0)}));
g.fillRect(0, 0, w, h);
g.setPaint(Color.RED);
g.drawRect(0, 0, w - 1, h - 1);
g.dispose();
return img;
}
}
I inspired by MeBigFatGuy interesting question, in this conection I have very specific question about Graphisc2D, how to change BackGround Color by depends if is JTables Row visible in the JViewPort,
1) if 1st. & last JTables Row will be visible in the JViewPort, then BackGround would be colored to the Color.red
2) if 1st. & last JTables Row will not be visible in the JViewPort, then BackGround would be colored to the Color.whatever
from SSCCE
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.RepaintManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableModel;
/*
https://stackoverflow.com/questions/1249278/
how-to-disable-the-default-painting-behaviour-of-wheel-scroll-event-on-jscrollpan
*
and
*
https://stackoverflow.com/questions/8195959/
swing-jtable-event-when-row-is-visible-or-when-scrolled-to-the-bottom
*/
public class ViewPortFlickering {
private JFrame frame = new JFrame("Table");
private JViewport viewport = new JViewport();
private Rectangle RECT = new Rectangle();
private Rectangle RECT1 = new Rectangle();
private JTable table = new JTable(50, 3);
private javax.swing.Timer timer;
private int count = 0;
public ViewPortFlickering() {
GradientViewPort tableViewPort = new GradientViewPort(table);
viewport = tableViewPort.getViewport();
viewport.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
RECT = table.getCellRect(0, 0, true);
RECT1 = table.getCellRect(table.getRowCount() - 1, 0, true);
Rectangle viewRect = viewport.getViewRect();
if (viewRect.intersects(RECT)) {
System.out.println("Visible RECT -> " + RECT);
} else if (viewRect.intersects(RECT1)) {
System.out.println("Visible RECT1 -> " + RECT1);
} else {
//
}
}
});
frame.add(tableViewPort);
frame.setPreferredSize(new Dimension(600, 300));
frame.pack();
frame.setLocation(50, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RepaintManager.setCurrentManager(new RepaintManager() {
#Override
public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
Container con = c.getParent();
while (con instanceof JComponent) {
if (!con.isVisible()) {
return;
}
if (con instanceof GradientViewPort) {
c = (JComponent) con;
x = 0;
y = 0;
w = con.getWidth();
h = con.getHeight();
}
con = con.getParent();
}
super.addDirtyRegion(c, x, y, w, h);
}
});
frame.setVisible(true);
start();
}
private void start() {
timer = new javax.swing.Timer(100, updateCol());
timer.start();
}
public Action updateCol() {
return new AbstractAction("text load action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("updating row " + (count + 1));
TableModel model = table.getModel();
int cols = model.getColumnCount();
int row = 0;
for (int j = 0; j < cols; j++) {
row = count;
table.changeSelection(row, 0, false, false);
timer.setDelay(100);
Object value = "row " + (count + 1) + " item " + (j + 1);
model.setValueAt(value, count, j);
}
count++;
if (count >= table.getRowCount()) {
timer.stop();
table.changeSelection(0, 0, false, false);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
table.clearSelection();
}
});
}
}
};
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ViewPortFlickering viewPortFlickering = new ViewPortFlickering();
}
});
}
}
class GradientViewPort extends JScrollPane {
private static final long serialVersionUID = 1L;
private final int h = 50;
private BufferedImage img = null;
private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB);
private JViewport viewPort;
public GradientViewPort(JComponent com) {
super(com);
viewPort = this.getViewport();
viewPort.setScrollMode(JViewport.BLIT_SCROLL_MODE);
viewPort.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
viewPort.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
Graphics2D g2 = shadow.createGraphics();
g2.setPaint(new Color(250, 150, 150));
g2.fillRect(0, 0, 1, h);
g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h,
new Color(0.5f, 0.8f, 0.8f, 0.5f)));
g2.fillRect(0, 0, 1, h);
g2.dispose();
}
#Override
public void paint(Graphics g) {
if (img == null || img.getWidth() != getWidth() || img.getHeight() != getHeight()) {
img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = img.createGraphics();
super.paint(g2);
Rectangle bounds = getViewport().getVisibleRect();
g2.scale(bounds.getWidth(), -1);
int y = (getColumnHeader() == null) ? 0 : getColumnHeader().getHeight();
g2.drawImage(shadow, bounds.x, -bounds.y - y - h, null);
g2.scale(1, -1);
g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h + y, null);
g2.dispose();
g.drawImage(img, 0, 0, null);
}
}
since I search for different suggestion I closed this question with my original knowledges about Graphics
based on code
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
//import java.awt.image.ColorModel; // I don't know how to use that
//import java.awt.image.SampleModel;// I don't know how to use that
import javax.swing.*;
import javax.swing.RepaintManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.TableModel;
public class ViewPortFlickeringOriginal {
private JFrame frame = new JFrame("Table");
private JViewport viewport = new JViewport();
private Rectangle RECT = new Rectangle();
private Rectangle RECT1 = new Rectangle();
private JTable table = new JTable(50, 3);
private javax.swing.Timer timer;
private int count = 0;
private boolean topOrBottom = false;
private GradientViewPortOriginal tableViewPort;
public ViewPortFlickeringOriginal() {
tableViewPort = new GradientViewPortOriginal(table);
viewport = tableViewPort.getViewport();
viewport.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (tableViewPort.bolStart) {
RECT = table.getCellRect(0, 0, true);
RECT1 = table.getCellRect(table.getRowCount() - 1, 0, true);
Rectangle viewRect = viewport.getViewRect();
if (viewRect.intersects(RECT)) {
System.out.println("Visible RECT -> " + RECT);
tableViewPort.paintBackGround(new Color(250, 150, 150));
} else if (viewRect.intersects(RECT1)) {
System.out.println("Visible RECT1 -> " + RECT1);
tableViewPort.paintBackGround(new Color(150, 250, 150));
} else {
System.out.println("Visible RECT1 -> ???? ");
tableViewPort.paintBackGround(new Color(150, 150, 250));
}
}
}
});
frame.add(tableViewPort);
frame.setPreferredSize(new Dimension(600, 300));
frame.pack();
frame.setLocation(50, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RepaintManager.setCurrentManager(new RepaintManager() {
#Override
public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
Container con = c.getParent();
while (con instanceof JComponent) {
if (!con.isVisible()) {
return;
}
if (con instanceof GradientViewPortOriginal) {
c = (JComponent) con;
x = 0;
y = 0;
w = con.getWidth();
h = con.getHeight();
}
con = con.getParent();
}
super.addDirtyRegion(c, x, y, w, h);
}
});
frame.setVisible(true);
start();
}
private void start() {
timer = new javax.swing.Timer(100, updateCol());
timer.start();
}
public Action updateCol() {
return new AbstractAction("text load action") {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("updating row " + (count + 1));
TableModel model = table.getModel();
int cols = model.getColumnCount();
int row = 0;
for (int j = 0; j < cols; j++) {
row = count;
table.changeSelection(row, 0, false, false);
timer.setDelay(100);
Object value = "row " + (count + 1) + " item " + (j + 1);
model.setValueAt(value, count, j);
}
count++;
if (count >= table.getRowCount()) {
timer.stop();
table.changeSelection(0, 0, false, false);
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
table.clearSelection();
tableViewPort.bolStart = true;
}
});
}
}
};
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ViewPortFlickeringOriginal viewPortFlickering = new ViewPortFlickeringOriginal();
}
});
}
}
class GradientViewPortOriginal extends JScrollPane {
private static final long serialVersionUID = 1L;
private final int h = 50;
private BufferedImage img = null;
private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB);
private JViewport viewPort;
public boolean bolStart = false;
public GradientViewPortOriginal(JComponent com) {
super(com);
viewPort = this.getViewport();
viewPort.setScrollMode(JViewport.BLIT_SCROLL_MODE);
viewPort.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
viewPort.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
paintBackGround(new Color(250, 150, 150));
}
public void paintBackGround(Color g) {
Graphics2D g2 = shadow.createGraphics();
g2.setPaint(g);
g2.fillRect(0, 0, 1, h);
g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h,
new Color(0.1f, 0.8f, 0.8f, 0.5f)));
g2.fillRect(0, 0, 1, h);
g2.dispose();
}
#Override
public void paint(Graphics g) {
if (img == null || img.getWidth() != getWidth() || img.getHeight() != getHeight()) {
img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = img.createGraphics();
super.paint(g2);
Rectangle bounds = getViewport().getVisibleRect();
g2.scale(bounds.getWidth(), -1);
int y = (getColumnHeader() == null) ? 0 : getColumnHeader().getHeight();
g2.drawImage(shadow, bounds.x, -bounds.y - y - h, null);
g2.scale(1, -1);
g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h + y, null);
g2.dispose();
g.drawImage(img, 0, 0, null);
}
}
Something like this... a bit of a hack.
class GradientViewPort extends JScrollPane {
private static final long serialVersionUID = 1L;
private final int h = 50;
private BufferedImage img = null;
private BufferedImage imgBottom = null;
private BufferedImage shadow = new BufferedImage(1, h,
BufferedImage.TYPE_INT_ARGB);
private BufferedImage shadowBottom = new BufferedImage(1, h,
BufferedImage.TYPE_INT_ARGB);
private JViewport viewPort;
public GradientViewPort(JComponent com) {
super(com);
viewPort = this.getViewport();
viewPort.setScrollMode(JViewport.BLIT_SCROLL_MODE);
viewPort.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
viewPort.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
createShadow(new Color(250, 150, 150),shadow);
createShadow(Color.BLUE,shadowBottom);
}
private void createShadow(Color color, BufferedImage shadow) {
Graphics2D g2 = shadow.createGraphics();
g2.setPaint(color);
g2.fillRect(0, 0, 1, h);
g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h,
new Color(0.5f, 0.8f, 0.8f, 0.5f)));
g2.fillRect(0, 0, 1, h);
g2.dispose();
}
#Override
public void paint(Graphics g) {
paintTop(g,img);
paintBottom(g,imgBottom);
}
private void paintBottom(Graphics g,BufferedImage img) {
if (img == null || img.getWidth() != getWidth()
|| img.getHeight() != getHeight()) {
img = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = img.createGraphics();
//super.paint(g2);
Rectangle bounds = getViewport().getVisibleRect();
g2.scale(bounds.getWidth(), -1);
int y = (getColumnHeader() == null) ? 0 : getColumnHeader().getHeight();
//g2.drawImage(shadowBottom, bounds.x, -bounds.y - y - h, null);
g2.scale(1, -1);
g2.drawImage(shadowBottom, bounds.x, bounds.y + bounds.height - h + y, null);
g2.dispose();
g.drawImage(img, 0, 0, null);
}
private void paintTop(Graphics g,BufferedImage img) {
if (img == null || img.getWidth() != getWidth()
|| img.getHeight() != getHeight()) {
img = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = img.createGraphics();
super.paint(g2);
Rectangle bounds = getViewport().getVisibleRect();
g2.scale(bounds.getWidth(), -1);
int y = (getColumnHeader() == null) ? 0 : getColumnHeader().getHeight();
g2.drawImage(shadow, bounds.x, -bounds.y - y - h, null);
g2.scale(1, -1);
//g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h + y, null);
g2.dispose();
g.drawImage(img, 0, 0, null);
}
EDIT fixed the code so when first and last row are in the view port the color is red when they are not the color is blue.
class GradientViewPort extends JScrollPane {
private static final long serialVersionUID = 1L;
private final int h = 50;
private BufferedImage imgRed = null;
private BufferedImage imgBlue = null;
private BufferedImage shadowRed = new BufferedImage(1, h,
BufferedImage.TYPE_INT_ARGB);
private BufferedImage shadowBlue = new BufferedImage(1, h,
BufferedImage.TYPE_INT_ARGB);
private JViewport viewPort;
private boolean recVisible = true;
public GradientViewPort(JComponent com) {
super(com);
viewPort = this.getViewport();
viewPort.setScrollMode(JViewport.BLIT_SCROLL_MODE);
viewPort.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE);
viewPort.setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
createShadow(new Color(250, 150, 150),shadowRed);
createShadow(Color.BLUE,shadowBlue);
final JTable table = (JTable) com;
viewport.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
Rectangle RECT = table.getCellRect(0, 0, true);
Rectangle viewRect = viewport.getViewRect();
if (viewRect.intersects(RECT)) {
System.out.println("Visible RECT -> " + RECT);
recVisible = true;
} else {
recVisible = false;
}
}
});
}
private void createShadow(Color color, BufferedImage shadow) {
Graphics2D g2 = shadow.createGraphics();
g2.setPaint(color);
g2.fillRect(0, 0, 1, h);
g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h,
new Color(0.5f, 0.8f, 0.8f, 0.5f)));
g2.fillRect(0, 0, 1, h);
g2.dispose();
}
#Override
public void paint(Graphics g) {
if(recVisible){
paintShadow(g,imgRed,shadowRed);
} else {
paintShadow(g,imgBlue,shadowBlue);
}
}
private void paintShadow(Graphics g,BufferedImage img, BufferedImage shadow) {
if (img == null || img.getWidth() != getWidth()
|| img.getHeight() != getHeight()) {
img = new BufferedImage(getWidth(), getHeight(),
BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2 = img.createGraphics();
super.paint(g2);
Rectangle bounds = getViewport().getVisibleRect();
g2.scale(bounds.getWidth(), -1);
int y = (getColumnHeader() == null) ? 0 : getColumnHeader().getHeight();
g2.drawImage(shadow, bounds.x, -bounds.y - y - h, null);
g2.scale(1, -1);
g2.drawImage(shadow, bounds.x, bounds.y + bounds.height - h + y, null);
g2.dispose();
g.drawImage(img, 0, 0, null);
}
}