Java Swing之谜:什么没有';第一次迭代是否显示在JPanel上?

Java Swing之谜:什么没有';第一次迭代是否显示在JPanel上?,java,swing,graphics,initialization,Java,Swing,Graphics,Initialization,这里有一个我已经接近了解,但从来没有真正了解 下面列出的代码应该在看到第一次单击时立即绘制一个绿色圆圈。没有。后续单击以红色绘制将当前单击点与上一点连接的线。代码在第一次单击时失败,并在随后的所有单击中起作用。为什么第一次单击不显示?它跑了 我做错了什么 代码应该在任何当前JDE上编译 短暂性脑缺血发作 从demolines() 并添加canvas.addMouseListener(这个) 我做错了什么 您正在使用getGraphics进行自定义绘制。调用重新绘制时,以前的任何绘制都将丢失。相反

这里有一个我已经接近了解,但从来没有真正了解

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

我做错了什么

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

短暂性脑缺血发作


demolines()

并添加
canvas.addMouseListener(这个)

我做错了什么

您正在使用
getGraphics
进行自定义绘制。调用
重新绘制时,以前的任何绘制都将丢失。相反,将所有自定义绘制功能移动到基于
JComponent
JPanel
的新类中,并在其中重写。请记住调用
super.paintComponent(g)


有关从
paintComponent
中绘制多个组件的解决方案,请参见。您可以构建自定义可绘制组件的
列表
,从方法中迭代列表,并根据需要使用
drawLine
drawOval

重写
paintComponent()时,应始终将
super.paintComponent()
作为第一行调用

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

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);
    }
}

笔记
  • 不要延伸框架或其他顶级容器。而是创建并使用一个实例
  • javagui可能必须在许多平台上工作,在不同的屏幕分辨率上&使用不同的plaf。因此,它们不利于部件的精确放置。要为健壮的GUI组织组件,请使用布局管理器或它们的组合,以及空白的布局填充和边框
  • paintComponent(Graphics)
    方法中添加
    JPanel
    &进行自定义绘制,而不是在顶级容器(如
    JFrame
    )中进行绘制。还要为自定义构件返回合理的首选尺寸,以帮助布局管理器
  • 对于
    JComponent
    中的自定义绘制,请替代
    paintComponent(Graphics)
    ,而不是
    paint(Graphics)

  • “。当您重写
    paintComponent()
    时”是的,您应该这样做,但是如果您仔细查看代码,您可能会注意到它不会重写该方法,因为1)它包含比常用方法更多的参数,2)
    JFrame
    没有
    paintComponent(Graphics)
    方法!成功了!又好又容易。谢谢谢谢你的密码。它可以工作,但不会改变背景色。这对于我正在进行的更大的项目很重要。当我把JPanel放进相框时,颜色变了。
    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));
    }
    
    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);
        }
    }