简体   繁体   English

为什么在此JPanel上显示此JMenu?

[英]Why is the this JMenu being displayed on this JPanel?

This illustrates my problem 这说明了我的问题

Im trying to copy a paint like program but whenever I click on the screen the menu bar is displayed in the panel area. 我试图复制类似程序的绘画,但是每当我单击屏幕时,菜单栏就会显示在面板区域中。 It doesn't do it unless I click on the screen (to draw). 除非我在屏幕上单击(绘制),否则它不会这样做。 The menu bar is added before the panel, any help would be much appreciated. 菜单栏被添加到面板之前,任何帮助将不胜感激。

public class Main {
public static Frame frame;
public static Panel panel;
public static MenuBar menubar;
public static void main(String[] args) {
    frame = new Frame();
    panel = new Panel();
    menubar = new MenuBar();
    frame.setJMenuBar(menubar);
    frame.addMouseMotionListener(panel);
    frame.add(panel);
    frame.setVisible(true);     
}

} }

public class Frame extends JFrame {
public Frame() {
    setTitle("Paint");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setExtendedState(JFrame.MAXIMIZED_BOTH);
}

} }

public class Panel extends JPanel implements MouseMotionListener {

public boolean isMouseDown = false;
public int x1,y1, x2, y2;
public Color colour = Color.BLACK;
public int size = 3;

public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(colour);
    g2.setStroke(new BasicStroke(size));
    g2.drawLine(x1 - 10, y1 - 80, x2 - 10, y2 - 80);
}

public void mouseDragged(MouseEvent arg0) {
    x1 = x2;
    y1 = y2;
    x2 = arg0.getX();
    y2 = arg0.getY();
    repaint();
}

public void mouseMoved(MouseEvent arg0) {
    x1 = x2;
    y1 = y2;
    x2 = arg0.getX();
    y2 = arg0.getY();
}

public void mouseClicked(MouseEvent arg0) {}

public void mouseEntered(MouseEvent arg0) {}

public void mouseExited(MouseEvent arg0) {}

} }

public class MenuBar extends JMenuBar {

JMenu file = new JMenu("File");
JMenu brush = new JMenu("Pen");
JMenu colour = new JMenu("Colour");
Font font = new Font("Times New Romans", Font.PLAIN, 18);

public MenuBar() {  
   //JMenuBar Code here, left black as very long
}

} }

One problems: You need to call super.paintComponent(g); 问题之一:您需要调用super.paintComponent(g); within your paintComponent method. 在paintComponent方法中。 Else the JPanel cannot do its house-keeping painting of its own self. 否则,JPanel不能自己做房屋整理画。

If you want the drawings to persist, then either create an ArrayList of lines that are then drawn within paintComponent in a for loop, or better, paint onto a BufferedImage which is then displayed within the paintComponent method. 如果要使图形持久化,则可以创建一个线的ArrayList,然后在for循环中的paintComponent中绘制这些线,或者最好将其绘制到BufferedImage上,然后将其显示在paintComponent方法中。

eg, 例如,

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;

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

    private static void createAndShowGui() {
        MyPainting mainPanel = new MyPainting();
        MenuCreator menuCreator = new MenuCreator(mainPanel);

        JFrame frame = new JFrame("MyPainting");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.setJMenuBar(menuCreator.getMenubar());
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

@SuppressWarnings("serial")
class MyPainting extends JPanel {
    private static final int IMG_W = 600;
    private static final int IMG_H = 450;
    private static final int STROKE_W = 3;
    private static final Stroke STROKE = new BasicStroke(STROKE_W);
    private BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
    private Color drawColor = Color.BLACK;

    public MyPainting() {
        setPreferredSize(new Dimension(IMG_W, IMG_H));
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

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

    private class MyMouse extends MouseAdapter {
        private Graphics2D g2 = null;
        private Point p0;

        @Override
        public void mousePressed(MouseEvent e) {
            if (img == null) {
                return;
            }
            g2 = img.createGraphics();
            g2.setStroke(STROKE);
            g2.setColor(drawColor);
            p0 = e.getPoint();
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (p0 == null) {
                return;
            }
            drawLine(e);

        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (p0 == null) {
                return;
            }
            drawLine(e);
            g2.dispose();
            p0 = null;
        }

        private void drawLine(MouseEvent e) {
            Point p1 = e.getPoint();
            g2.drawLine(p0.x, p0.y, p1.x, p1.y);
            repaint();
            p0 = p1;
        }

    }

    public void setDrawColor(Color drawColor) {
        this.drawColor = drawColor;
    }

    public void clear() {
        img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_ARGB);
        repaint();
    }
}

class MenuCreator {
    private JMenuBar menubar = new JMenuBar();
    private MyPainting myPainting;

    public MenuCreator(MyPainting myPainting) {
        JMenuItem clearDrawing = new JMenuItem(new AbstractAction("Clear Drawing") {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                if (myPainting != null) {
                    myPainting.clear();
                }
            }
        });
        JMenu fileMenu = new JMenu("File");
        fileMenu.add(clearDrawing);

        JMenu colourMenu = new JMenu("Colour");
        for (MyColor myColor : MyColor.values()) {
            colourMenu.add(new JMenuItem(new ColorAction(myColor)));
        }

        menubar.add(fileMenu);
        menubar.add(new JMenu("Pen"));
        menubar.add(colourMenu);
        this.myPainting = myPainting;
    }

    public JMenuBar getMenubar() {
        return menubar;
    }

    private class ColorAction extends AbstractAction {
        private MyColor myColor;

        public ColorAction(MyColor myColor) {
            super(myColor.getText());
            this.myColor = myColor;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (myPainting != null) {
                myPainting.setDrawColor(myColor.getColor());
            }
        }
    }
}

enum MyColor {
    BLACK("Black", Color.BLACK), RED("Red", Color.RED), ORANGE("Orange", Color.ORANGE), BLUE("Blue", Color.BLUE);

    private String text;
    private Color color;
    private MyColor(String text, Color color) {
        this.text = text;
        this.color = color;
    }

    public String getText() {
        return text;
    }

    public Color getColor() {
        return color;
    }

}

You failed to honour the requirements of the paint chain... 您未能遵守油漆链的要求。

public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(colour);
    g2.setStroke(new BasicStroke(size));
    g2.drawLine(x1 - 10, y1 - 80, x2 - 10, y2 - 80);
}

Apart from not needing to be public , one of the jobs of paintComponent is to prepare the Graphics context for painting. 除了不需要publicpaintComponent的工作之一是为绘画准备Graphics上下文。 So, one of the first things you should do is call super.paintComponent before you do any custom painting. 因此,您应该做的第一件事就是super.paintComponent任何自定义绘制之前调用super.paintComponent

protected void paintComponent(Graphics g) {
    super. paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(colour);
    g2.setStroke(new BasicStroke(size));
    g2.drawLine(x1 - 10, y1 - 80, x2 - 10, y2 - 80);
}

Graphics is a shared context, it is shared amongst the other components which need to be painted, so it is very important that you ensure that it's properly prepared before you paint to it. Graphics是一个共享的上下文,它在需要绘制的其他组件之间共享,因此在绘制之前确保正确准备非常重要。

It's also important that any significant modifications you make to the context (like transformations or rendering hints) are reversed before the method exists 同样重要的是,在方法存在之前,您对上下文所做的任何重大修改(例如转换或渲染提示)都必须撤消

I would recommend taking a look at Performing Custom Painting and Painting in Swing to gain a better understanding into how the painting system actually works 我建议您看一下《 在Swing执行自定义绘画绘画》,以更好地了解绘画系统的实际工作原理

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM