在JPanel中进行故障排除 [英] Trouble Drawing In JPanel

查看:129
本文介绍了在JPanel中进行故障排除的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我首先要说的是,我几乎可以保证这个问题将是一个副本,但是我找不到符合我的需求/在我的程序上工作过的其他答案.我需要在JPanel上绘制,但似乎无法获得需要绘制的线条.

I'm going to start off by saying that I can almost guarantee that this question is going to be a copy but I couldn't find any other answers that suited my needs / worked on my program. I need to draw on a JPanel, but I can't seem to be able to get the line I need to draw to show up.

JFrame drawF = new JFrame("Simulator");
        JPanel simPanel = new JPanel();
        drawF.setVisible(true);
        drawF.setSize(1000,650);
        drawF.add(simPanel);
        drawF.pack();
        simPanel.setLayout(null);
        simPanel.setSize(1000,650);
        simPanel.setVisible(true);
        simPanel.setBackground(Color.BLACK);

        //add drawing surface


        //start drawing
            simPanel.add(new JComponent()
            {
            public void paint(Graphics g)
            {
                g.setColor(Color.RED);
                int xLast,yLast;
                for(int i=0;i < 5000000; i++)  // five million
                {

                    double dX = (Math.E*Math.exp(-numd1*i)*Math.sin(i*numf1+nump1))+(Math.E*Math.exp(-numd2*i)*Math.sin(i*numf2*nump2));
                    double dY = (Math.E*Math.exp(-numd3*i)*Math.sin(i*numf3+nump3))+(Math.E*Math.exp(-numd4*i)*Math.sin(i*numf4*nump4));
                    int drawX = (int)dX;
                    int drawY = (int)dY;
                    if (i==0)
                    {
                        xLast = 0;
                        yLast = 0;
                        g.drawLine(xLast,yLast,drawX,drawY);

                        simPanel.revalidate();
                        simPanel.repaint();
                    }
                    else
                    {
                        xLast = drawX;
                        yLast = drawY;
                        g.drawLine(xLast,yLast,drawX,drawY);

                        simPanel.revalidate();
                        simPanel.repaint();
                    }
                }
            }
        });





        repaint();

向我的JPanel中添加JComponent有什么问题吗?

is there something wrong with adding a JComponent to my JPanel?

推荐答案

您的问题可能是布局管理器之一. JPanel默认使用FlowLayout,因此您的JComponent的大小将调整为其自然的首选大小,即[0,0],因此在这种情况下不会显示任何内容.尝试制作JPanel的布局BorderLayout并添加JComponent BorderLayout.CENTER.

Your problem is likely one of layout manager. JPanel uses FlowLayout by default, so your JComponent will size to its natural preferred size which is [0, 0], and so nothing will show in this situation. Try making your JPanel's layout BorderLayout and add the JComponent BorderLayout.CENTER.

其他问题:

  • 重写JComponent的paintComponent方法,而不是paint方法,否则如果不考虑边框和子项的绘制,则会冒意外的副作用的风险.
  • 在您的替代中调用super的绘画方法,如果您按照我的建议重写paintComponent,请调用super.paintComponent(g);.这将有助于清除所有脏像素.
  • 摆脱所有不必要的重绘,重新验证和setVisible调用.
  • 在将所有组件添加到GUI后,在JFrame上调用setVisible.
  • 我自己,我更喜欢在JPanel的paintComponent方法而不是JComponent中进行绘制,因为它不会自动绘制背景.
  • 我更喜欢在自己的独立班级上绘画,而不是埋在匿名的内部班级里.以这种方式掩埋的功能太重要了.
  • 您在绘画方法中调用的代码运行时间越长或CPU占用的时间越长,GUI的响应就会越慢.在类的构造函数中卸载for循环和数学计算,并从绘画方法中卸载.将结果存储在数组或列表中,或者将其存储到BufferedImage中,然后在paintComponent方法中显示该图像.
  • Override the JComponent's paintComponent method, not the paint method, otherwise you risk unexpected side effects by not taking into account the painting of borders and children.
  • Call the super's painting method in your override, super.paintComponent(g); if you're overriding paintComponent as I recommend. This will help clean any dirty pixels.
  • Get rid of all those unnecessary calls to repaint and revalidate and setVisible.
  • Call setVisible on the JFrame after adding all components to the GUI.
  • Myself, I prefer to paint within a JPanel's paintComponent method, not a JComponent, since it won't paint the background automatically.
  • And I prefer to do my painting in its own stand alone class, not buried within an anonymous inner class. It's too important a function to bury in such a way.
  • The more long running or CPU-intense code you call within a painting method, the less responsive your GUI will seem. Off load the for loops and the math calculations in your class's constructor and out of the painting method. Store the results in an array or list, or if you desire paint to a BufferedImage and then display that image within the paintComponent method.

例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;

@SuppressWarnings("serial")
public class DrawingStuff extends JPanel {
    private static final int PREF_W = 1000;
    private static final int PREF_H = 650;
    private static final Color BG = Color.BLACK;
    private static final Color GRAPHICS_COLOR = Color.RED;
    private static final int LOOP_COUNT = 5000000; // 5 million

    private BufferedImage image = null;
    private MathParams[] params;

    public DrawingStuff(MathParams[] params) {
        this.params = params;
        setBackground(BG);
        image = drawImage();
    }

    private BufferedImage drawImage() {
        BufferedImage img = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = img.createGraphics();

        g2.setColor(GRAPHICS_COLOR);
        int xLast, yLast;
        for (int i = 0; i < LOOP_COUNT; i++) {
            double dX = params[0].doCalc0(i) + params[1].doCalc1(i);
            double dY = params[2].doCalc0(i) + params[3].doCalc1(i);
            int drawX = (int) dX;
            int drawY = (int) dY;
            if (i == 0) {
                xLast = 0;
                yLast = 0;
                g2.drawLine(xLast, yLast, drawX, drawY);
            } else {
                xLast = drawX;
                yLast = drawY;
                g2.drawLine(xLast, yLast, drawX, drawY);
            }
        }

        g2.dispose();
        return img;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (image != null) {
            g.drawImage(image, 0, 0, this);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Drawing Stuff");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // TODO: fix this -- what numbers to use??? These don't work
        MathParams[] paramArray = { 
                new MathParams(1, 2, 3), 
                new MathParams(1, 2, 3), 
                new MathParams(3, 4, 5),
                new MathParams(3, 4, 5)
                };

        frame.getContentPane().add(new DrawingStuff(paramArray));
        frame.setResizable(false);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

public class MathParams {
    private int numd;
    private int numf;
    private int nump;

    public MathParams(int numd, int numf, int nump) {
        this.numd = numd;
        this.numf = numf;
        this.nump = nump;
    }

    public double doCalc0(int i) {
        return (Math.E * Math.exp(-numd * i) * Math.sin(i * numf + nump));
    }

    public double doCalc1(int i) {
        return (Math.E * Math.exp(-numd * i) * Math.sin(i * numf * nump));
    }
}

这篇关于在JPanel中进行故障排除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