Как нарисовать изображение под открытым меню - PullRequest
2 голосов
/ 16 марта 2012

Я реализую свою собственную двойную буферизацию для BufferedImage в JPanel, чтобы я мог отображать местоположение мыши в BufferedImage, не перерисовывая каждый объект обратно на него при перемещении мыши.Когда JMenu в родительском JFrame открыт, BufferedImage перекрашивается поверх JMenu.

Этот класс не завершен и содержит только необходимые методы,

    public class Foo extends JPanel implements ComponentListener {
        BufferedImage bufferedImage;
        long mousePosX;
        long mousePoxY;

        protected void paintComponent(Graphics g) {
            paintComponent(g, this.xform);
        }
        protected void paintComponent(Graphics graphics, XFormPixel xformIn) {
            bufferedImage = new BufferedImage(this.getWidth(),this.getHeight(),BufferedImage.TYPE_INT_RGB);
            Graphics g = bufferedImage.getGraphics();
            super.paintComponent(g);
            //Draw lots of stuff to graphics

            if(drawMouseLocation) {
                int width = this.getWidth();
                int height = this.getHeight();
                Color origColor = g.getColor();
                g.setColor(textColor);
                if (cursorLocation != null) {
                    g.drawString("X: "+mousePosX + " Y: " + mousePosY);
                }
            }

            g.setColor(origColor);
            graphics.drawImage(bufferedImage,0,0,null);
        }

        public void drawMouseLocation() {   

            int width = this.getWidth();
            int height = this.getHeight();
            Image image = bufferedImage;
            Graphics graphics = this.getGraphics();
            Graphics g = image.getGraphics();
            Color origColor = g.getColor();
            g.setColor(textColor);
            if (cursorLocation != null) {
                g.drawString("X: "+mousePosX + " Y: " + mousePosY);
            }
            g.setColor(origColor);
            graphics.drawImage(image,0,0,this);
        }
    }

Есть ли другой способ сделать это?

Еще один возможный разрыв заключается в том, что, когда FooJPanel инициализируется, имеет черную рамку, но когда изображение нарисовано для отображения расположения мыши, оно исчезает.Я предполагаю, что вызов repaint () или что-то для родителя решит обе проблемы, но это также вызовет перерисовку для ребенка, чего я пытаюсь избежать.

РЕДАКТИРОВАТЬ 1: Вот запрошенныйисполняемый код.При создании я не смог заставить работать двойную буферизацию правильно, поэтому у меня также возникают проблемы с мерцанием положения мыши при перемещении мыши.

    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import javax.swing.AbstractAction;
    import javax.swing.Action;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;

    public class DrawingTestFrame extends JFrame {
        private static final long serialVersionUID = 1L;        

        public static void main(String[] args) {
                new DrawingTestFrame();
        }   
        public DrawingTestFrame() {
                init();
        }

        public void init() {
                JMenuBar menuBar = new JMenuBar();                  
                    setJMenuBar(menuBar);
                JMenu dropMenu = new JMenu("Drop This");
                dropMenu.add(needs);
                dropMenu.add(to);
                dropMenu.add(overlap);
                menuBar.add(dropMenu);          
                    DrawingTest test = new DrawingTest();
                setTitle("Drawing Test");
                add(test);
                setMinimumSize(new Dimension(550,270));
                pack();
                setVisible(true);
        }

            public static Action needs = new AbstractAction("Needs") {
                private static final long serialVersionUID = 1L;
                public void actionPerformed(ActionEvent ae) {}};    
            public static Action to = new AbstractAction("To") {
                private static final long serialVersionUID = 1L;
                public void actionPerformed(ActionEvent ae) {}};    
            public static Action overlap = new AbstractAction("Overlap") {
                private static final long serialVersionUID = 1L;
                public void actionPerformed(ActionEvent ae) {}};    
    }


    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.MouseInfo;
    import java.awt.Point;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.awt.image.BufferedImage;
    import javax.swing.BorderFactory;
    import javax.swing.JPanel;

    public class DrawingTest extends JPanel implements MouseListener  {
        private static final long serialVersionUID = 1L;
            public Component parent;
            private Point mouseLocation;
            private BufferedImage bufferedImage;
            public DrawingTest() {
                    init();
            }        
            public void init() {
                    this.setPreferredSize(new Dimension(100, 100));
                    this.setBorder(BorderFactory.createLineBorder(Color.BLACK));
                    this.addMouseListener(this);
                    this.addMouseMotionListener(new MouseMotionListener() {
                public void mouseDragged(MouseEvent e) {
                    mouseLocation = MouseInfo.getPointerInfo().getLocation();
                    DrawingTest.this.repaint();
                }

                public void mouseMoved(MouseEvent e) {
                    mouseLocation = MouseInfo.getPointerInfo().getLocation();
                    DrawingTest.this.drawLocation();
                }
                    });
                    this.setVisible(true);
            }
        public void mouseClicked(MouseEvent e) {
            mouseLocation = MouseInfo.getPointerInfo().getLocation();
            this.repaint();
        }
        public void mousePressed(MouseEvent e) {}
        public void mouseReleased(MouseEvent e) {}
        public void mouseEntered(MouseEvent e) {}
        public void mouseExited(MouseEvent e) {}

            protected void paintComponent(Graphics graphics) {
                    bufferedImage = new   
                            BufferedImage(this.getWidth(),this.getHeight(),BufferedImage.TYPE_INT_RGB);
                    Graphics2D g = bufferedImage.createGraphics();
                    super.paintComponent(g);
                    g.setColor(Color.red);
                    g.drawRect(10,10,110,110);
                    graphics.drawImage(bufferedImage,0,0,null);
                    if (mouseLocation != null) {
                        graphics.drawString("X: " + mouseLocation.getX() + 
                "  Y: " + mouseLocation.getY(), this.getWidth()/2 - 50, this.getHeight()-10);
                    }
            }
            protected void drawLocation() {
                    this.getGraphics().drawImage(bufferedImage, 0,0,null);
                    this.getGraphics().setColor(Color.green);
                    if (mouseLocation != null) {
                        this.getGraphics().drawString("X: " + mouseLocation.getX() + 
                "  Y: " + mouseLocation.getY(), this.getWidth()/2 - 50, this.getHeight()-10);
                    }
            }
    }

