how to rotate a rectangle in Java2D - java

I want to rotate a rectangle in a method but do not understand how to do it and tried as follows:
private void setBoundaryRotate(Rectangle b, int radio) {
AffineTransform transform = new AffineTransform();
transform.rotate(Math.toRadians(45), b.getX() + b.width/2, b.getY() + b.height/2);}
Thanks for all.

You need to call the transform() method on your transform object, passing in the co-ordinates of your rectangle in an array.

This is a little subjective, it all depends on what it is you want to achieve.
The following code uses an AffineTransform to rotate the rectangle, but in order to do so, I need to get a PathIterator and add it back to Path2D
public class SpinBox {
public static void main(String[] args) {
new SpinBox();
}
public SpinBox() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SpinPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class SpinPane extends JPanel {
private Rectangle box = new Rectangle(0, 0, 100, 100);
private float angle = 0;
public SpinPane() {
Timer timer = new Timer(1000/60, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angle += 1;
repaint();
}
});
timer.setRepeats(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth() - 1;
int height = getHeight() - 1;
int x = (width - box.width) / 2;
int y = (height - box.height) / 2;
Graphics2D g2d = (Graphics2D) g.create();
AffineTransform at = new AffineTransform();
at.rotate(Math.toRadians(angle), box.x + (box.width / 2), box.y + (box.height / 2));
PathIterator pi = box.getPathIterator(at);
Path2D path = new Path2D.Float();
path.append(pi, true);
g2d.translate(x, y);
g2d.draw(path);
g2d.dispose();
}
}
}

Related

Adding multiple MouseListeners dynamically JPanel

I am trying to add shapes onto a window using JPanel and then be able to click and drag them around the window. This works if I only have one shape; but when I add more shapes, the click and drag is very funky. It does drag but not with the mouse, it isn't proportional and doesn't drag with the mouse.
Any help is appreciated. Thanks!
public class SimpleDraw {
public static void main(String[] args) {
JFrame frame = new UMLWindow();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(30, 30, 1000, 700);
frame.getContentPane().setBackground(Color.white);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
// Display the window.
frame.setVisible(true);
}
}
class UMLWindow extends JFrame {
Squares squares = new Squares();
private static final long serialVersionUID = 1L;
public UMLWindow() {
addMenus();
}
public void addMenus() {
getContentPane().add(squares);
JMenuBar menubar = new JMenuBar();
JMenu shapes = new JMenu("Shapes");
JMenuItem rectangleMenuItem = new JMenuItem("New Rectangle");
rectangleMenuItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
squares.addSquare(10, 10, 100, 100);
}
});
shapes.add(rectangleMenuItem);
menubar.add(shapes);
setJMenuBar(menubar);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
class Squares extends JPanel {
private static final long serialVersionUID = 1L;
private List<Path2D> squares = new ArrayList<Path2D>();
// private Path2D rect = new Path2D.Double();
int currentIndex;
public void addSquare(int x, int y, int width, int height) {
Path2D rect2 = new Path2D.Double();
rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
- height / 2, width, height), true);
squares.add(rect2);
// rect = rect2;
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setOpaque(true);
this.setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
for (Path2D rect : squares) {
g2.draw(rect);
}
repaint();
}
class MyMouseAdapter extends MouseAdapter {
private boolean pressed = false;
private Point point;
#Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (int i = 0; i < squares.size(); i++) {
if (squares.get(i) != null
&& squares.get(i).contains(e.getPoint())) {
currentIndex = i;
pressed = true;
this.point = e.getPoint();
}
}
}
#Override
public void mouseDragged(MouseEvent e) {
if (pressed) {
int deltaX = e.getX() - point.x;
int deltaY = e.getY() - point.y;
squares.get(currentIndex).transform(
AffineTransform.getTranslateInstance(deltaX, deltaY));
point = e.getPoint();
repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
pressed = false;
}
}
}
Lot of problems...
Most important, no you don't want to add a bunch of MouseListeners/MouseMotionListeners to your JPanel. You only want to add one, and have it control any and all squares that the JPanel holds.
Don't put a repaint() in your paintComponent method as that's a poor way to try to create an animation loop, a loop that you have absolutely no control over. Plus there's no need. The MouseAdapter should drive all the animation by itself.
class Squares extends JPanel {
private static final long serialVersionUID = 1L;
public Squares() {
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
private List<Path2D> squares = new ArrayList<Path2D>();
// private Path2D rect = new Path2D.Double();
int currentIndex;
public void addSquare(int x, int y, int width, int height) {
Path2D rect2 = new Path2D.Double();
rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
- height / 2, width, height), true);
squares.add(rect2);
repaint(); // !!
// rect = rect2;
// !! MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
// addMouseListener(myMouseAdapter);
// addMouseMotionListener(myMouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
this.setOpaque(true);
this.setBackground(Color.WHITE);
Graphics2D g2 = (Graphics2D) g;
for (Path2D rect : squares) {
g2.draw(rect);
}
// !! repaint();
}

