paintComponent的一些问题

问题描述 投票:0回答:1

我使用paintComponent绘制形状时遇到了一个不明确的问题。

public class Shape extends JPanel {
private String shape;
private boolean isFill;
private int x;
private int y;
private int width;
private int height;
private Color color;

public Shape(String shape, boolean isFill, int x, int y, int width, int height, Color color) {
    this.shape = shape;
    this.isFill = isFill;
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.color = color;
}
@Override
public boolean equals (Object O){
    if (O instanceof Shape){
        if (this.getWidth() == ((Shape) O).getWidth() && this.getHeight() == ((Shape) O).getHeight()){
            return true;
        }
    }
    return false;
}

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.setColor(this.getColor());
    if (this.getShape().equals(Constants.IS_RECTANGLE)){
        if (this.isFill()){
            g.fillRect(this.getX(), this.getY(),this.getWidth(),this.getHeight());
        }
        else{
            g.drawRect(this.getX(), this.getY(),this.getWidth(),this.getHeight());
        }
    }
    else{
        if (this.isFill()){
            g.fillOval(this.getX(), this.getY(),this.getWidth(),this.getHeight());
        }
        else{
            g.drawOval(this.getX(), this.getY(),this.getWidth(),this.getHeight());
        }
    }
}

public void drawShape(JPanel panel){
    panel.add(this);
    panel.setVisible(true);
}

这是我的Shape类,我想在面板中添加一些(使用JPanel)。

public class GuiManagement {

public JFrame createScreen(){
    // Creating the screen
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setTitle(Constants.APP_NAME);
    frame.setSize(Constants.SCREEN_WIDTH,Constants.SCREEN_HEIGHT);
    return frame;
}

public JPanel createPanel(JFrame frame, int x, int y, int width, int height, String borderSpace){
    // Creates a panel, set its bounds and direction in the screen
    JPanel panel = new JPanel();
    panel.setLayout(null);
    panel.setBounds(x,y,width,height);
    frame.add(panel, borderSpace);
    panel.setVisible(true);
    return panel;
}

这是我的2个函数,它们创建并返回一个框架和面板。

public static void main (String [] args){
    GuiManagement g = new GuiManagement();
    JFrame frame = g.createScreen();
    JPanel panel = g.createPanel(frame,0,0,800,800,BorderLayout.NORTH);
    panel.setBackground(Color.GREEN);
    Shape s = new Shape("Oval",true,40,40,100,100,Color.DARK_GRAY);
    s.drawShape(panel);

    frame.setLayout(new BorderLayout(30,30));
    frame.setVisible(true);
}

那是主要的课程。现在,程序应该绘制一个简单的椭圆形,但是当我运行main函数时,看起来面板为绘制形状分配了正确的空间(框架的绿色部分是我创建的面板),但绘制它只在该空间的一小部分。我在下图中添加了一个问题示例。 PRINT SCREEN EXAMPLE OF THE PROBLEM HERE!!!

谢谢你的帮助! :)

java swing
1个回答
2
投票

因此,您有一系列复合问题以及对Swing中坐标系如何工作的基本误解。

做...

g.fillRect(this.getX(), this.getY(),this.getWidth(),this.getHeight());

是个坏主意。

getXgetY表示组件在其父组件空间中的位置,因此您现在可以通过x * 2y * 2来偏移绘图的位置

我重命名了getX和getY函数

好吧,这不是你的原始代码,它只会造成更多的混乱

所以,我用...设置了一个小测试

Shape shape = new Shape("", true, 25, 25, 50, 50, Color.RED);
shape.setBorder(new LineBorder(Color.BLUE));
shape.setBounds(25, 25, 50, 50);

(我修改了Shape以总是画一个椭圆形)这产生......

Bad offset

您可以看到形状现在在Shape组件中偏移。

相反,你应该从0x0绘制,它将是Shape组件的顶部/左角。

我修改了Shape代码以使用...

if (this.isFill()) {
    g.fillOval(0, 0, this.getWidth(), this.getHeight());
} else {
    g.drawOval(0, 0, this.getWidth(), this.getHeight());
}

