为什么我的JComboBox没有涂在我的图纸上?

时间:2014-01-27 20:54:12

标签: java swing

我正在使用Java中的简单绘图板,我有一些用户可以使用的工具:笔和橡皮擦。但是用于选择工具的JComboBox没有出现,即使它被添加了。我听说定制油漆会掩盖任何JComponents。如果这是真的,我怎样才能让JComboBox始终处于领先地位?

窗口图片:

picture of bugged window

这是我的代码:

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.JComboBox;
import javax.swing.JFrame;


public class DrawFrame extends JFrame implements MouseMotionListener, Runnable {
    private static final long serialVersionUID = 1L;

    private Image dbi;
    private Graphics dbg;

    ArrayList<Integer> px = new ArrayList<Integer>();
    ArrayList<Integer> py = new ArrayList<Integer>();

    int mx;
    int my;

    @SuppressWarnings("rawtypes")
    JComboBox tool = new JComboBox();

    @SuppressWarnings("unchecked")
    public DrawFrame() {

        setSize(480, 480);
        setTitle("ScratchPad _14");
        setLayout(new FlowLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setBackground(Color.WHITE);
        setOpacity(1);

        tool.addItem("Pen");
        tool.addItem("Eraser");

        tool.setEnabled(true);

        add(tool);

        setVisible(true);

        addMouseMotionListener(this);

    }

    /*@Override
    public void mouseClicked(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }

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

    }

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

    }

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

    }

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

    }*/

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        DrawFrame df = new DrawFrame();
        Thread t = new Thread(df);

        t.start();

    }

    public void paint(Graphics g) {

        dbi = createImage(getWidth(), getHeight());
        dbg = dbi.getGraphics();
        draw(dbg);
        g.drawImage(dbi, 0, 0, null);

    }

    private void draw(Graphics g) {
        // TODO Auto-generated method stub

        super.paint(g);

        g.setColor(getBackground());
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(Color.BLACK);
        for (int i = 0; i < px.size(); i++) {

            g.fillOval(px.get(i), py.get(i), 3, 3);

        }

        g.setColor(Color.BLUE);
        g.drawString("(" + mx + ", " + my + ")", mx + 10, my - 5);

        repaint();

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub

        while(true) {

            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    @Override
    public void mouseDragged(MouseEvent m) {
        // TODO Auto-generated method stub

        int x = m.getX();
        int y = m.getY();

        mx = x;
        my = y;

        px.add(x);
        py.add(y);

    }

    @Override
    public void mouseMoved(MouseEvent m) {
        // TODO Auto-generated method stub

        int x = m.getX();
        int y = m.getY();

        mx = x;
        my = y;

    }

}

提前致谢!

3 个答案:

答案 0 :(得分:2)

因为您调用了super.paint,其中绘制了子组件,以及其他内容

super.paint(g);

然后使用...

用背景颜色填充整个帧
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());

在它之前绘制的擦除......

你应该避免覆盖paint等顶级容器JFrame,除了你在框架装饰下绘画并且它不是双重缓冲的事实,这些容器实际上是由一个编号产生最终输出的复合成分。

而是创建一个自定义组件,例如JPanel,并覆盖其paintComponent方法。将您的自定义绘画放在这里。

将组合框和自定义绘画面板分别添加到框架

此外,不要从任何可能生成重绘事件的绘制方法中调用任何内容(如调用repaint),这将设置一个无限循环,这将很快消耗你的CPU

请查看Performing Custom Painting了解详情

答案 1 :(得分:0)

通常,通常应该覆盖JFrame的paint方法。相反,您应该扩展JPanel,并使用重写的paintComponent方法进行绘制。

class PaintPanel extends JPanel
{
    public PaintPanel()
    {
        setOpaque(false);
    }

    @Override 
    protected void paintComponent(Graphics g) 
    {
        // Paint what you have been painting 
        // in your "draw" method ...
        ...
        super.paintComponent(g);
    }
}

通常,super.paintComponent(g)调用应该是对这种重写方法的第一次调用,但由于你想要将ComboBox绘制在你自己绘制的所有内容之上,它必须是最后一个。

其他问题:

  • 什么是线程?
  • 你为什么要做手动双缓冲?
  • 如果您想要手动双缓冲,则不应在每次绘画调用中重新创建图像

稍微清理一下,而不是“很好”,但是......仍然像原始程序一样,至少:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class DrawFrame extends JFrame implements MouseMotionListener {
    private static final long serialVersionUID = 1L;

    ArrayList<Integer> px = new ArrayList<Integer>();
    ArrayList<Integer> py = new ArrayList<Integer>();

    int mx;
    int my;

    @SuppressWarnings("rawtypes")
    JComboBox tool = new JComboBox();

    @SuppressWarnings("unchecked")
    public DrawFrame() {

        setSize(480, 480);
        setTitle("ScratchPad _14");
        setLayout(new GridLayout(1,1));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(false);
        setBackground(Color.WHITE);
        setOpacity(1);

        tool.addItem("Pen");
        tool.addItem("Eraser");

        tool.setEnabled(true);

        JPanel paintPanel = new PaintPanel();
        paintPanel.add(tool);
        add(paintPanel);

        setVisible(true);

        paintPanel.addMouseMotionListener(this);

    }
    public static void main(String[] args) {
        DrawFrame df = new DrawFrame();
    }

    class PaintPanel extends JPanel
    {
        public PaintPanel()
        {
            setOpaque(false);
        }

        @Override 
        protected void paintComponent(Graphics g) 
        {
            g.setColor(getBackground());
            g.fillRect(0, 0, getWidth(), getHeight());

            g.setColor(Color.BLACK);
            for (int i = 0; i < px.size(); i++) {
                g.fillOval(px.get(i), py.get(i), 3, 3);
            }
            g.setColor(Color.BLUE);
            g.drawString("(" + mx + ", " + my + ")", mx + 10, my - 5);
            super.paintComponent(g);
        }
    }

    @Override
    public void mouseDragged(MouseEvent m) {
        int x = m.getX();
        int y = m.getY();

        mx = x;
        my = y;

        px.add(x);
        py.add(y);

        repaint();
    }

    @Override
    public void mouseMoved(MouseEvent m) {
        int x = m.getX();
        int y = m.getY();

        mx = x;
        my = y;

    }

}

答案 2 :(得分:0)

绘图不应该调用重绘。我已经在mouseDragged中完成了这个,延迟为50毫秒。 然后,默认为双缓冲,因此您不会先在图像中收集所有更改。 擦除也是为一个人完成的。

所以代码变成:

@Override
public void paint(Graphics g) {
    super.paint(g);
    g.setColor(Color.BLACK);
    for (int i = 0; i < px.size(); i++) {
        g.fillOval(px.get(i), py.get(i), 3, 3);
    }

    g.setColor(Color.BLUE);
    g.drawString("(" + mx + ", " + my + ")", mx + 10, my - 5);
}

@Override
public void mouseDragged(MouseEvent m) {
    ...
    repaint(50L);
}

通常会引入一个用于绘画的JPanel,它有一个paintComponent来覆盖。