java - 在 JPanel 的一侧绘制

标签 java swing java-2d custom-painting

我想编写一个应用程序,让您可以通过在 JFrame 左侧单击鼠标来绘制圆圈,并且所有点都会“镜像”到右侧。我遇到的第一个问题是,当我尝试在框架中实现此绘制机制时,没有出现圆圈。

public class Application{
  int x,y;
  private JPanel container;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        new Application().gui();
      }
    });  
  }

  public void gui()
  {
    int height = 250;
    int width = 700;
    JFrame jframe = new JFrame();
    container = new JPanel();
    container.setLayout(new BorderLayout());

    container.add(new DrawCircle(), BorderLayout.WEST);
    container.setVisible(true);
    jframe.add(container);
    //jframe.add(new DrawCircle());

    jframe.setSize(500,700);
    jframe.setVisible(true);
    jframe.setTitle("Title");
    jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jframe.setResizable(false);

  } 
}

当我使用 container.add(new DrawCircle) 时,它可以(在整个框架上)工作,但如果我想添加约束,它就不行。

这是圆类:

public class DrawCircle extends JPanel implements MouseListener
{
  ArrayList<Point> p = new ArrayList<Point>();

  public DrawCircle()
  {
    addMouseListener(this);
  }

  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    for(Point point : p)
    {
      g.fillOval(point.x,point.y,30,30);    
    }  
  }

  @Override
  public void mouseClicked(MouseEvent e) {
  }

  @Override
  public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub
  }

  @Override
  public void mousePressed(MouseEvent e) {
    p.add(new Point(e.getY(), e.getX()));
  }

  @Override
  public void mouseReleased(MouseEvent e) {
  }

  @Override
  public void mouseDragged(MouseEvent e) {
  }

  @Override
  public void mouseMoved(MouseEvent arg0) {
  }
}

最佳答案

让我们来看看您的问题:

The first problem I encountered was that when I try to implement this draw-mechanic in my frame, no circles appear.

这是因为每当您单击 DrawCircle 类中的某个位置时,您忘记调用 JPanel#revalidate()JPanel#repaint()

因此,您可以将 mousePressed() 方法更改为:

@Override
public void mousePressed(MouseEvent e) {
    p.add(new Point(e.getX(), e.getY()));
    revalidate();
    repaint();
}

请注意,我还更改了 e.getX()e.getY() 调用,因为它们位于错误的位置(除非您希望它们那样) )。

这将使你的圆圈出现,但是,你的 DrawCircle 真的很薄(我将这个图像的 JFrame 的高度更改为 200,否则它会是真的很高):

enter image description here

红色部分是您的DrawCircle面板。

要解决此问题,您需要重写其 getPreferredSize() 方法:

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

这将使您的 JPanel 返回一半的大小,widthheight 作为参数传递给构造函数,并且您的类DrawCircle 现在应该如下所示:

class DrawCircle extends JPanel implements MouseListener {
    ArrayList<Point> p = new ArrayList<Point>();
    
    int width = 0;
    int height = 0;
    
    public DrawCircle(int width, int height) {
        this.width = width;
        this.height = height;
        addMouseListener(this);
    }
    
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(width, height);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (Point point : p) {
            g.fillOval(point.x, point.y, 30, 30);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mousePressed(MouseEvent e) {
        p.add(new Point(e.getX(), e.getY()));
        revalidate();
        repaint();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }
}

输出将是这样的:

enter image description here

It works (on the whole frame) when I use container.add(new DrawCircle)

这是因为默认情况下 BorderLayout 将元素默认放置在 CENTER 区域,并且如果在其余方向(NORTH)中没有其他内容, code>、SOUTH 等)它将占据整个空间。

现在让我们继续讨论如何解决您的问题:

我还对 Application 类进行了一些更改(在我的例子中,我将其重命名为 CustomPaintingInHalfFrame):

这些变化是:

  • WIDTHHEIGHT 属性创建最终常量。
  • 使用 BorderLayout 布局删除不必要的 JPanel,因为 JFrame 默认情况下已经具有此布局,我只需添加我们的 DrawClass 到它。
  • DrawCircle 面板绘制边框(因为您不希望在 JFrame 的两个(左和右)部分之间进行划分,如 previous question 中所述您可以简单地将其删除(我建议您在测试时将其保留在那里,以便您知道左面板在哪里结束,右面板在哪里开始。
  • WIDTH/2HEIGHT 作为参数传递给 DrawCircle 构造函数,以便它可以返回正确的 Dimension .

所以,我们的类现在应该如下所示:

public class CustomPaintingInHalfFrame {
    int x, y;
    public static final int WIDTH = 500;
    public static final int HEIGHT = 200;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new CustomPaintingInHalfFrame().gui();
            }
        });
    }

    @SuppressWarnings("serial")
    public void gui() {
        JFrame jframe = new JFrame("Title");
        
        DrawCircle dc = new DrawCircle(WIDTH / 2, HEIGHT);
        
        dc.setBorder(BorderFactory.createLineBorder(Color.RED));
        
        jframe.add(dc, BorderLayout.WEST);
        
        jframe.setSize(WIDTH, HEIGHT);
        jframe.setVisible(true);
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe.setResizable(false);

    }
}
<小时/>

其他提示

  1. 我建议您将 DrawCircle 重命名为 Circle 或类似名称。作为 convention名称应该是名词

  2. gui() 方法重命名为 createGui(),因为作为类名称,方法 名称应为 >动词

关于java - 在 JPanel 的一侧绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41700866/

相关文章:

java - 七月到 TomEE 1.7.2 上的 SLF4J,带有 Maven 插件

java - java在数据库中存储对象

java - 尝试在匿名类中使用最终变量。但它没有传递该值。我无法理解我的错误是什么

java - 如何避免 JFileChooser.setFileFilter() 调用中的 ConcurrentModificationException?

java - 一旦我生成了一个范围内的随机 Int,我如何将该整数分配给字母表中的每个字母?

java - 我从一个 JFrame 到另一个 Jframe 的链接不起作用

java - 无法在 JTable 的单个单元格中添加两个按钮

Java 2D - 散点图 - 点不渲染

java - 如何使用图像进行碰撞检测?

Java graphics2D fillRect 不能正确处理半透明颜色