Add panel ontop of panel and both are visible

I'm making a music/drawing application which you free draw lines with your mouse and a TrackBar passes horizontally through it and reads the lines and uses the x and y coordinate to modify music.
The problem I'm having is that TrackBar class is a JPanel and DrawBoard class is a JPanel which I add inside a Frame. But which ever is on-top is the one that will show, what I want is for them to both show, and the TrackBar to pass on top of the lines drawn.
Below Is the source code of this 3 classes and took out some unncesesary code:
The MainFrame class where I add them (with the current setup the TrackBar doesnt appear but the Drawing board appears since it overlaps it):
public class MainFrame extends JFrame {
public static ColourToolbar colourBar;
public static TrackBar tb;
public MainFrame(){
super("VIPE by Prestige WorldWide");
// Top colour toolbar for tones
colourBar = new ColourToolbar();
this.getContentPane().add(colourBar, BorderLayout.NORTH);
// This class ImagePanel is a JPanel which I overite the paintCOmponent to have background
ImagePanel bg = new ImagePanel();
bg.setLayout(new BorderLayout());
Dimension size = getPreferredSize();
size.setSize(1024,800); //w, h
bg.setPreferredSize(size);
this.getContentPane().add(bg, BorderLayout.CENTER);
// I add the TrackBar to the ImagePanel since its the Background
tb = new TrackBar();
bg.add(tb, BorderLayout.CENTER);
// I add the drawing board but It will overlap the Trackbar
DrawBoard dboard = new DrawBoard();
bg.add(dboard, BorderLayout.CENTER);
// The control toolbar where the settings and control buttons are.
Toolbar toolBar = new Toolbar();
this.getContentPane().add(toolBar, BorderLayout.SOUTH);
}
public static void main(String[] args){
MainFrame frame = new MainFrame();
frame.setBackground(Color.WHITE);
frame.setSize(1024,768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//frame.pack();
frame.setVisible(true);
}
}
Now the TrackBar class:
public class TrackBar extends JPanel{
private TrackBarAction tba = new TrackBarAction(this);
public static int TIME = 9;
public Timer t = new Timer(TIME, tba);
public static double x = 0, y = 0, velX = 1.0, velY = 0;
private int SKIP = 120;
public TrackBar(){
this.setOpaque(false);
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
//g2d.drawRect((int)x, (int)y, 10, 800);
Rectangle2D r2d = new Rectangle2D.Double(x, y, 8.0, 800.0); // x,x, w, h
g2d.setPaint(Color.DARK_GRAY);
g2d.fill(r2d);
g2d.draw(r2d);
}
public void reset(){
t.stop();
x = 0;
y = 0;
velX = 0.5;
velY = 0;
this.repaint();
}
public void skipForward(){
if(x+SKIP <= 1024){
x += SKIP;
} else {
x = 1024 - x;
}
this.repaint();
}
public void skipBackwards(){
if(x-SKIP >= 0){
x -= SKIP;
} else {
x = 0;
}
this.repaint();
}
}
And now the DrawBoard class:
public class DrawBoard extends JPanel implements MouseListener, MouseMotionListener{
(..)
public Color currentColor;
public static boolean eraser = false;
private int xX1, yY1;
public DrawBoard(){
Graphics2D g2d = bImage.createGraphics();
g2d.dispose();
Dimension size = getPreferredSize();
size.setSize(1024,800); //w, h
setPreferredSize(size);
//status = new JLabel("default");
//add(status, BorderLayout.SOUTH);
addMouseListener(this);
addMouseMotionListener(this);
imgLabel = new JLabel(new ImageIcon(bImage)) {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
paintInLabel(g);
}
};
imgLabel.setOpaque(false);
setOpaque(false);
add(imgLabel, BorderLayout.CENTER);
}
private void paintInLabel(Graphics g) {
if(!eraser){
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getColor()); // this colour is when mouse is pressed
g2d.setStroke(new BasicStroke(STROKESIZE));
if (points.size() < 1) {
return;
}
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
}
// Where the drawing happens
#Override
public void mousePressed(MouseEvent e) {
//status.setText("you pressed down the mouse");
if(!eraser){
xX1 = e.getX();
yY1 = e.getY();
points.add(e.getPoint());
}
}
#Override
public void mouseDragged(MouseEvent e) {
//status.setText("you draged the mouse");
Graphics2D g2d = bImage.createGraphics();
// this is the eraser code
if(eraser){
//Graphics2D g2d = bImage.createGraphics();
System.out.println("eraser = true");
System.out.println("Stroke = " + STROKESIZE);
g2d.setComposite(AlphaComposite.Clear);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.drawRect(e.getX(), e.getY(), STROKESIZE, STROKESIZE);
g2d.fillRect(e.getX(), e.getY(), STROKESIZE, STROKESIZE);
// g2d.setColor(c);
imgLabel.repaint();
}else {
//g2d.setComposite();
points.add(e.getPoint());
System.out.println("point = " + e.getPoint());
imgLabel.repaint();
}
}
#Override
public void mouseReleased(MouseEvent e) {
//status.setText("you release the mouse click");
if(!eraser){
Graphics2D g2d = bImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(getColor()); // this is the final colour
g2d.setStroke(new BasicStroke(STROKESIZE));
if (points.size() >= 2) {
for (int i = 1; i < points.size(); i++) {
int x1 = points.get(i - 1).x;
int y1 = points.get(i - 1).y;
int x2 = points.get(i).x;
int y2 = points.get(i).y;
g2d.drawLine(x1, y1, x2, y2);
}
}
g2d.dispose();
points.clear();
imgLabel.repaint();
}
//imgLabel.repaint();
}
// End of where the drawing happens
public void clearDrawBoard() {
}
private Color getColor() {
return ColourToolbar.selectedColor;
}
private void setColor(Color col){
this.currentColor = col;
}
#Override
public void mouseClicked(MouseEvent e) {
//throw new UnsupportedOperationException("Not supported yet.");
}
}
BorderLayout can only have one component add to each of it a 5 positions. By adding the DrawPanel to the center position, you are effectively removing the TrackPanel.
Instead, set the layout manager of the TrackBar to BorderLayout and add the DrawPanel to it.
You could also use a JLayeredPane, but the management becomes more involved

