Graphics2D рисует не правильно, это только рисование части овала - PullRequest
0 голосов
/ 05 октября 2019

Я пытаюсь нарисовать овал на JFrame, используя Graphics2D, я хочу, чтобы он изменял размеры в соответствии с окном, которое технически это делает, просто оно не рисует около трети овала. Это определенно что-то, что я делаю неправильно, я новичок в части Graphics2D Java.

Я не был уверен, что это был мой компьютер, поэтому я попытался запустить свой код на другом ПК, чтобы получить егослучиться снова, поэтому я не уверен, где я ошибся.

import javax.swing.*;
import java.awt.*;

public class ClockViewer {
    public static void main(String[] args) {
        //create frame
        JFrame frame = new JFrame();
        final int Frame_Width = 110;
        final int Frame_Height = 130;

        //set frame attributes
        frame.setSize(Frame_Width, Frame_Height);
        frame.setTitle("A Really Descriptive Title...");
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //get pane attributes
        System.out.println(frame.getContentPane().getWidth());
        System.out.println(frame.getContentPane().getHeight());

        //create ellipse
        EllipseComponent ellipse = new EllipseComponent();

        //add ellipse to frame
        while(frame.getContentPane().getHeight() > 0 && frame.getContentPane().getWidth() > 0) {
            int posX = Math.round(frame.getContentPane().getWidth() / 100) * 20;
            int posY = Math.round(frame.getContentPane().getHeight() / 100) * 20;
            int Width = Math.round(frame.getContentPane().getWidth() / 100) * 80;
            int Height = Math.round(frame.getContentPane().getHeight() / 100) * 80;
            ellipse.setAll(posX, posY, Width, Height);
            frame.add(ellipse);
        }
    }
}

Это следующий файл:

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class EllipseComponent extends JComponent {
    //global variables for ellipse drawing
    int posX = 0;
    int posY = 0;
    int Width = 0;
    int Height = 0;

    //getters for getting variables values
    public int getPosX() {
    return this.posX;
    }
    public int getPosY() {
        return this.posY;
    }
    @Override
    public int getWidth() {
        return this.Width;
    }
    @Override
    public int getHeight() {
        return this.Height;
    }

    //setters for setting variable values
    public void setPosX(int newPosX) {
        this.posX = newPosX;
    }
    public void setPosY(int newPosY) {
        this.posY = newPosY;
    }
    public void setWidth(int newWidth) {
        this.Width = newWidth;
    }
    public void setHeight(int newHeight) {
        this.Height = newHeight;
    }

    //setter for all variables
    public void setAll(int newPosX, int newPosY, int newWidth, int newHeight) {
        this.posX = newPosX;
        this.posY = newPosY;
        this.Width = newWidth;
        this.Height = newHeight;
    }

    //paint ellipse using graphics
    @Override
    public void paint(Graphics g) {
        Graphics g2 = (Graphics2D) g;
        g2.drawOval(posX, posY, Width, Height);
    }
}

Спасибо за любую помощь, которую вы все можете предоставить мне ^^

Редактировать: я получаю следующие ошибки, если это поможет:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: No such child: 0

at java.awt.Container.getComponent(Container.java:336)

at javax.swing.JComponent.rectangleIsObscured(JComponent.java:4390)

at javax.swing.JComponent.paint(JComponent.java:1054)

at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)

at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)

at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)

at javax.swing.RepaintManager.paint(RepaintManager.java:1272)

at javax.swing.JComponent._paintImmediately(JComponent.java:5158)

at javax.swing.JComponent.paintImmediately(JComponent.java:4969)

at javax.swing.RepaintManager$4.run(RepaintManager.java:831)

at javax.swing.RepaintManager$4.run(RepaintManager.java:814)

at java.security.AccessController.doPrivileged(Native Method)

at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)

at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)

at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)

at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)

at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)

at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)

at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)

at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)

at java.awt.EventQueue.access$500(EventQueue.java:97)

at java.awt.EventQueue$3.run(EventQueue.java:709)

at java.awt.EventQueue$3.run(EventQueue.java:703)

at java.security.AccessController.doPrivileged(Native Method)

at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)

at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)

at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)

at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)

at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)

at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)

at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

1 Ответ

1 голос
/ 05 октября 2019

Я не получаю ошибку, которую вы получаете. Однако это не правильный способ рисования в Swing. Я предлагаю вам взглянуть на , как выполнить заказную живопись . Короче говоря, эта вещь, которую вы пытаетесь выполнить с условием while, не будет работать. Вместо этого позвольте компоненту быть нарисованным согласно его родительскому размеру и координатам, не устанавливая их явно:

/**
 * @Overide paint method was a thing in AWT.
 * In Swing you must override paintComponent (and call super.paintComponent())
 * in order to respect the paint chain.
 * 
 */
@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (getParent() != null) { //Paint according to parent
        Graphics g2 = (Graphics2D) g;
        //Calculations
        int posX = Math.round(getParent().getWidth() / 100) * 20;
        int posY = Math.round(getParent().getHeight() / 100) * 20;
        int Width = Math.round(getParent().getWidth() / 100) * 80;
        int Height = Math.round(getParent().getHeight() / 100) * 80;
        g2.drawOval(posX, posY, Width, Height);
    }
}

Еще одна ненужная вещь, которую вы сделали, это:

@Override
public int getWidth() {
    return this.Width;
}

ПереопределениеgetWidth и getSize компонента ни к чему вас не приведут.

Другие полезные ссылки, которые я рекомендую вам прочитать, Исходные темы и Почему бы мне не позвонитьsetVisible (true) перед добавлением компонентов?

Полный пример:

public class ClockViewer {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(()->{
            // create frame
            JFrame frame = new JFrame();
            final int Frame_Width = 110;
            final int Frame_Height = 130;

            // set frame attributes
            frame.setSize(Frame_Width, Frame_Height);
            frame.setTitle("A Really Descriptive Title...");

            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // get pane attributes
            System.out.println(frame.getContentPane().getWidth());
            System.out.println(frame.getContentPane().getHeight());

            // create ellipse
            JComponent ellipse = new JComponent() {
                @Override
                protected void paintComponent(Graphics g) {
                    super.paintComponent(g);
                    if (getParent() != null) { //Paint according to parent
                        Graphics g2 = (Graphics2D) g;
                        //Calculations
                        int posX = Math.round(getParent().getWidth() / 100) * 20;
                        int posY = Math.round(getParent().getHeight() / 100) * 20;
                        int Width = Math.round(getParent().getWidth() / 100) * 80;
                        int Height = Math.round(getParent().getHeight() / 100) * 80;
                        g2.drawOval(posX, posY, Width, Height);
                    }
                }
            };
            frame.add(ellipse);
            frame.setVisible(true);
        });

    }
}
...