摆动时,MouseEvent上的图像无法正确显示

时间:2013-06-28 10:16:25

标签: java swing jpanel graphics2d mouselistener

enter image description here

我在JPanel上渲染了3x3类似棋盘格的图像,并添加到JFrame上。然后我还有9个JPanels(每个方块顶部有1个),点击后需要在相应的方块上绘制。我的问题是它只适用于左上角的广场。其余图纸似乎绘制在棋盘图像下方。因此,如果我注释掉加载棋盘图像的部分,然后单击它们就好了,那么图形就会正确显示。我在分层窗格中得到了相同的结果。使用绝对定位并且坐标似乎是正确的,因为如果我移除了检查板图像,则图形出现在它们应该的位置并且图形不占用超过正方形。  我的代码结构如下:

'main'类创建框架并添加另一个类的实例,该类扩展JPanel并使用paintComponent(Graphics g)绘制棋盘图像。 'main'类还添加了一个类,它扩展了JPanel并使用paintComponent(Graphics g)在鼠标单击上绘制了一些东西。每个实例都放在一个正方形

上面

请注意,因为我打算只使用矩形我将第二个类命名为Rectangles,但它是rectangualar JPanels而不是java Rectangle实例

代码:

public class Main3
{
private JFrame frame=new JFrame("");
private Rectangles rect00=new Rectangles(0,0,129,129);
private Rectangles rect01=new Rectangles(136,0,129,129);
private Rectangles rect02=new Rectangles(268,0,129,129);
private Rectangles rect10=new Rectangles(0,136,129,129);
private Rectangles rect11=new Rectangles(134,136,129,129);
private Rectangles rect12=new Rectangles(269,137,129,129);
private Rectangles rect20=new Rectangles(0,270,129,129);
private Rectangles rect21=new Rectangles(136,269,129,129);
private Rectangles rect22=new Rectangles(269,270,129,129);

public void Display()
 {
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setLayout(null);
    frame.setSize(600,400); 
    sub inter=new sub();
    inter.setLayout(null);
    inter.setBounds(0,0,600,400);
    inter.setSize(600,400);

    rect00.setBounds(rect00.getX(),rect00.getY(),rect00.getWidth(),rect00.getHeight());
    rect01.setBounds(rect01.getX(),rect01.getY(),rect01.getWidth(),rect01.getHeight());
    rect02.setBounds(rect02.getX(),rect02.getY(),rect02.getWidth(),rect02.getHeight());
    rect10.setBounds(rect10.getX(),rect10.getY(),rect10.getWidth(),rect10.getHeight());
    rect11.setBounds(rect11.getX(),rect11.getY(),rect11.getWidth(),rect11.getHeight());
    rect12.setBounds(rect12.getX(),rect12.getY(),rect12.getWidth(),rect12.getHeight());
    rect20.setBounds(rect20.getX(),rect20.getY(),rect20.getWidth(),rect20.getHeight());
    rect21.setBounds(rect21.getX(),rect21.getY(),rect21.getWidth(),rect21.getHeight());
    rect22.setBounds(rect22.getX(),rect22.getY(),rect22.getWidth(),rect22.getHeight());
    rect00.setOpaque(false);
    rect01.setOpaque(false);
    rect02.setOpaque(false);
    rect10.setOpaque(false);
    rect11.setOpaque(false);
    rect12.setOpaque(false);
    rect20.setOpaque(false);
    rect21.setOpaque(false);
    rect22.setOpaque(false);

    inter.add(rect00);
    inter.add(rect01);
    inter.add(rect02);
    inter.add(rect10);
    inter.add(rect11);
    inter.add(rect12);
    inter.add(rect20);
    inter.add(rect21);
    inter.add(rect22);
    frame.add(inter);
    frame.setResizable(false);
    frame.setVisible(true);     
}

public static void main(String args[])
{
    new main().Display();
}


private class sub extends JPanel
{

    private BufferedImage image;

