【问题标题】:Creating a simple custom JComponent in Java?在 Java 中创建一个简单的自定义 JComponent?
【发布时间】:2014-06-22 04:18:24
【问题描述】:

我想开始为工作中的项目构建我自己的定制 JComponent。我在下面有一个简单的示例,它应该只在屏幕上创建一个球。 (我在互联网上找到了大部分内容)但它确实提供了一个不错的起点。我的问题是为什么这段代码没有在我的表格中显示球?我做错了什么?

此外,应该为自定义 JComponent 提供哪些基本方法?

代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

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

    public testBall() {
        JPanel testPane = new JPanel();
        testPane.setBackground(Color.white);
        testPane.setLayout(new GridBagLayout());
        testPane.add(new MyBall(30,30,10));

        JFrame frame = new JFrame("Testing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());
        frame.add(testPane);
        frame.pack();
        frame.setSize(500, 300); 
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

class MyBall extends JComponent
{
    private static final long serialVersionUID = 1L;
    public MyBall() { }
    public MyBall(int x, int y, int diameter)
    {
        super();
        this.setLocation(x, y);
        this.setSize(diameter, diameter);
    }

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillOval(0, 0, 100, 100);
    }
}

在哪里可以找到 JComponent 类中应覆盖的所有方法的列表? (我知道有些组件应该始终包含在 JComponent 中。)

如果我在一个类中创建这个组件的一个实例,并且需要更改圆圈的颜色,我会直接从该类调用repaint() 方法吗?

【问题讨论】:

    标签: java swing paintcomponent jcomponent preferredsize


    【解决方案1】:

    您正在将MyBall 添加到testPane(具有GridBagLayout)而没有指定任何约束。 (也就是说,您对add() 的调用没有第二个参数。)默认约束很可能不是您想要的。尝试将BorderLayout 用于您的测试窗格,因为这使用BorderLayout.CENTER 作为默认值,这在您的情况下可能是合理的:

    testPane.setLayout(new BorderLayout());
    

    这会让球出现在我面前。

    至于您的第二个问题,我认为您的课程符合定义。您要实现的主要方法是paintComponent(),就像您一样。有时需要重写 get min/max/preferred size 方法,但这实际上取决于您希望组件做什么。 JComponent 不是抽象的,因此如果您不想覆盖任何内容,则不必覆盖任何内容。它提供了很多开箱即用的功能,例如键盘焦点、可插入的外观和可访问性等。只要您不想更改任何内容,就离开照原样。实现paintComponent() 和各种get*Size() 方法并完成它。 (您只需要选择 JavaDoc 中的方法来查看适合覆盖的方法。)

    另一个选择是扩展JComponent 的子类,如果有一个类可以做类似于你想做的事情。例如,JPanel 通常是实施您自己的容器的良好起点。

    您可能正在寻找比“取决于”更具体的东西,但现在,如果您只想画一个球,那么只需覆盖处理 JComponent (paintCompentent()) 渲染的方法,以及get*Size() 方法)。

    附带说明一下,您确实应该使用SwingUtilities.invokeLater() 在 Swing 线程上创建您的 Swing 组件。请参阅http://docs.oracle.com/javase/6/docs/api/javax/swing/package-summary.html 上标题为“Swing 的线程策略”的部分。

    【讨论】:

    • 如果您想要一份可以或应该包含在 JComponent 中的所有方法的列表,我会找到吗?
    • 在我的测试方法中,如果我想在单击表单时将 Jcomponent 重新绘制为绿色怎么办。我可以只调用 repaint() 并且应该正确地重新绘制表单上的每个组件。
    • @user3376708 更新了答案以解决您的第一个问题。对于您的第二个问题,是的 - 我认为您需要做的就是在 MyBall 上调用 repaint()。
    • Sometimes it becomes necessary to override the get min/max/preferred size methods, - 创建自定义组件时需要一直这样做。您需要实现这些方法,以便布局管理器能够正常工作。使用 BorderLayout 的解决方案不能解决问题。尝试将组件添加到 BorderLayout 的 NORTH,您仍然会遇到同样的问题。
    • 为什么这在不同的布局中不起作用?如果要制作一个真正的组件,我是否不想制作该组件以便它可以在每个布局表单中使用。
    【解决方案2】:

    构造函数:我们只是将位置设置为通过构造函数参数传递的点。这是该组件所在的位置。我们设置大小的方式相同(width x height)。

    paintComponent:这里我们只是在传递的图形对象上绘制一些椭圆。

    另一部分只是测试,它表明组件已正确创建和显示。

    【讨论】:

      【解决方案3】:

      围绕你的 java 类做了一些调整,我做的唯一改变就是将你的新 MyBall 直接添加到 JFrame 的内容窗格中,尝试运行它,你会在你的 jframe 上看到一个红色圆圈

      public class TestBall {
          public static void main(String[] args) {
              new TestBall();
          }
      
          public TestBall() {
      
              JFrame frame = new JFrame("Testing");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setLayout(new BorderLayout());
              frame.getContentPane().add(new MyBall(30,30,10));
              frame.pack();
              frame.setSize(500, 300);
              frame.setLocationRelativeTo(null);
              frame.setVisible(true);
          }
      }
      
      class MyBall extends JComponent
      {
          private static final long serialVersionUID = 1L;
          public MyBall() { }
          public MyBall(int x, int y, int diameter)
          {
              super();
              this.setLocation(x, y);
              this.setSize(diameter, diameter);
          }
      
          @Override
          public void paintComponent(Graphics g)
          {
              super.paintComponent(g);
              g.setColor(Color.red);
              g.fillOval(0, 0, 100, 100);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-19
        • 1970-01-01
        • 1970-01-01
        • 2020-12-21
        相关资源
        最近更新 更多