Спасибо!

Ответы [ 2 ]

1 голос
/ 22 марта 2012

Проблема в том, что вы получаете объект Graphics, вызывая getGraphics () для компонента, а этого делать не следует.Почему вы делаете эту домашнюю двойную буферизацию и где вы читали, что это способ ее реализации?Я хотел бы увидеть этот учебник.Если бы это было мое приложение, я бы либо:

  • использовал бы BufferedImage для своих фоновых изображений и просто рисовал поверх него в paintComponent, возможно, ограничивая мою картину прямоугольником интереса ...
  • или показать мою позицию мыши, используя JLabel.

Например, этот код показывает обе техники:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import javax.swing.*;

@SuppressWarnings("serial")
public class DrawingTestFrame2 {
   private static void createAndShowGui() {
      JFrame frame = new JFrame("DrawingTestFrame2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      DrawingTest2 drawingTest = new DrawingTest2();

      frame.getContentPane().add(drawingTest);
      frame.setJMenuBar(drawingTest.createMenuBar());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class DrawingTest2 extends JPanel {

   private static final int PREF_W = 500;
   private static final int PREF_H = 300;
   private static final int RECT_W = 100;
   private static final int RECT_H = 20;
   public static final Rectangle BOTTOM_RECT = new Rectangle(PREF_W/2 - RECT_W/2, PREF_H - RECT_H, 
         RECT_W, RECT_H);
   private String[] menuItemStrings = {"One", "Two", "Three"};
   public Point mouseLocation;
   private BufferedImage bufferedImage = new BufferedImage(PREF_W, PREF_H, 
         BufferedImage.TYPE_INT_ARGB);
   private JLabel mousePositionLabel = new JLabel("", SwingConstants.RIGHT);

   public DrawingTest2() {
      MouseAdapter mouseAdapter = new MyMouseAdapter();
      addMouseListener(mouseAdapter);
      addMouseMotionListener(mouseAdapter);

      mousePositionLabel.setForeground(Color.gray);
      setLayout(new GridBagLayout());
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 1;
      gbc.gridy = 1;
      gbc.gridwidth = 1;
      gbc.gridheight = 1;
      gbc.weightx = 1.0;
      gbc.weighty = 1.0;
      gbc.anchor = GridBagConstraints.SOUTHEAST;
      add(mousePositionLabel, gbc);

      Graphics2D g2 = bufferedImage.createGraphics();
      g2.setPaint(new GradientPaint(0, 0, Color.yellow, 40, 40, Color.green, true));
      g2.fillRect(0, 0, PREF_W, PREF_H);
      g2.dispose();
      g2 = bufferedImage.createGraphics();
      g2.setColor(Color.red);
      g2.setStroke(new BasicStroke(3f));
      g2.drawRect(10, 10, 110, 110);
      g2.dispose();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (bufferedImage != null) {
         g.drawImage(bufferedImage, 0, 0, this);
      }
      if (mouseLocation != null) {
         g.drawString("X: " + mouseLocation.getX() + "  Y: "
               + mouseLocation.getY(), this.getWidth() / 2 - 50,
               this.getHeight() - 10);
      }
   }

   public JMenuBar createMenuBar() {
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("Menu");
      for (int i = 0; i < menuItemStrings .length; i++) {
         menu.add(new JMenuItem(menuItemStrings[i]));
      }
      menuBar.add(menu );
      return menuBar;
   }

   class MyMouseAdapter extends MouseAdapter {
      @Override
      public void mouseMoved(MouseEvent mEvt) {
         mouseLocation = mEvt.getLocationOnScreen();
         repaint(BOTTOM_RECT);

         String mousePosStr = String.format("x:%d y:%d", mouseLocation.x, mouseLocation.y);
         mousePositionLabel.setText(mousePosStr);
      }
   }
}
0 голосов
/ 16 марта 2012

Существует класс с именем DisplayJAI. Это может отображать PlanarImage (вы можете использовать PlanarImage, чтобы обернуть BufferedImage). Он расширяет JPanel и уже дает вам всех слушателей мыши, которые вам нужны. Вам не нужно переписывать краску или делать что-либо в этом вопросе.

...