0

这是我已经接近弄清楚但从未真正做到的一个。

下面列出的代码应该在看到第一次点击后立即绘制一个绿色圆圈。它没有。随后的单击绘制将当前单击点与前一个单击点连接起来的线,以红色显示。该代码在第一次单击时失败,并且适用于所有后续单击。为什么第一次点击不显示?它运行!

我究竟做错了什么?

代码应该在任何当前的 JDE 上编译。

TIA

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

class Demo extends JFrame
            implements  ActionListener, ListSelectionListener, MouseListener {

  int clkCt = 0, // Count of the number of clicks we've done.
      oldX,      // Penultimate X value
      oldY,      // Penultimate X value
      scrH,      // Height of the drawing canvas.
      scrW;      // Width of the drawing canvas.

  JFrame f;      // Holder for the drawing canvas.

  JLabel ctL;    // Displays the number of clicks we've done.

  JPanel canvas; // The drawing canvas.

  public void demoLines() {

    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    scrH = (int) ((double) d.height * 0.75);
    scrW = (int) ((double) d.width * 0.75);

    oldX = scrH / 2;
    oldY = oldX;

    // Create and set up the window.
    f = new JFrame("Multi Click Demo");
    f.getContentPane().setLayout(null);
    int h = scrH / 5;
    f.setBounds(h, h, scrW, scrH);

    // Create a panel
    canvas = new JPanel();
    canvas.setBackground(Color.black);
    canvas.setForeground(Color.red);
    canvas.setLayout(null);
    canvas.setBounds(0, 0, scrW, scrH);
    canvas.setPreferredSize(new Dimension(scrW, scrH));
    canvas.addMouseListener(this);
    f.getContentPane().add(canvas);

    // Create the exit button.
    JButton exit = new JButton("Exit");
    exit.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        goAway();
      }
    });
    exit.setBackground(Color.black);
    exit.setForeground(Color.red);
    exit.setBounds(0, 0, (scrW / 15), (scrH / 15));
    canvas.add(exit); //*/

    // Create the label for the click count.
    ctL = new JLabel("None Yet");
    ctL.setBackground(Color.black);
    ctL.setForeground(Color.red);
    ctL.setBounds((scrH / 15), (scrH * 13 / 15), (scrW / 15), (scrH / 15));
    canvas.add(ctL);

    f.getContentPane().add(canvas);
    f.setVisible(true);

    Graphics g = canvas.getGraphics();
    if (g == null) {
      System.out.println("No graphics for canvas!");
    } else {
      canvas.revalidate(); // This didn't help.
      paintComponent(g, (oldX + oldX / 2), (oldY + oldY / 2));
    }
  }

  void goAway() {
    f.setVisible(false);
    f.dispose();
  }

  public void mouseClicked(MouseEvent m) {
    // Where was the mouse clicked?
    int clkdBtn = m.getButton(),
        x = m.getX(),
        y = m.getY();
    Graphics g = canvas.getGraphics();
    paintComponent(g, x, y);
  }

  public void paintComponent(Graphics g,
                             int x,
                             int y) {

    // This always runs.
    ctL.setText(clkCt + "");

    if (clkCt == 0) {
      // This never displays!
      g.setColor(Color.green);
      int r = scrH * 4 / 5;
      g.drawOval((scrH / 10), (scrH / 10), r, r);
    }

   g.setColor(Color.red);
   g.drawLine(oldX, oldY, x, y);
   oldX = x;
    oldY = y;
    clkCt++;
  }


  public void actionPerformed(ActionEvent event) { }
  public void valueChanged(ListSelectionEvent event) { }

  public void mouseEntered(MouseEvent e) { }
  public void mouseExited(MouseEvent e) { }
  public void mousePressed(MouseEvent e) { }
  public void mouseReleased(MouseEvent e) { }

  public static void main(String[] s) {

    Demo m = new Demo();
    m.demoLines();
  }
}
4

4 回答 4

3

我究竟做错了什么?

