I am attempting to make a drawing pad using Graphics2D where I draw a line from two Points, a startPoint and an endPoint, within the MouseMotionlistener method mouseDragged, but whenever I add this line, it appears to be really jagged and rough. I have used this to help with AntiAliasing but it seems to do nothing.
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
but it does not help whatsoever for high strokevalues.
This is my code for drawing.
public void mouseDragged(MouseEvent e) {
//sets up graphics2d object
g2 = (Graphics2D)getGraphics();
g2.setStroke(new BasicStroke(strokeSize));
g2.setColor(color);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//draws line using points and shapes
endPoint = e.getPoint();
Shape line = new Line2D.Double(beginPoint, endPoint);
g2.draw(line);
beginPoint = endPoint;
beginPoint is given a value within mousePressed
There are lots of (really cool) rendering hints! I would recommend you start playing around with all of them and see what combinations give you the desired results!
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Remember, graphics is a shared context, when you make changes
// to it, you should also undo them. To this end, we use create/dispose
// which takes a snapshot of the current state and restores it at the
// end.
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.setColor(Color.BLACK);
g2.drawLine(0, 0, getWidth(), getHeight());
g2.drawLine(getWidth(), 0, 0, getHeight());
g2.dispose();
}
}
}
Warning
g2 = (Graphics2D)getGraphics(); is a very, very bad idea and isn't how custom painting is suppose to work.
getGraphics is nothing more then a snapshot of what was last painted during the last paint pass and will be invalidated on the next paint pass.
I would highly recommend reading through Performing Custom Painting and Painting in AWT and Swing to get a better understanding of how painting in Swing works and how you're suppose to work with it.
Drawing with the mouse is not a uncommon question and has any number of answers. I'd recommend having a looking around at some of the other question/answers to see how this might be done and adopt them to your needs
Related
I have searched everywhere and I just cant find the answer.
How do I rotate a Rectangle in java?
Here is some of my code:
package net.chrypthic.Space;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Space extends JPanel implements ActionListener{
Timer time;
public Space()
{
setVisible(true);
setFocusable(true);
addMouseMotionListener(new ML());
addMouseListener(new ML());
addKeyListener(new AL());
time=new Timer(5, this);
time.start();
}
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.WHITE);
Rectangle rect2 = new Rectangle(100, 100, 20, 20);
g2d.draw(rect2);
g2d.fill(rect2);
}
public void actionPerformed(ActionEvent ae) {
repaint();
}
public class AL extends KeyAdapter
{
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
}
public class ML extends MouseAdapter
{
public void mouseMoved(MouseEvent e) {
}
public void mousePressed(MouseEvent e){
}
}
}
I tried g2d.rotate(100D); but it didnt work.
Thanks in advance.
Here's my edited code:
package net.chrypthic.Space;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Space extends JPanel implements ActionListener{
Timer time;
public Space()
{
setVisible(true);
setFocusable(true);
setSize(640, 480);
setBackground(Color.BLACK);
time=new Timer(5, this);
time.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
Rectangle rect1 = new Rectangle(100, 100, 20, 20);
g2d.setColor(Color.WHITE);
g2d.translate(rect1.x+(rect1.width/2), rect1.y+(rect1.height/2));
g2d.rotate(Math.toRadians(90));
g2d.draw(rect1);
g2d.fill(rect1);
}
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
For images you have to use drawImage method of Graphics2D with the relative AffineTransform.
For shape you can rotate Graphics2D itself:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.WHITE);
Rectangle rect2 = new Rectangle(100, 100, 20, 20);
g2d.rotate(Math.toRadians(45));
g2d.draw(rect2);
g2d.fill(rect2);
}
And btw, you should override paintComponent method instead of paint.
Citing JComponent's API:
Invoked by Swing to draw components. Applications should not invoke
paint directly, but should instead use the repaint method to schedule
the component for redrawing.
This method actually delegates the work of painting to three
protected methods: paintComponent, paintBorder, and paintChildren.
They're called in the order listed to ensure that children appear on
top of component itself. Generally speaking, the component and its
children should not paint in the insets area allocated to the border.
Subclasses can just override this method, as always. A subclass that
just wants to specialize the UI (look and feel) delegate's paint
method should just override paintComponent.
Remember also than when you perform an affine transformation, like a rotation, the object is implicitly rotated around the axis origin. So if your intent is to rotate it around an arbitrary point, you should before translating it back to the origin, rotate it, and then re-traslating it to the desired point.
public void draw(Graphics2D g) {
Graphics2D gg = (Graphics2D) g.create();
gg.rotate(angle, rect.x + rect.width/2, rect.y + rect.height/2);
gg.drawRect(rect.x, rect.y, rect.width, rect.height);
gg.dispose();
gg = (Graphics2D) g.create();
... other stuff
}
Graphics.create() and Graphics.dispose() allow you to save the current transformation parameters (as well as current font, stroke, paint, etc), and to restore them later. It is the equivalent of glPushMatrix() and glPopMatrix() in OpenGL.
You can also apply an inverse rotation once you drew the rectangle to revert the transformation matrix back to its initial state. However, floating point approximations during substractions may lead to a false result.
Another way is by using Path2D, with it you can rotate the path only and not the entire graphics object:
Rectangle r = new Rectangle(x, y, width, height);
Path2D.Double path = new Path2D.Double();
path.append(r, false);
AffineTransform t = new AffineTransform();
t.rotate(angle);
path.transform(t);
g2.draw(path);
The only problem with g2d.rotate is that it doesn't rotate it around a specific point. It will mostly mess up where you want your Image and then force you to move the x and y coordinates of the image. I would not use it,expecially for a game. What you should look into is rotating a point in java.
My application is a simple game of Brick Breaker. In order to paint the visuals of the application I'm using the paintComponent method. The application also has several buttons that are added using the following code:
levelMenu = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double scale = screenSize.getHeight()/1080;
Graphics2D g2d = (Graphics2D) g;
g2d.scale(scale, scale);
g2d.drawImage(background, 0, 0, null);
}
};
levelMenu.setLayout(new FlowLayout());
JPanel subPanel = new JPanel(new GridLayout(20, 2, 10, 10));
subPanel.setBackground(Constants.CLEAR);
subPanel.add(new JLabel());
subPanel.add(new JLabel());
for (JButton level: levelList) {
subPanel.add(level);
}
subPanel.add(new JLabel());
subPanel.add(back);
levelMenu.add(subPanel);
this.add(levelMenu);
The issue Im having is that the buttons are being added, but also they seem to be painted in the background image of the application:
The buttons on the right dont work, and are just images. Any clue how to fix this issue.
The primary issue comes down to...
Graphics2D g2d = (Graphics2D) g;
g2d.scale(scale, scale);
g2d.drawImage(background, 0, 0, null);
The Graphics context passed to the paintComponent method is a shared resource, all the components rendered within the paint pass will use it. This means that any changes you make to it will also affect them. You should be especially aware of transformations (like translate and scale).
A general practice is to make a snapshot of the state of Graphics context before you use it, this allows you to make changes to the copy with affecting the original, something like...
Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(scale, scale);
g2d.drawImage(background, 0, 0, null);
g2d.dispose();
The other issue is subPanel.setBackground(Constants.CLEAR);. I'm assuming that this is a alpha based color. Swing component's don't support alpha based colors, they are either fully opaque or fully transparent (although you can fake it). This is controlled through the use of setOpaque
Now, I strongly recommend that you stop and go have a read through:
Performing Custom Painting
Painting in AWT and Swing
Use below code snippet for your reference:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicPanelUI;
class MyPanelUI extends BasicPanelUI {
public void paint(Graphics g, JComponent c) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Graphics2D g2d = (Graphics2D) g;
Image img = toolkit.getImage("/usr/share/backgrounds/warty-final-ubuntu.png");
g2d.drawImage(img, 0, 0, null);
}
public Dimension getPreferredSize(JComponent c) {
return super.getPreferredSize(c);
}
}
public class PanelBGTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setUI(new MyPanelUI());
panel.setLayout(new FlowLayout());
panel.add(new JButton("This is button"));
SwingUtilities.updateComponentTreeUI(frame);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
using paint component is not good practice so its always better to extent your component UI class from basic component UI class and override the paint() method. This way swing will take care of all the rendering / re-rendering part and your component(s) added to panel will be visible too.
Now, I strongly recommend that you stop and go have a read through:
Performing Custom Painting
Painting in AWT and Swing
BufferStrategy and BufferCapabilities
How to Use Layered Panes
So, I have been doing Java for a couple of months, and I'm now learing about Graphics. So, I am trying to make a paint kind of thing, where I can just draw with my mouse. Nothing really fancy, just something to get me started. The program just paints a small dot whenever I drag the mouse. It sort of works, except for the fact that it doesn't save my old dots. It just creates a new one! It would be kind if someone could help me with this problem:
Main class:
import javax.swing.JFrame;
public class Test{
public static void main(String args[]){
Ploofer ploof = new Ploofer();
PumpkinPie f = new PumpkinPie(ploof);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000,1000);
f.setResizable(false);
ploof.setSize(1000,1000);
f.add(ploof);
f.setVisible(true);
}
}
"Ploofer" class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Ploofer extends JPanel{
PumpkinPie pObj = new PumpkinPie(this);
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
this.setBackground(Color.WHITE);
g2d.setColor(new Color(190, 50, 0));
if(pObj.draw==true){
g2d.fillRect(pObj.x, pObj.y, 2, 2);
pObj.draw = false;
}
}
#Override
public void update(Graphics g){
paint(g);
}
//I tried to override update, but it didn't really help
}
"PumpkinPie" class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Ploofer extends JPanel{
PumpkinPie pObj = new PumpkinPie(this);
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
this.setBackground(Color.WHITE);
g2d.setColor(new Color(190, 50, 0));
/* g2d.fillRect(475, 475, 50, 50);
g2d.drawString("^Red^", 484, 540); */
if(pObj.draw==true){
g2d.fillRect(pObj.x, pObj.y, 2, 2);
pObj.draw = false;
}
}
#Override
public void update(Graphics g){
paint(g);
}
//I tried to override update, but it didn't really help
}
It sort of works, except for the fact that it doesn't save my old dots. It just creates a new one!
Check out Custom Painting Approaches for the two common ways to do custom painting:
add objects to paint to an ArrayList and iterate through the list to paint all objects
draw to a BufferedImage and repaint the BufferedImage
In your case I would recommend approach 2.
//I tried to override update, but it didn't really help
Don't override update(). There is no reason to do that. That is an old AWT approach with is not needed in Swing.
I have a java application that somehow has a different behavior when launched in windows by double clicking the jar file compared to launching it using the command prompt.
The behavior that i'm noticing specifically is when I override a JLabel to render better using the following
lblDate = new ATimeLabel(ATimeLabel.DATE_LETTERS) {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
super.paintComponent(g2d);
}
};
The effect appears when I launch the app from my IDE or launch the jar from the command prompt but when I double click my app it will show the label without the paintComponent() overriden effects.
would appreciate help to figure out exactly how to be able to have the same effect happen on double click of my app.
EDIT:
I should also mention that I add the following font changes after creating one of 2 JLabels
lblDate.setForeground(Color.gray);
lblDate.setFont(boldFont.deriveFont(Font.PLAIN, timeFontSize));
Here is a screen shot of what it looks like. The one on the left clearly has the anti-aliasing and clean text rendering i'm looking for while the one on the right is fatter and not as sharp. (I also temporary added the red border to show that the paint method is in effect)
EDIT 2:
Seems that when I double click the JVM is 1.7 and my IDE uses JDK 1.6
I don't understand why the RenderingHints for the fonts wouldn't look the same on Java6 and Java7 they are in both APIs and run without exceptions...
Any help would be appreciated.
Seems to work just fine for me...
From left to right, in IDE, from command line and double clicked...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestPaintLabel {
public static void main(String[] args) {
new TestPaintLabel();
}
public TestPaintLabel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JLabel lblDate = new JLabel("Hello, is it me you're looking for?") {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
super.paintComponent(g2d);
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 50);
}
};
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(lblDate);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Try adding some additional painting to determine if the paint method is actually been called.
i have an application that has graphics which are thought to be displayed at 1024x768.
I want to make the application flexible in size without rewriting all drawing code, position calculation etc..
To achieve that my attempt was overriding the paint method of the JFrame container in the following way:
#Override
public void paint(Graphics g)
{
BufferedImage img = new BufferedImage(this.desiredWidth, this.desiredHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D gi = (Graphics2D) img.getGraphics();
gi.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB);
gi.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
gi.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
super.paint(gi);
gi.dispose();
((Graphics2D) g).drawImage(img, screenScale, null);
}
while screenScale is an AffineTransform Object i created in the constructor which does the appropriate scaling according to the target size.
The problem now is: My child components get drawn and scaled, but with the limitations of the parent JFrame. So if my parent frame has the dimension 640x480 the child layers that i have added to it can only draw inside a 640x480 fraction of the 1024x768 BufferedImage that it is painting on.
I guess in some place the child components use getPreferredSize of the JFrame parent, because the child always has this values as bounds. So in the end my scaling strategy is in conflict with the painting behavior of the childs, because they fully ignore the bounds of the graphics object they get delivered for drawing on.
In the end, what ever i do, my child layers (derived from jpanel if that matters) get cut off when the target size is smaller than my "virtual" screen size.
Can anyone provide a better solution or hints how i can circumvent the strange behavior that the graphics bounds are ignored?
Edit: updated outcome of above code with unscaled output, expectet output and resulting output
expected output
resulted output
update: working test code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.print.attribute.standard.OrientationRequested;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class AffineTransformTest
{
private static TransformingFrame canvas;
private static JButton button;
private static TestLayer layer;
public static void main(String[] args)
{
canvas = new TransformingFrame();
canvas.addMouseWheelListener(new ScaleHandler());
layer=new TestLayer(canvas.originalSize);
canvas.getContentPane().add(layer);
layer.setVisible(true);
button = new JButton("asdf");
canvas.setUndecorated(true);
button.setVisible(true);
canvas.getContentPane().add(button);
canvas.pack();
canvas.setLayout(new BorderLayout());
canvas.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
canvas.setPreferredSize(canvas.originalSize);
canvas.setSize(canvas.originalSize);
canvas.setLayout(null);
canvas.setVisible(true);
canvas.validate();
}
#SuppressWarnings("serial")
private static class TransformingFrame extends JFrame
{
private double scale;
private final Dimension originalSize;
private AffineTransform tx = new AffineTransform();
TransformingFrame()
{
originalSize=new Dimension(800,600);
scale = 1;
}
#Override
public void paint(Graphics g)
{
BufferedImage offscreenBuffer=new BufferedImage(originalSize.width,originalSize.height, BufferedImage.TYPE_INT_ARGB);
Graphics bufferGraphics=offscreenBuffer.getGraphics();
super.paint(bufferGraphics);
bufferGraphics.dispose();
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
((Graphics2D) g).drawImage(offscreenBuffer, tx,null);
}
#Override
public void paintComponents(Graphics g)
{
BufferedImage offscreenBuffer=new BufferedImage(originalSize.width,originalSize.height, BufferedImage.TYPE_INT_ARGB);
Graphics bufferGraphics=offscreenBuffer.getGraphics();
super.paintComponents(bufferGraphics);
bufferGraphics.dispose();
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
((Graphics2D) g).drawImage(offscreenBuffer, tx,null);
}
#Override
public void paintAll(Graphics g)
{
BufferedImage offscreenBuffer=new BufferedImage(originalSize.width,originalSize.height, BufferedImage.TYPE_INT_ARGB);
Graphics bufferGraphics=offscreenBuffer.getGraphics();
super.paintAll(bufferGraphics);
bufferGraphics.dispose();
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
((Graphics2D) g).drawImage(offscreenBuffer, tx,null);
}
}
#SuppressWarnings("serial")
private static class TestLayer extends JPanel{
public TestLayer(Dimension originalSize)
{
this.setPreferredSize(originalSize);
this.setSize(originalSize);
setOpaque(false);
setDoubleBuffered(false);
}
#Override
public void paint(Graphics g)
{
Graphics2D ourGraphics = (Graphics2D) g;
super.paint(ourGraphics);
ourGraphics.setColor(Color.green);
ourGraphics.fillRect(0, 0, getWidth(), getHeight());
ourGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
ourGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
ourGraphics.setColor(Color.BLACK);
ourGraphics.drawRect(50, 50, 50, 50);
ourGraphics.fillOval(100, 100, 100, 100);
ourGraphics.drawString("Test Affine Transform", 50, 30);
ourGraphics.drawString(canvas.tx.toString(), 50, 250);
}
}
private static class ScaleHandler implements MouseWheelListener
{
public void mouseWheelMoved(MouseWheelEvent e)
{
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL)
{
// make it a reasonable amount of zoom
// .1 gives a nice slow transition
canvas.scale += (.1 * e.getWheelRotation());
// don't cross negative threshold.
// also, setting scale to 0 has bad effects
canvas.scale = Math.max(0.00001, canvas.scale);
canvas.tx.setTransform(new AffineTransform());
canvas.tx.scale(canvas.scale, canvas.scale);
canvas.setPreferredSize(new Dimension((int)(canvas.originalSize.width*canvas.scale),(int)(canvas.originalSize.height*canvas.scale)));
canvas.setSize(new Dimension((int)(canvas.originalSize.width*canvas.scale),(int)(canvas.originalSize.height*canvas.scale)));
canvas.validate();
canvas.repaint();
}
}
}
}
for some reason this code is working (except the button disappearing).. maybe my error is somewhere else in the child layers.. i'll go investigate that
Okay after some hours fiddling around with it, i came to the conclusion that the drawing limitations that the child panels get in their paint(Graphics g) method don't allow painting more than the parent's size. In the example it works but in the full application not. Seems some settings force that behaviour on my application, but not the demo app.
So if my parent frame has the dimension 640x480 the child layers that i have added to it can only draw inside a 640x480 fraction of the 1024x768
create JFrame --> put there JScrollPane --> to the JScrollPane put :
1) JPanel or JComponent with override paintComponentn(Graphics g) not paint(Graphics g)
2) you wrote about BufferedImage, then better way is put BufferedImage as Icon to the JLabel
As you've observed, a component can be rendered in a scaled graphics context, but the result is effectively useless: the UI delegate has no knowledge of the altered geometry. As #mKorbel suggests, a JScrollPane is the traditional alternative.
You might also look at the scheme used in this game or the technique used in this scalable label. If you are willing to make your own components, you may be able to adapt the approach shown in this ScaledView.
My problem got completely solved after asking some ppl about this.
The solution was:
1.
Create a new Class which you can draw on and make the manipulation there, example:
private class ScaledPane extends JPanel
{
public ScaledPane(Window parent)
{
super();
setPreferredSize(new Dimension(parent.getDesiredWidth(), parent.getDesiredHeight()));
setSize(this.getPreferredSize());
}
#Override
public void paint(Graphics g)
{
Graphics2D g2 = (Graphics2D) g.create(0, 0, getWidth(), getHeight());
g2.setTransform(screenScale);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); //
System.out.println(g2.getClip());
super.paint(g2);
}
}
after that set an instance of that class to your contentpane:
setScreenScale(AffineTransform.getScaleInstance((double) width / (double) desiredWidth, (double) height / (double) desiredHeight));
setContentPane(new ScaledPane(this));
after doing that everything just went fine, as the components of the window us the contentpanes paint method to draw themselves with the new graphics object that is set there
With that done i can scale my window to any desired size without manipulation of the movement formulas or positions of any child.