它现在生成......

Better positioned

恕我直言,以这种方式使用组件是一个坏主意。 null布局非常难以管理,如果您想要做的只是绘制形状,那么纯粹的自定义绘画路线通常更好/更容易管理。

这个想法基本上构造了一个可以绘制任意数量的“形状”对象的单个组件

因为我喜欢从可以构建的“抽象”概念开始,我从Shape的基本概念开始,它定义了所有Shape实现所需的所有信息......

public interface Shape {
    public Rectangle getBounds();
    public boolean isFilled();
    public Color getColor();
    public void paint(Graphics2D g2d);
}

然后我定义了一个涵盖核心/通用功能的abstract实现......

public abstract class AbstractShape implements Shape {
    private Rectangle bounds;
    private boolean filled;
    private Color color;

    public AbstractShape(Rectangle bounds, boolean filled, Color color) {
        this.bounds = bounds;
        this.filled = filled;
        this.color = color;
    }

    public Rectangle getBounds() {
        return bounds;
    }

    public boolean isFilled() {
        return filled;
    }

    public Color getColor() {
        return color;
    }

}

然后我定义了实际的实现,在这种情况下,我只完成了OvalShape,但你可以有一个三角形,矩形,弧形和形状......

public class OvalShape extends AbstractShape {

    public OvalShape(Rectangle bounds, boolean filled, Color color) {
        super(bounds, filled, color);
    }

    @Override
    public void paint(Graphics2D g2d) {
        g2d.setColor(this.getColor());
        Rectangle bounds = getBounds();
        if (isFilled()) {
            g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
        } else {
            g2d.drawOval(bounds.x, bounds.y, bounds.width, bounds.height);
        }
    }

}

然后,我们需要一些方法来展示这些形状......

public class ShapeContainer extends JPanel {
    private List<Shape> shapes;

    public ShapeContainer() {
        shapes = new ArrayList<>(25);
    }

    public void add(Shape shape) {
        shapes.add(shape);
        repaint();
    }

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

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Shape shape : shapes) {
            Graphics2D g2d = (Graphics2D) g.create();
            shape.paint(g2d);
            g2d.dispose();
        }
    }



}

这意味着,所有形状都在容器坐标上下文中工作,如果您想在轨道上添加新功能,则无需担心尝试翻译它们...

因为我知道这可能需要一点点,一个可运行的例子......

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
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() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                Shape shape = new OvalShape(new Rectangle(25, 24, 50, 50), true, Color.RED);

                ShapeContainer container = new ShapeContainer();
                container.add(shape);

                frame.add(container);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface Shape {
        public Rectangle getBounds();
        public boolean isFilled();
        public Color getColor();
        public void paint(Graphics2D g2d);
    }

    public abstract class AbstractShape implements Shape {
        private Rectangle bounds;
        private boolean filled;
        private Color color;

        public AbstractShape(Rectangle bounds, boolean filled, Color color) {
            this.bounds = bounds;
            this.filled = filled;
            this.color = color;
        }

        public Rectangle getBounds() {
            return bounds;
        }

        public boolean isFilled() {
            return filled;
        }

        public Color getColor() {
            return color;
        }

    }

    public class OvalShape extends AbstractShape {

        public OvalShape(Rectangle bounds, boolean filled, Color color) {
            super(bounds, filled, color);
        }

        @Override
        public void paint(Graphics2D g2d) {
            g2d.setColor(this.getColor());
            Rectangle bounds = getBounds();
            if (isFilled()) {
                g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
            } else {
                g2d.drawOval(bounds.x, bounds.y, bounds.width, bounds.height);
            }
        }

    }

    public class ShapeContainer extends JPanel {
        private List<Shape> shapes;

        public ShapeContainer() {
            shapes = new ArrayList<>(25);
        }

        public void add(Shape shape) {
            shapes.add(shape);
            repaint();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Shape shape : shapes) {
                Graphics2D g2d = (Graphics2D) g.create();
                shape.paint(g2d);
                g2d.dispose();
            }
        }



    }
}
© www.soinside.com 2019 - 2024. All rights reserved.