package com.company;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayDeque;
import java.util.Random;
public class REcom {
REcom() {
JFrame jfm = new JFrame("Paint");
jfm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
BorderLayout border = new BorderLayout();
border.setVgap(10);
jfm.setLayout(border);
DrawPanel dw = new DrawPanel();
dw.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
dw.setXY(e.getX() , e.getY());
dw.repaint();
}
#Override
public void mouseMoved(MouseEvent e) {
dw.previosPosition = new Position(e.getX() , e.getY());
}
});
jfm.add(dw ,BorderLayout.CENTER);
jfm.setBackground(Color.white);
jfm.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
jfm.setSize(500 ,500);
JPanel color = new JPanel(new FlowLayout(FlowLayout.LEFT));
//that Jpanel background is doubled
// color.setBounds(new Rectangle(0 ,0 , 100 , jfm.getHeight()));
Button blue = new Button();
blue.setBackground(Color.blue);
blue.setSize(500 ,200);
blue.addActionListener(e -> {
dw.color = Color.blue;
});
color.add(blue);
Button white = new Button();
white.setBackground(Color.white);
white.setSize(200 ,200);
white.addActionListener(e -> {
dw.color = Color.white;
});
color.add(white);
jfm.add(color , BorderLayout.NORTH);
jfm.setPreferredSize(new Dimension(500 ,500));
jfm.pack();
color.setBackground(Color.blue);
jfm.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(REcom::new);
}
}
class DrawPanel extends JPanel {
ArrayDeque<Position> ad = new ArrayDeque<>();
Position previosPosition = null;
Color color = Color.yellow;
void setXY(int x , int y) {
ad.push(new Position(x , y));
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(color);
g2.setStroke(new BasicStroke(12f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
Position d = ad.pollLast();
if(d != null) {
if(previosPosition == null)
g2.fillOval(d.x, d.y -10 , d.x , d.y-10);
else{
g2.drawLine(previosPosition.x -5 , previosPosition.y -10 , d.x-5 , d.y-10);
}
previosPosition = d;
}
}
}
class Position {
int x, y;
Position(int x, int y) {
this.x= x;
this.y = y;
}
void setXY(int x , int y) {
this.x = x;
this.y = y;
}
}
about code: two panels, one intended for drawing, another for the switch between colors. I decided to add the switcher to the top in frame. But its background move to the bottom and I can draw on it.(therefore its background out of border). and if I will set a border for central JPanel its panel (for drawing), top of the border is doubled
I wanted to add Jpanel to the top for switch between colors (background is doubled after drawing anything )for drawing. But the top Jpanel background is doubled. But if I will replace Jpanel (color) by the common panel, the program work normally. I don't know why? Please help! if you don't understand please try run code (this question I wrote with translater)
JPanel background is doubled
When you do custom painting, the first statement in your method should be:
super.paintComponent(g);
to clear the background otherwise you can have painting artifacts, which is why you see the two blue lines.
Of course when you do add the super.paintComponent(g) the painting disappears because the background is cleared.
The are two solutions to the problem:
keep an ArrayList of object to paint and the iterate through the ArrayList in the paintComponent() method to paint all the objects
paint to a BufferedImage, then just draw the entire image.
I would suggest that option 2 might be the best in this case.
Check out Custom Painting Approaches for more information and examples of each approach.
Related
I have tried and tried, I looked up many examples for keeping Shapes on the screen but can't seem to adapt to my code. In Summary, a left click prints a square, a right click prints a circle. I would like to fill the window with squares (rects) and circles. Any help and explanation so I can learn the concept would be great. I understand I have to keep track on the coordinates, perhaps in a loop but can seem to get it to work. Thanks again.
import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
public class MouseButtonTester extends JFrame implements MouseListener
{
private int mouseX, mouseY;
private int mouseButton;
private boolean isFirstRun;
private static final int WIDTH = 640;
private static final int HEIGHT = 480;
private static final long serialVersionUID = 0; //use this if you do not like warnings
public MouseButtonTester() //constructor
{
super("Mouse Button Tester");
//set up all variables
mouseX = mouseY = 0;
mouseButton = 0;
isFirstRun = true;
//set up the Frame
setSize(WIDTH,HEIGHT);
setBackground(Color.WHITE);
setVisible(true);
//start trapping for mouse clicks
addMouseListener(this);
}
public void mouseClicked(MouseEvent e)
{
mouseX=e.getX(); //Tracks x coordinates
mouseY=e.getY(); //Tracker y coordinates
mouseButton = e.getButton(); //gets button number
repaint();
}
public void paint( Graphics window ) // Draws the Window
{
if(isFirstRun)
{
window.setColor(Color.WHITE);
window.fillRect(0,0,WIDTH, HEIGHT);
//change isFirstRun
}
window.setFont(new Font("TAHOMA",Font.BOLD,12));
window.setColor(Color.BLUE);
window.drawString("MOUSE BUTTON TESTER", 420,55);
draw(window);
}
public void draw(Graphics window)
{
if(mouseButton==MouseEvent.BUTTON1) //left mouse button pressed
{
//window.drawString("BUTTON1", 50,200); //debug code
window.setColor(Color.RED);
window.drawRect(mouseX,mouseY,10,10);
}
//right mouse button pressed
{
if (mouseButton == MouseEvent.BUTTON2)
window.setColor(Color.BLUE);
window.drawOval(mouseX,mouseY,10,10);
}
//any other mouse button pressed
{
}
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) { }
}
------ Main Method --------------
public class MouseButtonTesterRunner
{
public static void main(String[] args)
{ MouseButtonTester prog = new MouseButtonTester();
}
}
First, start by having a read through:
Performing Custom Painting
Painting in AWT and Swing
So you can get a understanding how painting in Swing works, how you can work with it and your responsibilities when doing so.
Next, have a read through:
How can I set in the midst?
Java JFrame .setSize(x, y) not working?
How to get the EXACT middle of a screen, even when re-sized
Graphics rendering in title bar
for reasons why you should avoid overriding paint of top level containers like JFrame
Finally...
Painting in Swing is destructive, that is, every time your component is painted, you are expected to completely repaint the component state from scratch.
In order to achieve your goal, you will need to maintain a cache of the items you want to paint.
The concept itself it's very difficult, but there might be some "gotchas" along the way
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
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() {
EventQueue.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 {
private List<Point> circles;
private List<Point> squares;
public TestPane() {
circles = new ArrayList<>();
squares = new ArrayList<>();
addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
circles.add(e.getPoint());
} else if (SwingUtilities.isRightMouseButton(e)) {
squares.add(e.getPoint());
}
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// I'm picky
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
for (Point p : circles) {
g2d.drawOval(p.x, p.y, 10, 10);
}
g2d.setColor(Color.BLUE);
for (Point p : squares) {
g2d.drawRect(p.x, p.y, 10, 10);
}
g2d.setFont(new Font("TAHOMA", Font.BOLD, 12));
g2d.setColor(Color.BLUE);
FontMetrics fm = g2d.getFontMetrics();
String text = "MOUSE BUTTON TESTER";
int x = getWidth() - fm.stringWidth(text) - 10;
int y = getHeight() - (fm.getAscent() - fm.getHeight()) - 10;
g2d.drawString(text, x, y);
g2d.dispose();
}
}
}
I suggest creating 2 classes.
1) Circle class
2) Square Class
Those classes will store info that you need, like X, y etc..
Initialize an array list that stores those objects & read from it in your paint method, proceed with painting them just like you do in your code.
(On a click event you simply create new object (circle/square) and add it into your array list)
So here's how i understand how your code works so far: The user left clicks, those coordinates are recorded, and a square is rendered on the screen at those coordinates.
When we click the coordinates are updated and on the next draw, the square is moved to a new position.
You were on the right track about needing a loop.
Here's the logic you need to implement:
Create an ArrayList as a member variable. The type can be a pair<int,int> object. So this arraylist will hold a list of X,Y coordinates. This arraylist will look something like this:
ArrayList<pair<int,int>> myRightClickCoords;
Once you make that list, every time the user clicks, record the click coordinates and insert them into the arraylist. That will look something like this:
myRightClickCoords.insert(new pair<int,int>(e.getX(),e.getY()));
Then, once that is added to your code, in your draw function, you can have a look that runs through the entire myRightClickCoords list and runs drawRect for each set of coordinates.
Once you get that working, you can do the same thing for left click and circles. Good luck!
I had an assignment about making painting circles on a JComponent when I click on it and that if you click on an existing circle, it will print a message. Everything works fine, except that the first circle that I draw will have a black border when the following ones wont.
I think it has to do with the repaint method but I cant seems to find what is going on.
import javax.swing.*;
import java.awt.*;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
public class GraphComponent extends JComponent {
private int defaultWidth = 500;
private int defaultHeight = 500;
protected Point spot;
protected int width = 50;
protected int height = 50;
private ArrayList<Ellipse2D> shapeList = new ArrayList();
public GraphComponent() {
super();
this.setPreferredSize(new Dimension(defaultWidth,defaultHeight));
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
boolean contains = false;
spot = e.getPoint();
for (Shape shape : shapeList) {
if (shape.contains(spot)) {
System.out.println("WIN");
System.out.println();
contains = true;
break;
}
}
System.out.println();
System.out.println(shapeList.contains(spot));
if(contains == false){
shapeList.add(new Ellipse2D.Double(spot.x - width / 2,
spot.y - width / 2, width, height));
}
repaint();
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
//moveSquare(e.getX(),e.getY());
}
});
}
public void paintComponent(Graphics gfx) {
super.paintComponents(gfx);
for (Ellipse2D shape : shapeList) {
gfx.drawOval((int)shape.getX(), (int)shape.getY(),width,height);
gfx.setColor(Color.YELLOW);
gfx.fillOval((int)shape.getX(), (int)shape.getY(),width,height);
}
}
}
I expect all the circles to look the same, yet the first created has black borders
You are using a unique Graphics object, so the first call (from the first iteration) to drawOval will paint with the default Graphics 's color, which is black .
Next iterations will all paint in yellow .
for (Ellipse2D shape : shapeList) {
gfx.drawOval((int)shape.getX(), (int)shape.getY(),width,height);// BLACK (at first iteration, YELLOW for next ones)
gfx.setColor(Color.YELLOW);// YELLOW (from now on)
gfx.fillOval((int)shape.getX(), (int)shape.getY(),width,height);
}
I want to create a simple drawing programm in java which currently only draws a line using Graphics.fillOval() and a mouseMotionListener(). The problem is, that if you move the mouse quickly the line gets less precise and the ovals (circles in this case) spread apart.
Here is the code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Drawing
{
private JFrame window;
private Graphics g;
public Drawing()
{
window=new JFrame();
window.setTitle("Paint_window");
window.setSize(1000,700);
window.setVisible(true);
window.setDefaultCloseOperation(window.EXIT_ON_CLOSE);
g=window.getGraphics();
window.addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseEvent e)
{
if(SwingUtilities.isLeftMouseButton(e)
{
g.fillOval((int)e.getX(),(int)e.getY(),10,10);
}
}
});
}
}
Is there a way of improving this or a better way to this?
g=window.getGraphics();
First of all you should not be using getGraphics() of a component. Any painting you do will only be temporary and will be erased the first time Swing determines the component needs to be repainted. In you above example just try resizing the frame to see this.
The proper way to do custom painting is to override the paintComponent(...) method of a JPanel and add the panel to the frame. See Custom Painting for more information.
The problem is, that if you move the mouse quickly the line gets less precise and the ovals (circles in this case) spread apart
You will not be able to have an event generated for every pixel the mouse moves.
Instead you need to be able to "draw a line" between consecutive points generated as you drag the mouse.
So you need to store each point in an ArrayList and in the custom painting code iterate through all the points and draw a line.
A basic example to get you started:
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
class DrawingPanel extends JPanel
{
private ArrayList<ArrayList<Point>> previous = new ArrayList<ArrayList<Point>>();
private ArrayList<Point> current = new ArrayList<Point>();
private BasicStroke basicStroke;
public DrawingPanel(int strokeSize)
{
basicStroke = new BasicStroke(strokeSize, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
MouseAdapter ma = new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
current.add( new Point(e.getX(), e.getY()) );
}
#Override
public void mouseDragged(MouseEvent e)
{
current.add( new Point(e.getX(), e.getY()) );
repaint();
}
#Override
public void mouseReleased(MouseEvent e)
{
if (current.size() > 1)
{
previous.add( current );
}
current = new ArrayList<Point>();
}
};
addMouseMotionListener( ma );
addMouseListener( ma );
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke( basicStroke );
// Paint lines from previous drags
for (int i = 0; i < previous.size(); i++)
{
drawLines(g, previous.get(i));
}
// Paint line from current drag
drawLines(g, current);
}
private void drawLines(Graphics g, ArrayList<Point> points)
{
for (int i = 0; i < points.size() - 1; i++)
{
int x = (int) points.get(i).getX();
int y = (int) points.get(i).getY();
int x2 = (int) points.get(i + 1).getX();
int y2 = (int) points.get(i + 1).getY();
g.drawLine(x, y, x2, y2);
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Drawing Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawingPanel(15));
frame.setSize(400, 400);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args) throws Exception
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
Using the above approach you will redraw the lines every time the component is repainted.
Another approach is to draw to a BufferedImage and then paint the BufferedImage on the panel. You can check out Custom Painting Approaches for an example of this approach.
Basicly this is a part of my code:
package Piano;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class DrawingPanel extends JPanel
{
int r = 0;
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(2.0f));
for (int i = 60; i < 1800; i += 150)
{
drawKeys(g, i, 450, 150, 550);
}
}
public void drawKeys(Graphics g, int x, int y, int width, int height)
{
g.setColor(Color.WHITE);
g.fillRect(x, y, width, height);
g.setColor(Color.BLACK);
g.drawRect(x, y, width, height);
r++;
this.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
if (e.getX() > x && e.getX() < x + width && e.getY() > y && e.getY() < y + height)
{
System.out.println(r);
}
}
});
}
}
and I was wondering if it is possible to add all the mousePressed locations in a single loop. Well, in my case it doesn't work, because for all keys it prints the same, which is the last known 'r' (System.out.println(r)). How would you approch this?
Never add a MouseListener (or any listener) to a component in a painting method. Every time Swing repaints the component you will add another listener.
I was wondering if it is possible to add all the mousePressed locations in a single loop.
You would never add a MouseListener for each pixel location. That is not how a MouseListener works.
Instead you:
create an ArrayList of Rectangles to represent each piano key
you add a single MouseListener to your component
When a MouseEvent is generated you use the Point from the MouseEvent and iterate through the ArrayList of rectangles using the Rectangle.contains(...) method to see if the Rectangle contains the mouse point. If so, then you do your custom logic.
Going off what you said in your comment you could do something a little like this. Create a JButton for each key, or preferably a JButton Array for all the keys. Add an action listener to them all. Then when a JButton is clicked play the corresponding sound.
A simple example
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
public class GUITemplate {
private JFrame myMainWindow = new JFrame("This is my title");
private JPanel firstPanel = new JPanel();
private JButton a = new JButton("a"), b = new JButton("b"), c = new JButton("c"), d = new JButton("d"), e = new JButton("e");
private CustomMouseListener cML = new CustomMouseListener();
private void runGUI() {
myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myMainWindow.setLayout(new FlowLayout());
createFirstPanel();
myMainWindow.getContentPane().add(firstPanel);
myMainWindow.pack();
myMainWindow.setVisible(true);
}
private void createFirstPanel() {
firstPanel.setLayout(new FlowLayout());
firstPanel.add(a);
firstPanel.add(b);
firstPanel.add(c);
firstPanel.add(d);
firstPanel.add(e);
int panelComponents = firstPanel.getComponentCount();
for(int i = 0;i<panelComponents;i++) {
if(firstPanel.getComponent(i) instanceof JButton) {
JButton temp = (JButton) firstPanel.getComponent(i);
temp.addMouseListener(cML);
firstPanel.getComponent(i).setFocusable(false);
}
}
}
private class CustomMouseListener extends MouseAdapter {
public void mousePressed(MouseEvent mE) {
if(mE.getSource() == a) {
System.out.println("a");
}
if(mE.getSource() == b) {
System.out.println("b");
}
if(mE.getSource() == c) {
System.out.println("c");
}
if(mE.getSource() == d) {
System.out.println("d");
}
if(mE.getSource() == e) {
System.out.println("e");
}
}
}
public static void main(String[] args)
{
new GUITemplate().runGUI();
}
}
In this example, a letter is printed to the terminal instead of a sound being played and it looks nothing like a piano but the JButtons could be made to look like piano keys and it would be easy enough to get it to play correct sounds.
Edit
I changed code to use a MouseListener just incase you desperately wanted to use one. It works the same except you a MouseListener to each JButton instead of an ActionListener.
Picture this... A program GUI JFrame that is split in 2, EAST and WEST. The first JPanel is just a print preview screen. The EAST side of the JFrame is where the user can create a 1 2 or 3 size image. The user clicks the "Add" button and the defined image on the right goes to the panel on the left. So if the user clicks "Add" 3 times with different size images, then the panel uses FlowLayout to organize the added panel images added on the left.
When you run this code, you can see a sorta idea of what I want. Really what would be nice is to create all this off-screen and call it MainPanel. Then have printPreview extend MainPanel and scale it down for screen view. And have the Printable method paint the MainPanel into the print method which would be a correct size.
So my question...
-Can you copy or paint a JPanel before it is rendered on the screen?
-Is there a better way to do what I want, I FlowLayout solves what I want amazingly, so a JPanel seems to be the answer unless there is something I do not know of.
Ok now that that is pictured. I have built some code that is about as SSCCE as I can get.
Guys I have tried asking this question at New To Java forums and they just do not respond, I am not double posting on purpose, I completely rewrote this from scratch.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.print.*;
import java.awt.event.*;
public class PrintGrid extends JFrame {
Paper paper = new Paper();
PrintGrid() {
super("Check out this grid panel");
setSize(672, 750);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(paper);
setVisible(true);
} // end PrintGrid constructor
// **************************
// ****** PAPER CLASS *******
// **************************
private class Paper extends JPanel {
final int PAPER_X = 672, PAPER_Y = 975, UNIT = 12, DPI = 72;
X1 x1a = new X1(), x1b = new X1(), x1c = new X1();
X2 x2a = new X2(), x2b = new X2(), x2c = new X2();
X3 x3a = new X3(), x3b = new X3(), x3c = new X3();
Paper() {
setPreferredSize(new Dimension(PAPER_X, PAPER_Y));
setBackground(Color.GRAY);
setLayout(new FlowLayout(FlowLayout.LEADING));
//Users will manually add different sizes to this sheet.
add(x1a);
add(x2a);
add(x3a);
add(x1b);
add(x1c);
add(x2b);
add(x3b);
}
// ******* Parent Class for GridUnits *******
abstract class GridUnit extends JPanel {
MouseListen ml = new MouseListen();
float alpha = 1.0f;
GridUnit() {
this.addMouseListener(ml);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLACK);
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(makeComposite(alpha));
g.setColor(Color.WHITE);
g.drawRect(0, 0, this.getWidth()-1, this.getHeight()-1);
g.setColor(Color.darkGray);
g.fillRect(15, 15, this.getWidth()-30, this.getHeight()-30);
} // end paintComponent.
private AlphaComposite makeComposite(float alpha) {
int type = AlphaComposite.SRC_OVER;
return(AlphaComposite.getInstance(type, alpha));
}
void click() {
setVisible(false);
}
void entered() {
alpha = 0.8f;
repaint();
}
void exited() {
alpha = 1.0f;
repaint();
}
class MouseListen extends MouseAdapter {
public void mouseEntered(MouseEvent event) {
entered();
}
public void mouseExited(MouseEvent event) {
exited();
}
public void mousePressed(MouseEvent event) {
click();
}
}
} // end GridUnit class
class X1 extends GridUnit {
X1() {
setPreferredSize(new Dimension(UNIT*13, UNIT*18));
}
} // end X1 Class
class X2 extends GridUnit {
X2() {
setPreferredSize(new Dimension(UNIT*26, UNIT*18));
}
} // end X1 Class
class X3 extends GridUnit {
X3() {
setPreferredSize(new Dimension(UNIT*39, UNIT*18));
}
} // end X1 Class
} // end Paper class.
public static void main(String[] args) {
new PrintGrid();
} // end main method.
} // end PrintGrid class.
It's quite trivial to paint any Java component to an offscreen image, from which you can do as you please, including copying a portion or scaled image to a final target.
Subclass JComponent and override void paintComponent(Graphics g). Paint to a BufferedImage, then copy the image to the target component. Off the top of my head, something like:
void paintComponent(Graphics g) {
BufferedImage img=new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_ARGB);
Graphics2D gph=(Graphics2D)img.getGraphics();
// paint to gph here
gph.dispose();
g.drawImage(img); // paints the contents of img to the component's graphics context.
}