【问题标题】:Java Swing create Oval by ClickJava Swing 通过单击创建椭圆
【发布时间】:2018-09-16 15:27:04
【问题描述】:

我认为用 java 创建一个小程序会很容易:

  • 我创建了一个 jFrame =>(大小为 500,500 并且可见)
  • 我在 jFrame 中添加了一个 mouseListener
  • 当我点击时,我想在这个位置创建一个椭圆

所以我做了什么:

  • 我创建了一个班级圈子(JPanel)
  • 每当mouslistener 注意到我点击了jFrame 时,我都会在其中添加一个新圆圈。 (它获取 x 和 y 点作为参数)

然后令人震惊的事情发生了: 我点击了我的 jFrame ......什么也没发生。 我想:好吧,让我们在创建新圈子后重新绘制......但它什么也没发生! 只有当我点击windwos边框并重新拉伸它时,它才会“重新绘制”它。

同时,真正糟糕和可悲的是,如果我单击一个位置,然后单击另一个位置,然后重新拉伸框架,它只会绘制最后一个圆圈:(它应该同时绘制两个!)

现在我将 repaint() 放在数千个不同的地方,但没有区别。我还尝试了 setopaque 等,只是因为我现在不知道该怎么做!

这里是mouseListener:你可以忽略颜色

public class Aufgabe3 {
    public static Circ.CircleColor actualColor = CircleColor.ROT;

    // fromone color to another depend on the actual
    public static Circ.CircleColor getNextColor(Circ.CircleColor aktuell) {
        switch (aktuell) {
        case ROT:
            return Circ.CircleColor.GRÜN;
        case GRÜN:
            return Circ.CircleColor.GELB;
        case GELB:
            return Circ.CircleColor.ROT;
        default:
            return null;
        }

    }

    public static void main(String[] args) {

        JFrame jFrame = new JFrame();
        jFrame.setVisible(true);
        jFrame.setSize(500, 500);
        jFrame.setDefaultCloseOperation(jFrame.EXIT_ON_CLOSE);
        // jFrame.add()
        // farbenfolge rot,grün,gelb--
        jFrame.addMouseListener(new MouseListener() {

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

            }

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

            }

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

            }

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

            }

            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("clicked");
                int x = e.getX();
                int y = e.getY();
                System.out.println("coords:" + x + "|" + y);
                Circ circ = new Circ(x, y, actualColor);
                circ.repaint();
                jFrame.add(circ);
                jFrame.repaint();
                System.out.println(actualColor);
                // actualisation of the next color
                actualColor = getNextColor(actualColor);

            }
        });
    }

}

现在是圆圈:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JComponent;
import javax.swing.JPanel;

public class Circ extends JComponent {
    static public enum CircleColor {
        ROT, GRÜN, GELB
    };

    private int x;
    private int y;
    private CircleColor circleColor;

    public Circ() {
        super();

    }

    public Circ(int x, int y, CircleColor circColor) {
        super();
        this.x = x;
        this.y = y;
        this.circleColor = circColor;
        System.out.println("new circle created");
        setSize(new Dimension(50, 50));
        setVisible(true);
        setOpaque(true);
    }

    public Color decodeCircleColor(CircleColor farbe) {
        switch (farbe) {
        case GRÜN:
            return Color.GREEN;
        case GELB:
            return Color.yellow;
        case ROT:
            return Color.red;
        default:
            return null;
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        System.out.println("paint");
        Graphics2D g2d = (Graphics2D) g;
        super.paintComponent(g2d);
        g2d.setColor(decodeCircleColor(circleColor));
        // g2d.drawOval(x, y, 50, 50);
        g2d.fillOval(x, y, 50, 50);
    }
}

【问题讨论】:

  • 阅读 Custom Painting 上的 Swing 教程部分,了解如何进行自定义绘画的分步示例。

标签: java swing mouselistener


【解决方案1】:

JFrame 的默认布局是BorderLayout。 在未指定位置的情况下将组件添加到BorderLayout 时,它们将添加到BorderLayout.CENTER 中,替换之前的一组到此位置。 这意味着您始终只有一个 Circle 添加到您的 JFrame。

无论如何,您似乎正在尝试在光标位置绘制圆圈,这意味着您必须将Circle 组件添加到JFrame 的不同位置,这并不容易。 相反,您最好只向框架中添加一个组件并在该组件中绘制所有圆圈。

【讨论】:

  • 嗯,我会试试的!我将在 JFrame 中添加一个 JPanel,然后在 JPanel 上绘制:D 让我们看看!谢谢。
【解决方案2】:

如果您在mouseClicked 事件中添加您的组件,这可能会重新验证您应该调用,因为您更改了容器(JFrame)。此外,JFrame 很特别:它们有一个 内容窗格,您应该以这种方式添加组件:

frame.getContentPane().add(...);

默认内容窗格使用BorderLayout

为每次点击添加一个组件可能是矫枉过正,除非您将其设置为null(例如:绝对布局)并为每个圆圈调用 setBounds(x, y, 50, 50) .

但是,由于您覆盖了paintComponent,您可以直接绘制椭圆而无需关心布局或组件。

使用 BorderLayout.CENTER 约束添加一次 Circle 组件。这将确保您的 Circle 获得最大尺寸。

MouseListener 应该在 Circle 上,您必须使其具有焦点 (setFocus(true))。

每次鼠标点击Circle时,在列表中注册鼠标位置(如:List<Point>)然后调用repaint:

circle.points.add(new Point(e.getX(), e.getY()); // 
circle.repaint();

每次调用paintComponent(Graphics),使用列表按照调用顺序绘制椭圆。

@Override
protected void paintComponent(Graphics g) {
    System.out.println("paint");
    Graphics2D g2d = (Graphics2D) g;
    super.paintComponent(g2d);
    g2d.setColor(decodeCircleColor(circleColor));
    // if you know lambda
    points.forEach(p -> g2d.fillOval(p.x, p.y, 50, 50)); 
    // or if you don't know lambda yet.
    // for (Point p : points) g2d.fillOval(p.x, p.y, 50, 50)); 
}

请注意,您可以使用 Point 或任何相关类(例如,您可以使用存储 Paint 对象的具体对象,例如 java.awt.Color 来更改椭圆的颜色)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    相关资源
    最近更新 更多