    public sub ()
    {

        try
        {                 
             image=ImageIO.read(new File("image.jpg"));

        }
        catch (IOException e)
        {

            e.printStackTrace();
        }
    }

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(600,400));
    }


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


   }}

这是另一个班级

   public class Rectangles extends JPanel implements MouseListener
   {

private int Posx;
private int Posy;
private int width;
private int height;
private boolean selected=false;
public Rectangles(int Posx,int Posy,int width,int height)
   {
      this.Posx=Posx;
      this.Posy=Posy;
      this.width=width;
      this.height=height;
      this.addMouseListener(this);     
}

@Override
protected void paintComponent(Graphics g)
{
        if(selected==true)
        {
            Graphics2D g2 = (Graphics2D) g;
        super.paintComponent(g2);
      g2.setColor(new Color(250, 235, 215));
       g2.drawRect(Posx,Posy,width,height);
    Graphics2D g3=(Graphics2D)g;
        g2.setColor(new Color(0,0,0));
        g3.setStroke(new BasicStroke(20));
       g3.drawLine(Posx,Posy,Posx+width,Posy+height);
       g3.drawLine(Posx+width,Posy,Posx,Posy+height);

        }   

}

public int getX()
{
    return Posx;
}

public int getY()
{
    return Posy;
}


public int getWidth()
{
    return width;
}


public int getHeight()
{
    return height;
}


public void setSelected()
{
    selected=true;
}

@Override
   public void mouseClicked(MouseEvent arg0)
     {


     }

    @Override
   public void mouseEntered(MouseEvent arg0) 
    {

    }

    public void mouseExited(MouseEvent arg0) 
    {

    }
    @Override
    public void mousePressed(MouseEvent arg0) 
    {

    }

    @Override
   public void mouseReleased(MouseEvent arg0)
   {
        selected=true;
        repaint();


   }

}

1 个答案:

答案 0 :(得分:1)

1)你不尊重组件 paint chain

根据paintComponent(Graphics g)的java文档:

  

此外,如果你没有调用super super的实现,你必须尊重   opaque属性,即如果此组件是不透明的,则必须   以非不透明的颜色完全填充背景。如果你不   尊重不透明属性,你可能会看到视觉文物。

2)super.paintComponent在大多数情况下是方法中的第一个调用。

3)但是还有更多,你对Graphics2D的演员两次,不应该这样做:

Graphics2D g2 = (Graphics2D) g;
...
Graphics2D g3=(Graphics2D)g;

省略g3不需要的Graphics2D已经投放到sub对象

4)inter.add(rect00); inter.add(rect01); ... 课程中存在另一个问题。您可以在主代码中执行此操作:

inter

但在sub中,您只有@Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, null); } 类实例的变量名称:

g2.drawLine(Posx, Posy, Posx + width, Posy + height);

因此无论你添加多少个矩形,它都只会绘制一个图像!

