Change in thickness when using g.drawLine()? - java

Some of the lines I'm drawing with Java Swing are changing thickness in the middle and I'm not sure why.
import javax.swing.*;
import java.awt.*;
public class Main extends Canvas {
public static void main(String[] args) {
try {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Main canvas = new Main();
canvas.setSize(900, 700);
frame.add(canvas);
frame.pack();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.drawLine(450, 0, 900, 450);
}
}
Image of the line drawn by this program:

Related

Java - BufferedImage Not Appearing on JFrame

I'm having trouble getting an image to show on a JFrame.
The frame is completely black upon running. Here's my code:
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class JFrameTesting extends JFrame {
BufferedImage test = null;
public static void main(String[] args) throws URISyntaxException {
new JFrameTesting();
}
public JFrameTesting() throws URISyntaxException {
JFrame frame = new JFrame("My first JFrame!");
frame.setSize(400, 400);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
test = ImageIO.read(new File(getClass().getResource("test.png").toURI()));
} catch (IOException ex) {
Logger.getLogger(JFrameTesting.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(test, 200, 200, null);
}
}
I'm not sure if I'm nessecarily doing anything wrong. I have no errors at all when running.
Thanks in advance!
you can try, with this code.
you need to load a JLabel on Jframe when you add a image.
BufferedImage test = null;
public static void main(String[] args) throws URISyntaxException {
new JFrameTesting();
}
public JFrameTesting() throws URISyntaxException {
JFrame frame = new JFrame("My first JFrame!");
JLabel label = new JLabel();
frame.setSize(800, 800);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
test = ImageIO.read(new File(getClass().getResource("test.png").toURI()));
frame.add( new JLabel(new ImageIcon(test)),BorderLayout.CENTER);
frame.setIconImage(test);
frame.setVisible(true);
label.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(JFrameTesting.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(test, 200, 200, null);
}
}
You haven't actually added your image to the JFrame yet. To have the image appear you need to add the BufferedImage onto a component then draw that. You can do that using a JLabel and an ImageIcon.
public class JFrameTesting extends JFrame {
BufferedImage test = null;
ImageIcon image = new ImageIcon();
public static void main(String[] args) throws URISyntaxException {
new JFrameTesting();
}
public JFrameTesting() throws URISyntaxException {
JFrame frame = new JFrame("My first JFrame!");
try {
test = ImageIO.read(new File(getClass().getResource("test.png").toURI()));
image.setImage(test);
} catch (IOException ex) {
Logger.getLogger(JFrameTesting.class.getName()).log(Level.SEVERE, null, ex);
}
JLabel label = new JLabel();
label.setIcon(image);
frame.add(label);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Alternatively you can skip the Label and draw onto a component if you want. In which case you you'll have to override the draw method of a JPanel.
JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 200, 200, null);
}
};
frame.add(pane);
Another note is that you're extending JFrame but also making a new JFrame inside of the class. You can remove the extra JFrame and all the "frame." The class itself is a JFrame so you don't need an extra one.
//set the title using the setTitle method
setTitle("My first JFrame!");
add(label);
setSize(400, 400);
setVisible(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
Also, I believe the ImageIO.read(...) method can take a URI as a parameter so you shouldn't have to create a File from it.
My code draws image, but need repaint. For this you need for example to change size of frame using you mouse.
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class JFrameTesting extends JFrame {
BufferedImage test = null;
public static void main(String[] args) throws URISyntaxException {
new JFrameTesting();
}
public JFrameTesting() throws URISyntaxException {
JFrame frame = new JFrame("My first JFrame!");
frame.setSize(400, 400);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
System.out.println("init");
test = ImageIO.read(new File(getClass().getResource("test.png").toURI()));
System.out.println(test);
} catch (IOException ex) {
Logger.getLogger(JFrameTesting.class.getName()).log(Level.SEVERE, null, ex);
}
final JPanel pane = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
System.out.println("paint");
super.paintComponent(g);
g.drawImage(test, 0, 0, null);
}
};
frame.add(pane);
frame.repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
System.out.println("paint");
g.drawImage(test, 200, 200, null);
}
}

Why is this graphics component not working?

