我使用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!!!
谢谢你的帮助! :)
因此,您有一系列复合问题以及对Swing中坐标系如何工作的基本误解。
做...
g.fillRect(this.getX(), this.getY(),this.getWidth(),this.getHeight());
是个坏主意。
getX
和getY
表示组件在其父组件空间中的位置,因此您现在可以通过x * 2
和y * 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
以总是画一个椭圆形)这产生......
您可以看到形状现在在Shape
组件中偏移。
相反,你应该从0x0
绘制,它将是Shape
组件的顶部/左角。
我修改了Shape
代码以使用...
if (this.isFill()) {
g.fillOval(0, 0, this.getWidth(), this.getHeight());
} else {
g.drawOval(0, 0, this.getWidth(), this.getHeight());
}
它现在生成......
恕我直言,以这种方式使用组件是一个坏主意。 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();
}
}
}
}