也不要这样做             g2.drawLine(0, 0, Posx + width, Posy + height);而是             x因为JPanel已在其容器上的坐标yimport java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; public class Test { private JFrame frame = new JFrame(""); private Rectangles rect00 = new Rectangles(0, 0, 129, 129); private Rectangles rect01 = new Rectangles(136, 0, 129, 129); private Rectangles rect02 = new Rectangles(268, 0, 129, 129); private Rectangles rect10 = new Rectangles(0, 136, 129, 129); private Rectangles rect11 = new Rectangles(134, 136, 129, 129); private Rectangles rect12 = new Rectangles(269, 137, 129, 129); private Rectangles rect20 = new Rectangles(0, 270, 129, 129); private Rectangles rect21 = new Rectangles(136, 269, 129, 129); private Rectangles rect22 = new Rectangles(269, 270, 129, 129); public void Display() { frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setLayout(null); frame.setSize(600, 400); sub inter = new sub(); inter.setLayout(null); inter.setBounds(0, 0, 600, 400); inter.setSize(600, 400); rect00.setBounds(rect00.getX(), rect00.getY(), rect00.getWidth(), rect00.getHeight()); rect01.setBounds(rect01.getX(), rect01.getY(), rect01.getWidth(), rect01.getHeight()); rect02.setBounds(rect02.getX(), rect02.getY(), rect02.getWidth(), rect02.getHeight()); rect10.setBounds(rect10.getX(), rect10.getY(), rect10.getWidth(), rect10.getHeight()); rect11.setBounds(rect11.getX(), rect11.getY(), rect11.getWidth(), rect11.getHeight()); rect12.setBounds(rect12.getX(), rect12.getY(), rect12.getWidth(), rect12.getHeight()); rect20.setBounds(rect20.getX(), rect20.getY(), rect20.getWidth(), rect20.getHeight()); rect21.setBounds(rect21.getX(), rect21.getY(), rect21.getWidth(), rect21.getHeight()); rect22.setBounds(rect22.getX(), rect22.getY(), rect22.getWidth(), rect22.getHeight()); rect00.setOpaque(false); rect01.setOpaque(false); rect02.setOpaque(false); rect10.setOpaque(false); rect11.setOpaque(false); rect12.setOpaque(false); rect20.setOpaque(false); rect21.setOpaque(false); rect22.setOpaque(false); inter.addPanel(rect00); inter.addPanel(rect01); inter.addPanel(rect02); inter.addPanel(rect10); inter.addPanel(rect11); inter.addPanel(rect12); inter.addPanel(rect20); inter.addPanel(rect21); inter.addPanel(rect22); frame.add(inter); frame.setResizable(false); frame.setVisible(true); } public static void main(String args[]) { new Test().Display(); } private class sub extends JPanel { private BufferedImage image; private ArrayList<Rectangles> rects = new ArrayList<>(); public sub() { try { image = ImageIO.read(new File("c:/image.png")); } catch (IOException e) { e.printStackTrace(); } } @Override public Dimension getPreferredSize() { return (new Dimension(600, 400)); } void addPanel(Rectangles r) { rects.add(r); add(r); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); for (Rectangles r : rects) { g.drawImage(image, r.getX(), r.getY(), null); } } } } class Rectangles extends JPanel implements MouseListener { private int Posx; private int Posy; private int width; private int height; private boolean selected = false; public Rectangles(int Posx, int Posy, int width, int height) { this.Posx = Posx; this.Posy = Posy; this.width = width; this.height = height; this.addMouseListener(this); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (selected == true) { Graphics2D g2 = (Graphics2D) g; g2.setColor(new Color(250, 235, 215)); g2.drawRect(0,0, width, height); g2.setColor(new Color(0, 0, 0)); g2.setStroke(new BasicStroke(20)); g2.drawLine(0,0, width,height); g2.drawLine(getWidth(),0, 0, height); } } public int getX() { return Posx; } public int getY() { return Posy; } public int getWidth() { return width; } public int getHeight() { return height; } public void setSelected() { selected = true; } @Override public void mouseClicked(MouseEvent arg0) { } @Override public void mouseEntered(MouseEvent arg0) { } public void mouseExited(MouseEvent arg0) { } @Override public void mousePressed(MouseEvent arg0) { } @Override public void mouseReleased(MouseEvent arg0) { selected = true; repaint(); } } 中添加,当您在JPanel上绘制时,我们想要从左上角开始,即0,0,更改该值会使图像在其内容上进一步向下移动

请在此处查看固定代码:

Absolute

其他一些指示:

  • 不要使用Null / GridLayout布局。 GridBagLayoutJFrame#setSize(...);可以满足您的需求。 (有关详情,请参阅here。)
  • 请勿LayoutManager使用正确pack()并在JFrame上致电setSize,然后再将其设为可见。
  • 请勿在{{1​​}}个实例上致电Rectangles,只需覆盖getPreferredSize,就像使用sub面板一样?
  • 无需实施MouseListener,只需使用MouseAdapter即可让您自由选择要覆盖的方法,而不是仅覆盖所有方法。
  • Have a read on Concurrency in Swing特别Event-Dispatch-Thread