您正在使用getGraphics自定义绘画。调用a 时,任何先前的绘画都将丢失repaint。而是将所有自定义绘画功能移至基于JComponentor的新类,JPanel并在那里覆盖paintComponent。记得调用super.paintComponent(g).

有关从内部绘制多个组件的解决方案,请参阅自定义绘制方法paintComponent。您可以构建一个List<Shape>自定义可绘制组件,从方法中遍历列表,并根据需要使用drawLinedrawOval

于 2013-06-16T20:25:34.250 回答
2

删除以下行demolines()

Graphics g = canvas.getGraphics();
if (g == null) {
  System.out.println("No graphics for canvas!");
} else {
  canvas.revalidate(); // This didn't help.
  paintComponent(g, (oldX + oldX / 2), (oldY + oldY / 2));
}

canvas.addMouseListener(this);在函数末尾添加

于 2013-06-16T20:19:22.957 回答
2

该代码存在许多问题。我修复了它们,但忽略了记录每一个变化。如果您不理解(通过阅读相关文档/教程)我为什么要进行更改,请仔细查看此代码并提出问题。

在此处输入图像描述

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.EmptyBorder;

public class Demo extends JPanel
        implements ListSelectionListener, MouseListener {

    int clkCt = 0, // Count of the number of clicks we've done.
            oldX, // Penultimate X value
            oldY, // Penultimate X value
            scrH = 100, // Height of the drawing canvas.
            scrW = 400;      // Width of the drawing canvas.
    JLabel ctL;    // Displays the number of clicks we've done.
    int x, y;

    public void demoLines() {
        oldX = scrH / 2;
        oldY = oldX;

        // Create a panel
        setBackground(Color.black);
        setForeground(Color.red);
        setPreferredSize(new Dimension(scrW, scrH));

        // Create the label for the click count.
        ctL = new JLabel("None Yet");
        ctL.setBackground(Color.black);
        ctL.setForeground(Color.red);
        ctL.setBounds((scrH / 15), (scrH * 13 / 15), (scrW / 15), (scrH / 15));
        add(ctL);
        addMouseListener(this);
    }

    public void mouseClicked(MouseEvent m) {
        // Where was the mouse clicked?
        x = m.getX();
        y = m.getY();
        repaint();
    }

    @Override
    public void mousePressed(MouseEvent e) {}

    @Override
    public void mouseReleased(MouseEvent e) {}

    @Override
    public void mouseEntered(MouseEvent e) {}

    @Override
    public void mouseExited(MouseEvent e) {}

    public void paintComponent(Graphics g) {

        // This always runs.
        ctL.setText(clkCt + "");

        if (clkCt == 0) {
            // This never displays!
            g.setColor(Color.green);
            int r = scrH * 4 / 5;
            g.drawOval((scrH / 10), (scrH / 10), r, r);
        }

        g.setColor(Color.red);
        g.drawLine(oldX, oldY, x, y);
        oldX = x;
        oldY = y;
        clkCt++;
    }

    public void valueChanged(ListSelectionEvent event) {
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                Demo m = new Demo();
                m.demoLines();
                JFrame f = new JFrame("Demo");
                f.add(m);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}

笔记

  1. 不要扩展框架或其他顶级容器。而是创建并使用一个实例。
  2. Java GUI 可能必须在多个平台、不同的屏幕分辨率和使用不同的 PLAF 上工作。因此,它们不利于组件的精确放置。要为强大的 GUI 组织组件,请改为使用布局管理器或它们的组合,以及用于空白空间的布局填充和边框。
  3. 而不是在顶级容器中进行绘画,例如在方法中JFrame添加JPanel& 进行自定义绘画paintComponent(Graphics)。还为自定义组件返回一个合理的首选大小,以帮助布局管理器。
  4. 对于 a 中的自定义绘画JComponent,覆盖paintComponent(Graphics)而不是paint(Graphics).
于 2013-06-17T06:48:52.640 回答
1

覆盖时,您应该始终将super.paintComponent()其作为第一行调用paintComponent()

于 2013-06-16T20:28:50.300 回答