I am trying to draw a rectangle in the class "Graphics", but for some reason the rectangle does not appear, but the program returns no errors. I have never experience issues such as this before so I am rather confused.
Main()
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main
{
public Main()
{
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
Graphics()
import java.awt.Color;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(500, 500, 500, 500);
}
}
EDIT FOR HOVERCRAFT
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main
{
public Main()
{
JFrame window = new JFrame();
Sound soundCall = new Sound();
Draw drawCall = new Draw();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawCall);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
}
Through adding this window.getContentPane().add(drawCall); asks me to change drawCall to a Component
EDIT 2:
public class Draw
{
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
}
}
ERROR
The method add(Component) in the type Container is not applicable for the arguments (Draw)
You add your graphicsCall variable to nothing, and so it will not be displayed. Solution: add it to a container such as that JPanel that you just created, or perhaps directly to the JFrame's contentPane.
i.e., change this:
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
to this:
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
// final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(soundCall);
As an aside, you will want to re-name that class from Graphics to something else, or else you risk confusing yourself or your compiler since there already exists a critical Java class with that name.
Also, avoid using setSize(...). Better to have your drawing JPanel override getPreferredSize() and to call pack() on your JFrame.
Edit
As per MadProgrammer's astute observation, you're drawing outside of the bounds of your component.
Edit 2
Regarding your latest code, this:
public class Draw
{
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
}
}
is useless dreck. Why are you needlessly wrapping a class inside of a class? Instead why not simply:
public class Draw extends JPanel {
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
#Override
public Dimension getPreferredSize() {
// return an appropriate Dimension here
}
}

Background color not being set in Java

I am trying to set background color of my screen to green.
My code so far:
package game;
import java.awt.*;
import javax.swing.JFrame;
public class Game extends JFrame {
public static void main(String[] args) {
DisplayMode dm = new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
Game g = new Game();
g.run(dm);
}
public void run(DisplayMode dm) {
setBackground(Color.GREEN);
setForeground(Color.WHITE);
setFont(new Font("arial", Font.PLAIN, 24));
Screen s = new Screen();
try {
s.setFullScreen(dm, this);
try {
Thread.sleep(5000);
} catch (Exception E) {
}
} finally {
s.restoreScreen();
}
}
#Override
public void paint(Graphics g){
g.drawString("Check Screen", 200, 200);
}
}
When I run the program, I get this:
Screen should be green according to line:
setBackground(Color.GREEN);
Why does the background is not being set to green when I run the program?
You need to add a call to super.paint (g); in your paint () method.
#Override
public void paint(Graphics g){
super.paint (g);
g.drawString("Check Screen", 200, 200);
}
This will ensure that the component will draw itself correctly, including the background color, then draw your text.
Generally, whole approach is very bad. Even if it works with getContentPane().setBackground(Color.GREEN) it won't probably work because you are calling a Thread.sleep(5000) on EDT (or you will have issues soon or later). Use proper component for repetitive task's (refreshing of your screen): Swing Timer.
Instead of overriding JFrame's paint method, it's far better to use JPanel and to override it's paintComponent method. So, something like this:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Game extends JFrame {
JFrame frame = new JFrame();
public Game() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Panel());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Game();
}
});
}
class Panel extends JPanel {
Timer timer;
Panel() {
setBackground(Color.BLACK);
setForeground(Color.WHITE);
refreshScreen();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("arial", Font.PLAIN, 24));
g.drawString("Check Screen", 200, 200);
}
public void refreshScreen() {
timer = new Timer(0, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
});
timer.setRepeats(true);
//Aprox. 60 FPS
timer.setDelay(17);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(650, 480);
}
}
}

resizable angle

