Home > Net >  Having trouble aligning graphics in Java
Having trouble aligning graphics in Java

Time:02-18

So I am using a JFrame object to open up a window and add a bunch of graphics first I am adding an image then I am trying to add some lines, But it seems like the line start from the Y center of the previous image I would like for it to start at the top of the page here is my code for the JFrame:

    JFrame f = new JFrame();
    JLabel trebeclef = new JLabel(new ImageIcon(getClass().getClassLoader().getResource("Some image")));
    Draw d = new Draw();
    f.add(trebeclef);
    f.add(d);   
    f.setSize(1000,1000);
    f.getContentPane().setBackground(Color.white);
    f.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));
    f.pack();
    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

here is the code for the Draw class

public void paint(Graphics g2) {
        super.paintComponent(g2);
        Graphics2D g = (Graphics2D) g2;
        g.setStroke(new BasicStroke(2));
        g.drawLine(0, 0, 100, 0);
    }

it results in this

enter image description here

Any help appreciated, thanks

CodePudding user response:

Trying to layout components like this isn't the easiest thing to to, especially when you consider the complexities of JLabel and the possibilities of other layout constraints.

If you have the image and you're drawing the lines via custom painting, I would just custom paint the whole thing

Starting with...

enter image description here

We can produce something like...

enter image description here

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public final class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new ClefWithLinesPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class ClefWithLinesPane extends JPanel {

        private BufferedImage trebbleClef;

        public ClefWithLinesPane() throws IOException {
            trebbleClef = ImageIO.read(getClass().getResource("/images/ClefLines.png"));
            setBackground(Color.WHITE);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(800, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = 0;
            int y = (getHeight() - trebbleClef.getHeight()) / 2;
            g2d.drawImage(trebbleClef, x, y, this);

            int[] lines = new int[] {
                30, 60, 89, 120, 149
            };

            x = trebbleClef.getWidth();

            g2d.setStroke(new BasicStroke(2));
            for (int line = 0; line < lines.length; line  ) {
                y = lines[line];
                g2d.drawLine(x, y, getWidth(), y);
            }

            g2d.dispose();
        }

    }
}

But... as you can see, the lines don't "quite" match up, now this is simply an issue with source image and you could spend some time cleaning it up, or, you could just dispense with the lines of the clef itself and do those you're self, for example...

Starting with...

enter image description here

We could produce something like...

enter image description here

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public final class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new ClefWithOutLinesPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class ClefWithOutLinesPane extends JPanel {

        private BufferedImage trebbleClef;

        public ClefWithOutLinesPane() throws IOException {
            trebbleClef = ImageIO.read(getClass().getResource("/images/Clef.png"));
            setBackground(Color.WHITE);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(800, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int minLineY = 30;
            int maxLineY = 150;

            int lineSpacing = (maxLineY - minLineY) / 4;

            int x = 10;

            g2d.setStroke(new BasicStroke(8));
            g2d.drawLine(x, minLineY   3, x, maxLineY - 3);
            int y = (getHeight() - trebbleClef.getHeight()) / 2;
            g2d.drawImage(trebbleClef, x   10, y, this);

            g2d.setStroke(new BasicStroke(2));
            for (int line = 0; line < 5; line  ) {
                y = minLineY   (lineSpacing * line);
                g2d.drawLine(x, y, getWidth(), y);
            }

            g2d.dispose();
        }

    }
}

CodePudding user response:

Adds after setLayout. One often uses an overloaded add with an extra parameter for a layout's specific constraint.

By default the content pane the frame's adds are done upon, has a BorderLayout with center, left and so on.

The horizontal "line" in a flow is vertically centered. Setting a preferred height ensures a line component is filled up.

d.setPreferredSize(new Dimension(100, 1000)); 

Of course an other layout might serve better; depending on what you want - just experiment.

  • Related