Drawing a bounding rectangle to select what area to record

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.

JFrame on OS X with buffer strategy disables rounded corners

I'm trying to create a simple JFrame window in OS X and render a simple black square on it like so using Graphics2d:
public Start() {
running = true;
window = new JFrame("Finest Hour");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setPreferredSize(new Dimension(500, 500));
window.setSize(window.getPreferredSize());
FullScreenUtilities.setWindowCanFullScreen(window, true);
window.setIgnoreRepaint(true);
window.setVisible(true);
window.createBufferStrategy(2);
strategy = window.getBufferStrategy();
}
public static void main(String[] args) {
Start s = new Start();
s.loop();
}
public void loop() {
Random random = new Random();
while(running) {
Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(20, 20, 40, 40);
strategy.show();
}
}
However the window doesyn't seem to have rounded corners at the bottom when I use strategy.show(); :
Rendering it without the buffer strategy, i.e: Graphics2D = (Graphics2D) window.getGraphics(); produces a window with rounded corners:
I know it's a really small problem but it's annoying none the less. Any way to fix this?
Works fine for me.
public class TestMacFrame extends JFrame {
public TestMacFrame() throws HeadlessException {
super("Testing");
setSize(200, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(new PaintPane());
setVisible(true);
}
protected class PaintPane extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth() - 1;
int height = getHeight() - 1;
g.setColor(Color.BLACK);
int blockWidth = width / 2;
int blockHeight = height / 2;
int x = (width - blockWidth) / 2;
int y = (height - blockHeight) / 2;
g.fillRect(x, y, blockWidth, blockHeight);
}
}
public static void main(String[] args) {
new TestMacFrame();
}
}
Now, I have no idea what it is you're trying to, but I can tell you this:
public void loop() {
Random random = new Random();
while(running) {
Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(20, 20, 40, 40);
strategy.show();
}
}
Is a bad idea. Firstly as SoboLAN pointed out, you're trying to update a UI component out side the Event Dispatching Thread. Swing components are not Thread safe.
Secondly, this loop will eventually chew up your CPU cycles, making you application unusable as well as you overall system.
UPDATED with Animation
Here, try this. This is a really BASIC example ;)
public class TestMacFrame extends JFrame {
private float angel = 0;
private Timer timer;
public TestMacFrame() throws HeadlessException {
super("Testing");
setSize(200, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(new PaintPane());
setVisible(true);
timer = new Timer(25, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
angel += 1;
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.setInitialDelay(0);
timer.start();
}
protected class PaintPane extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth() - 1;
int height = getHeight() - 1;
g.setColor(Color.BLACK);
int blockWidth = width / 2;
int blockHeight = height / 2;
int x = (width - blockWidth) / 2;
int y = (height - blockHeight) / 2;
g2d.setTransform(AffineTransform.getRotateInstance(Math.toRadians(angel), width / 2, height / 2));
g2d.fillRect(x, y, blockWidth, blockHeight);
g2d.dispose();
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new TestMacFrame();
}
}

AWT Canvas flickering on manual resize

Just out of intellectual interest can you make a Canvas not flicker when doing a manual resize.
public class FlickerAWT extends Canvas {
public static void main(String[] args) {
Frame f = new Frame(str);
//this line change nothing
//JFrame f = new JFrame(str);
f.add(new FlickerAWT());
f.pack();
int frameWidth = f.getWidth();
int frameHeight = f.getHeight();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
f.setLocation(screenSize.width / 2 - frameWidth / 2, screenSize.height / 2 - frameHeight / 2);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
});
}
private Color bgColor; private Color contentColor;
Font f = new Font("Georgia", Font.BOLD, 16);
static String str = "AWT Canvas Resize Flickering";
public FlickerAWT() {
Random r = new Random();
bgColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
contentColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
}
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(f);
return new Dimension(fm.stringWidth(str) + 20, fm.getHeight() + 10);
}
public void paint(java.awt.Graphics g) {
g.setColor(bgColor);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(contentColor);
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
int dx = getWidth() / 2 - (fm.stringWidth(str) / 2);
int dy = getHeight() / 2 + (fm.getHeight() / 2);
g.drawString(str, dx, dy);
}
}
You can copy paste in a Java editor and run the example.
You can add this to the beginning of your main method to avoid the background flicker:
System.setProperty("sun.awt.noerasebackground", "true");
I know this question is ancient, but it came up during my search and I meanwhile found a solution:
There are two problems:
On the one hand, the update(...) method of java.awt.Container looks like the following:
public void update(Graphics g) {
if (isShowing()) {
if (! (peer instanceof LightweightPeer)) {
g.clearRect(0, 0, width, height);
}
paint(g);
}
}
I.e. it calls g.clearRect(...) to erase the current content before painting its children.
Therefore, you need to override update(...) in every descendant of java.awt.Container in your view-stack, that doesn't already do so, with something like:
public void update(Graphics g) {
if (isShowing()) paint(g);
}
Also, it seems that AWT or the JVM or whoever (haven't figured this out yet) also clears the background of the main window, independent of any Container's update-methods. To prevent this, follow #WhiteFang34's suggestion and add the following line to your code somewhere:
System.setProperty("sun.awt.noerasebackground", "true");
Only doing both of these things finally solved my flicker issues...
The key I believe is to use double buffering, and one way to possibly solve this is to use Swing which double buffers by default:
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class FlickerSwing extends JPanel {
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
private static void createAndShowGui() {
JFrame f = new JFrame(str);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new FlickerSwing());
f.setLocationRelativeTo(null);
f.pack();
f.setVisible(true);
}
private Color bgColor;
private Color contentColor;
Font f = new Font("Georgia", Font.BOLD, 16);
static String str = "Swing Resize Flickering";
public FlickerSwing() {
Random r = new Random();
bgColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
contentColor = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
setBackground(bgColor);
}
public Dimension getPreferredSize() {
FontMetrics fm = getFontMetrics(f);
return new Dimension(fm.stringWidth(str) + 20, fm.getHeight() + 10);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(contentColor);
g.setFont(f);
FontMetrics fm = g.getFontMetrics(f);
int dx = getWidth() / 2 - (fm.stringWidth(str) / 2);
int dy = getHeight() / 2 + (fm.getHeight() / 2);
g.drawString(str, dx, dy);
}
}

Categories

Resources