I have an angle in a frame (I draw it with two lines). I want to make it flexible to frame; I mean, when the user expands the frame angle also become expanded and vice versa. I tried a lot of examples but I could not solve it. Can someone help?
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class LineDraw extends Frame {
Line2D line1 = new Line2D.Double(200, 200, 100, 300);
Stroke drawingStroke1 = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0,
new float[] { 9 }, 0);
Line2D line2 = new Line2D.Double(200, 200, 200, 300);
public void paint(Graphics g) {
Graphics2D graph = (Graphics2D) g;
graph.setPaint(Color.red);
graph.draw(line2);
graph.setStroke(drawingStroke1);
graph.setPaint(Color.green);
graph.draw(line1);
}
public static void main(String args[]) {
Frame frame = new LineDraw();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
frame.setSize(300, 250);
frame.setVisible(true);
}
}
Here it is done in Swing. Everything is done in the EDT, as is intended with Swing as it is not thread safe. It is double buffered. Why the JLabel/Icon combination? It's just the best way to do it, as far as I have discovered, and I'd struggle to give you a historical/technical explanation of why - that's just the way it seems to have been designed. The other approach is to get involved with BufferStrategy but that starts to get more complicated IMHO.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class LineDrawSwing extends JLabel implements Icon {
Line2D line1, line2;
public LineDrawSwing() { this.setIcon(this); }
Stroke drawingStroke1 = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0,
new float[] { 9 }, 0);
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
frame.add(new LineDrawSwing());
frame.validate();
frame.setSize(300, 250);
frame.setVisible(true);
}
#Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Dimension size = getSize();
line1 = new Line2D.Double(size.width/2, size.height-10, 10, 10);
line2 = new Line2D.Double(size.width/2, size.height-10, size.width-10, 10);
Graphics2D graph = (Graphics2D) g;
graph.setPaint(Color.red);
graph.draw(line2);
graph.setStroke(drawingStroke1);
graph.setPaint(Color.green);
graph.draw(line1);
}
#Override
public int getIconHeight() {
return getSize().height;
}
#Override
public int getIconWidth() {
return getSize().width;
}
}
If sticking with AWT, I would use a ComponentListener to track the size changes for the Frame and reset the line coordinates accordingly.
You may get away with creating/updating the lines in the Frame.paint() context, but that's just not a very clean implementation, with a lot of implied logic and assumptions and, therefore, probably some issues.
So here's the ComponentListener approach. I had to make a few assumptions about where you wanted your lines to get drawn from/to, as you were not clear on this. (If you can be clearer on this, I can update the example.)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class LineDraw extends Canvas implements ComponentListener {
Line2D line1, line2;
public LineDraw() {
this.addComponentListener(this);
}
// set up lines every size update
public void componentResized(ComponentEvent e) {
Dimension size = getSize();
line1 = new Line2D.Double(size.width/2, size.height-10, 10, 10);
line2 = new Line2D.Double(size.width/2, size.height-10, size.width-10, 10);
}
// required to satisfy ComponentListener interface
public void componentHidden(ComponentEvent e) { }
public void componentMoved(ComponentEvent e) { }
public void componentShown(ComponentEvent e) { }
// paint, main both as before
Stroke drawingStroke1 = new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0,
new float[] { 9 }, 0);
public void paint(Graphics g) {
Graphics2D graph = (Graphics2D) g;
graph.setPaint(Color.red);
graph.draw(line2);
graph.setStroke(drawingStroke1);
graph.setPaint(Color.green);
graph.draw(line1);
}
public static void main(String args[]) {
Frame frame = new Frame();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
frame.add(new LineDraw());
frame.validate();
frame.setSize(300, 250);
frame.setVisible(true);
}
}

Cannot get image to display in Swing on OSX

I think I'm being a bit of an idiot, given that I haven't done Swing programming in a while, but I'm trying to draw a simple image to screen, and I'm not getting what I expected
public class ImageApp {
public static void main(String[] args) throws MalformedURLException, IOException {
final Image image = ImageIO.read(new File("/Library/WebServer/Documents/image.gif"));
final JPanel component = new JPanel(){
public void paint(final Graphics g) {
System.out.println("Drawing image "+image.getWidth(null)+" "+image.getHeight(null));
g.drawString("hello", 0,0);
g.drawImage(image,this.getWidth()/2,this.getHeight()/2, 100, 100, Color.blue,this);
super.paint(g);
}
};
final JFrame frame = new JFrame();
frame.add(component);
frame.setSize(100, 100);
frame.pack();
frame.setVisible(true);
}
}
This renders a blank window which doesn't seem to be sized to 100,100. Is there some other step I need to perform to get the graphics to appear on screen, or the size to be respected?
I'm using JDK6 on OSX 10.6
In Swing, you should override paintComponent(), not paint().
Addendum: e.g., see below. In a comment, #eugener raises an excellent point about using a JLabel as an alternative image container.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageApp {
public static void main(String[] args) throws IOException {
final Image image = ImageIO.read(new File("image.jpg"));
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final JPanel component = new JPanel() {
#Override
public void paintComponent(final Graphics g) {
g.drawImage(image, 0, 0, null);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(
image.getWidth(this), image.getHeight(this));
}
};
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(component);
frame.pack();
frame.setVisible(true);
}
});
}
}
Try this:
public class ImageApp {
public static void main(String[] args) throws MalformedURLException, IOException {
final Image image = ImageIO.read(new File("/Library/WebServer/Documents/image.gif"));
final JPanel component = new JPanel() {
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
System.out.println("Drawing image " + image.getWidth(null) + " " + image.getHeight(null));
g.drawString("hello", 0,10);
g.drawImage(image, this.getWidth() / 2, this.getHeight() / 2, 100, 100, Color.blue, this);
}
};
final JFrame frame = new JFrame();
frame.add(component);
frame.setSize(100, 100);
frame.setVisible(true);
}
}

Categories

Resources