I'm trying to write a simple paint applet with Java, but I'm having trouble with BasicStroke. Initially, my plan was to try to somehow draw a line with a width, but the API apparently doesn't support that.
I tried using BasicStroke, but the result is just a fuzzy mess. How can I fix this fuzz problem?
private void mousedrag_hook(Point point)
{
if(start == null)
start = point;
end = point;
Graphics2D g2d = (Graphics2D)applInstance.buffer_g;
g2d.setStroke(new BasicStroke(7));
//g2d.fillOval(point.x - 5, point.y - 5, 10, 10);
g2d.drawLine(start.x, start.y, end.x, end.y);
applInstance.repaint();
start = end;
}
Don't forget the RenderingHints:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
...
}
Related
When i print something by java application in windows 7 the output is blank page and the last graphic only is printed but when i print it in windows 10 it printed successfully .. so i don't no why this happen in windows 7 specially it was printing before on windows 7 and suddenly it happen what i told before (blank page)
this is my code and the output in the picture below
public void printed_bill_printing() {
totals_panelB.setVisible(true);
footer_panelB.setVisible(true);
int count_rows = tableEB.getRowCount();
int count = 0;
int table_height = 0;
while (count <= count_rows - 1) {
int row_height = tableEB.getRowHeight(count);
table_height = row_height + table_height;
count++;
}
float widtha = scrollPaneEB.getWidth();
float heighta = table_height + 30;
scrollPaneEB.setSize(Math.round(widtha), Math.round(heighta));
PrinterJob printJob = PrinterJob.getPrinterJob();
final int finalTable_height = table_height;
printJob.setPrintable(new Printable() {
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D paint_PF = (Graphics2D) graphics;
paint_PF.scale(.68, .6);
B.print(paint_PF);
Graphics2D paint_table = (Graphics2D) graphics;
paint_table.translate(1, 430);
paint_table.scale(.68, 1);
scrollPaneB.setVisible(false);
scrollPaneEB.print(paint_table);
Graphics2D paint_egmaly = (Graphics2D) graphics;
paint_egmaly.translate(1, finalTable_height + tableEB.getTableHeader().getHeight() + 2);
paint_egmaly.scale(1.45, 1);
totals_panelB.setVisible(false);
totals_panelB.print(paint_egmaly);
Graphics2D paint_tawke3 = (Graphics2D) graphics;
paint_tawke3.translate(0, 200);
footer_panelB.setVisible(false);
footer_panelB.print(paint_tawke3);
return Printable.PAGE_EXISTS;
}
});
PrintRequestAttributeSet printRequestAttrSet = new HashPrintRequestAttributeSet();
printRequestAttrSet.add(new MediaPrintableArea(0, 0, 350, 500, MediaPrintableArea.MM));
printRequestAttrSet.add(Chromaticity.MONOCHROME);
try {
PrintService ps = findPrintService(String.valueOf(printer1PST_combo.getSelectedItem()));
printJob.setPrintService(ps);
printJob.print(printRequestAttrSet);
} catch (PrinterException ex) {
}
adapt_table_size(scrollPaneEB, 440, 351);
}
Casting a Graphics object does not create a new Graphics object. You repeatedly cast the Graphics object and place it in new variables, but it’s still the same Graphics object, so your changes are cumulative.
Stepping through the code:
Graphics2D paint_PF = (Graphics2D) graphics;
This causes paint_PF to contain the same print Graphics object that was passed to the method. It is referring to the graphics object as a Graphics2D, but it’s still the same object.
paint_PF.scale(.68, .6);
B.print(paint_PF);
Now the original print Graphics object is at 0.68 by 0.6 scale.
Graphics2D paint_table = (Graphics2D) graphics;
Again, this is the same Graphics object, which the code just set to have a 0.68 by 0.6 scale.
paint_table.translate(1, 430);
paint_table.scale(.68, 1);
The print Graphics object is still scaled by 0.68 by 0.6; now you are scaling it further by 0.68, resulting in a Graphics object which is actually scaled by 0.04624 by 0.6 (because 0.68 × 0.68 = 0.04624).
scrollPaneB.setVisible(false);
scrollPaneEB.print(paint_table);
Graphics2D paint_egmaly = (Graphics2D) graphics;
paint_egmaly still contains the original print Graphics object.
paint_egmaly.translate(1, finalTable_height + tableEB.getTableHeader().getHeight() + 2);
paint_egmaly.scale(1.45, 1);
Now your print Graphics has been scaled, scaled again, translated, and scaled yet again.
totals_panelB.setVisible(false);
totals_panelB.print(paint_egmaly);
Graphics2D paint_tawke3 = (Graphics2D) graphics;
paint_tawke3 contains the original graphics object, with all of the previous scaling and translation.
paint_tawke3.translate(0, 200);
Now the Graphics object has been scaled, scaled, translated, scaled, and translated again.
footer_panelB.setVisible(false);
footer_panelB.print(paint_tawke3);
One way to make your changes to the Graphics temporary is by creating a new Graphics object, using Graphics.create, then apply your changes to that. If you do this, you are responsible for deallocating the Graphics object by calling its dispose method.
Graphics2D paint_PF = (Graphics2D) graphics.create();
paint_PF.scale(.68, .6);
B.print(paint_PF);
paint_PF.dispose(); // DO NOT FORGET THIS
Graphics2D paint_table = (Graphics2D) graphics.create();
paint_table.translate(1, 430);
paint_table.scale(.68, 1);
scrollPaneB.setVisible(false);
scrollPaneEB.print(paint_table);
paint_table.dispose(); // DO NOT FORGET THIS
Graphics2D paint_egmaly = (Graphics2D) graphics.create();
paint_egmaly.translate(1, finalTable_height + tableEB.getTableHeader().getHeight() + 2);
paint_egmaly.scale(1.45, 1);
totals_panelB.setVisible(false);
totals_panelB.print(paint_egmaly);
paint_egmaly.dispose(); // DO NOT FORGET THIS
Graphics2D paint_tawke3 = (Graphics2D) graphics.create();
paint_tawke3.translate(0, 200);
footer_panelB.setVisible(false);
footer_panelB.print(paint_tawke3);
paint_tawke3.dispose(); // DO NOT FORGET THIS
Another option, which uses fewer resources, is to restore the transform of the Graphics object after each change:
AffineTransform originalTransform = ((Graphics2D) graphics).getTransform();
Graphics2D paint_PF = (Graphics2D) graphics;
paint_PF.scale(.68, .6);
B.print(paint_PF);
paint_PF.setTransform(originalTransform);
Graphics2D paint_table = (Graphics2D) graphics;
paint_table.translate(1, 430);
paint_table.scale(.68, 1);
scrollPaneB.setVisible(false);
scrollPaneEB.print(paint_table);
paint_table.setTransform(originalTransform);
Graphics2D paint_egmaly = (Graphics2D) graphics;
paint_egmaly.translate(1, finalTable_height + tableEB.getTableHeader().getHeight() + 2);
paint_egmaly.scale(1.45, 1);
totals_panelB.setVisible(false);
totals_panelB.print(paint_egmaly);
paint_egmaly.setTransform(originalTransform);
Graphics2D paint_tawke3 = (Graphics2D) graphics;
paint_tawke3.translate(0, 200);
footer_panelB.setVisible(false);
footer_panelB.print(paint_tawke3);
paint_tawke3.setTransform(originalTransform);
I want to paint on an image what the user is painting on the screen. For that I created an image array where the images are saved. That all works how it should. But if I draw a circle or some other round shapes it is shown very angular and not nearly round. My code:
private void onPress(java.awt.event.MouseEvent evt) {
images[actualLevel] = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = (Graphics2D) images[actualLevel].getGraphics();
g2d.fillOval(evt.getX() - 200, evt.getY() - 200, 400, 400);
lastX = evt.getX();
lastY = evt.getY();
g2d = (Graphics2D) display.getGraphics();
g2d.drawImage(images[actualLevel], 0, 0, null);
g2d = (Graphics2D) paPaintingArea.getGraphics();
g2d.drawImage(display, 0, 0, paPaintingArea);
System.out.println(actualLevel);
}
private void onDrag(java.awt.event.MouseEvent evt) {
Graphics2D g2d = (Graphics2D) images[actualLevel].getGraphics();
g2d.setStroke(new BasicStroke(20));
g2d.drawLine(lastX, lastY, evt.getX(), evt.getY());
lastX = evt.getX();
lastY = evt.getY();
g2d = (Graphics2D) display.getGraphics();
g2d.drawImage(images[actualLevel], 0, 0, null);
g2d=(Graphics2D)paPaintingArea.getGraphics();
g2d.drawImage(display, 0, 0,paPaintingArea);
}
display is the image that is painted on the panel after saving the image in the array.
Why are my lines so angular and how can I fix it?
I am starting to build a simulation in java and using a rectangle as a plane. But as I rotate the rectangle its foreground color won't stick to it. Can someone help me?
Screenshot:Here
Source Code:
private void drawTransform(Graphics g, double modifier) {
Rectangle rect = new Rectangle(130,350, 350, 15);
AffineTransform at = new AffineTransform();
at.rotate(-Math.toRadians(modifier), rect.getX(), rect.getY() + rect.height);
// Transform the shape and draw it to screen
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.fillRect(130, 350, 350, 15);
g2d.draw(at.createTransformedShape(rect));
}
Use fill instead of draw:
g2d.fill(at.createTransformedShape(rect));
I'm writing a JApplet that displays a diagram with numbers in circles and lines connecting the circles. I've created a class that extends JComponent to act as the circles. I overrode the paintComponent() method to draw a circle with the numbers inside, and I placed these circles on my applet, on which I drew the lines in the paint() method.
However, if the lines hit the circle at an angle, they cut out early, before the circle, at the square that outlines the entire JComponent, even though the background should be transparent. this forms an "invisible box" around the circle.
I've prepared a smaller program to demonstrate the issue:
And here is the code for that example:
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.*;
public class Circle extends JApplet {
private static final long serialVersionUID = 1L;
myCircle myC = new myCircle(10, 215, 215); // custom circle
Container c;
public void init() {
setSize(500, 500);
c = getContentPane();
c.setLayout(null);
c.setBackground(Color.lightGray);
c.add(myC);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
//draw lines
g2d.draw(new Line2D.Double(0f, 0f, 500f, 500f));
g2d.draw(new Line2D.Double(0f, 500f, 500f, 0f));
g2d.draw(new Line2D.Double(0f, 250f, 500f, 250f));
g2d.draw(new Line2D.Double(250f, 0f, 250f, 500f));
g2d.draw(new Line2D.Double(150f, 0f, 350f, 500f));
myC.repaint(); // put the circle on top
}
public class myCircle extends JComponent {
private static final long serialVersionUID = 1L;
int number; // number to display
public myCircle(int num, int x, int y) {
this.number = num;
this.setLocation(x, y);
this.setSize(75, 75);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
g2d.setColor(Color.white);
g2d.fill(new Ellipse2D.Float(1f, 1f, 70f, 70f));
g2d.setColor(Color.black);
g2d.draw(new Ellipse2D.Float(1f, 1f, 70f, 70f));
g2d.drawString(Integer.toString(number), 15f, 20f);
}
}
}
I wouldn't use a component to represent the circle shape alone. Instead, just paint it all on one JPanel (I'm using a JFrame instead of an applet):
public class Circle extends JPanel {
int number = 10;
float size = 500f;
float rad = 70f;
float stringLocX = 15f, stringLocy = 20f;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER));
g2d.setColor(Color.BLACK);
g2d.draw(new Line2D.Double(0f, 0f, size, size));
g2d.draw(new Line2D.Double(0f, size, size, 0f));
g2d.draw(new Line2D.Double(0f, size / 2, size, size / 2));
g2d.draw(new Line2D.Double(size / 2, 0f, size / 2, size));
g2d.draw(new Line2D.Double(150f, 0f, 350f, 500f));
Ellipse2D.Float circle = new Ellipse2D.Float((size - rad) / 2, (size - rad) / 2, rad, rad);
g2d.setColor(Color.WHITE);
g2d.fill(circle);
g2d.setColor(Color.BLACK);
g2d.draw(circle);
g2d.drawString(Integer.toString(number), (size - rad) / 2 + stringLocX,
(size - rad) / 2 + stringLocy);
}
#Override
public Dimension getPreferredSize() {
return new Dimension((int) size, (int) size);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame();
frame.add(new Circle());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
});
}
}
Depending on how many circles you have and what data they must contain, you can just keep a list of those numbers, then iterate over the list in painComponent and draw them.
Notes:
Don't use null layout.
Better to keep the hard coded numbers as fields so you can change them more easily, possibly make them final.
You need to look at the length of the line being drawn. From the edge of your figure to the circle is longer at an angle than at the sides. Recall for a triangle with 45 degrees, 45 degree, and 90 degree angles the ratio of the length of the sides is 1:1:sqrt(2)
I am making a basic Java program and I would like to draw a line using basic swing Graphics.drawLine.
Is there a way to make the two points in terms of doubles so I can make the output more accurate, or another way that is better?
You can draw the lines using ((Graphics2D) g).draw(Shape) and pass it a Line2D.Double.
Here's a demo:
import javax.swing.*;
public class FrameTestBase extends JFrame {
public static void main(String args[]) {
FrameTestBase t = new FrameTestBase();
t.add(new JComponent() {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (int i = 0; i < 50; i++) {
double delta = i / 10.0;
double y = 5 + 5*i;
Shape l = new Line2D.Double(5, y, 200, y + delta);
g2.draw(l);
}
}
});
t.setDefaultCloseOperation(EXIT_ON_CLOSE);
t.setSize(400, 400);
t.setVisible(true);
}
}
You might also want to try adding
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE)
If you have a refernce to g, which I assume is Graphics object, you should use Java 2D APIs
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Line2D.Double(x1, y1, x2, y2));
Javadocs for:
Line2D
Graphics2D