2017-02-11 54 views
0

我正在尝试编写一个程序,该程序允许用户通过单击窗口中的JButton来创建方块或圆,然后通过单击窗口中的某个位置(而不是按钮)。未使用mouseMoved调用PaintComponent()方法

我目前正在使用两个actionListeners来为不同的按钮添加一个Square或Circle到类型为Shape的数组列表(同时包含正方形和圆形的接口)。我有一个名为frameListener的类,它实现了MouseListener和MouseMotionListener,当鼠标移动时更新正方形或圆形的位置,当鼠标离开窗口时删除正方形或圆形,或者在单击鼠标时停止更新它永久)。我还有一个名为MyPanel的类,它扩展了JPanel,并使用paintComponent(Graphics g)方法在背景上绘制正方形和圆形。为Shape接口

package smys01; 

import java.util.ArrayList; 
import java.text.*; 
import javax.swing.*; 
import java.awt.event.*; 
import java.awt.*; 




public class SMYS01 extends JFrame { 

    private Color c = new Color(0, 0, 0); 
    private static ArrayList<Shape> shapes = new ArrayList(); 
    private static ArrayList<Shape> deleted = new ArrayList(); 

    private Point a; 
    private boolean makeSquare = false, makeCircle = false, makeSquiggle = false; 

    public static void main(String[] args) { 
     SMYS01 window = new SMYS01(); 

    } 
    //good main 

    //0 is empty for making things, 1 is having a square selected to change, 2 is background; 

    private JButton makeSquareB = new JButton("New Square" /*, add icon later*/); 

    private JButton makeCircleB = new JButton("New Circle"); 

    private Color background = new Color(0, 150, 0); 



    public SMYS01() { 
     makeSquareB.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("making square"); 
       if(!makeCircle&&!makeSquare){ 
        makeSquare = true; 

        shapes.ensureCapacity(shapes.size()); 
        shapes.add(new Square((int) a.getX(), (int) a.getY(), c)); 
       }else if(makeSquare){ 

       }else if(makeCircle){ 
        makeCircle=false; 
        makeSquare=true; 
        shapes.remove(shapes.size()-1); 
        shapes.ensureCapacity(shapes.size()); 
        shapes.add(new Square((int) a.getX(), (int) a.getY(), c)); 
       } 
      } 
     }); 


     makeCircleB.addActionListener(new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("making circle"); 
       if(!makeCircle&&!makeSquare){ 
        makeCircle = true; 
        shapes.ensureCapacity(shapes.size()); 
        shapes.add(new Circle((int) a.getX(), (int) a.getY(), c)); 
       }else if(makeCircle){ 

       }else if(makeSquare){ 
        makeSquare=false; 
        shapes.remove(shapes.size()-1); 
        shapes.ensureCapacity(shapes.size()); 
        shapes.add(new Circle((int) a.getX(), (int) a.getY(), c)); 
       } 
      } 
     }); 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane(); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     MyPanel thing = new MyPanel(); 


     frame.addMouseListener(new FrameListener()); 
     frame.setContentPane(thing); 

     frame.setSize(thing.getPreferredSize()); 

     frame.setTitle("Art!"); 

     frame.addMouseMotionListener(new FrameListener()); 
    } 


    private class MyPanel extends JPanel { 

     public MyPanel() { 

      GroupLayout layout = new GroupLayout(this); 
      layout.setHorizontalGroup(
        layout.createSequentialGroup() 
        .addComponent(makeCircleB) 
        .addComponent(makeSquareB) 
      ); 
      layout.setVerticalGroup(
        layout.createSequentialGroup() 
        .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) 
          .addComponent(makeCircleB) 
          .addComponent(makeSquareB) 
        ) 
      ); 

     } 

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

     @Override 
     public void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      g.setColor(background); 
      g.drawRect((int)g.getClipBounds().getX(),(int)g.getClipBounds().getY(),(int)g.getClipBounds().getWidth(),(int)g.getClipBounds().getHeight()); 
      g.fillRect((int)g.getClipBounds().getX(),(int)g.getClipBounds().getY(),(int)g.getClipBounds().getWidth(),(int)g.getClipBounds().getHeight()); 


      System.out.println(shapes.size()); 
      for (Shape i : shapes) { 

       int[] a = i.getDim(); 
       g.setColor(new Color(a[4], a[5], a[6], a[7])); 

       if(i instanceof Square){ 
        g.drawRect(a[0], a[1], a[2], a[3]); 
        g.fillRect(a[0], a[1], a[2], a[3]); 
       }else if(i instanceof Circle){ 
        g.drawOval(a[0], a[1], a[2], a[3]); 
        g.fillOval(a[0], a[1], a[2], a[3]); 
       } 

      } 

     } 
    } 


    class FrameListener implements MouseListener, MouseMotionListener { 


     public void mousePressed(MouseEvent e) { 
      System.out.println("pressed"); 
      a = new Point(e.getPoint()); 
      if (makeSquare) { 
       makeSquare = false; 
       System.out.println("square made!"); 
      } 
      if (makeCircle) { 
       makeCircle = false; 
       System.out.println("cirlce made!"); 
      } 

      //use this for sliders, nothing else. 

     } 

     public void mouseReleased(MouseEvent e) { 
      System.out.println("released"); 
      a = new Point(e.getPoint()); 
      //use for sliders, nothing else. 

     } 

     public void mouseClicked(MouseEvent e) { 
      System.out.println("clicked"); 
      a = new Point(e.getPoint()); 
      //don't need this 
      //makeSquare = false; 
      //makeCircle = false; 

      //makeSquiggle too. 
     } 

     public void mouseMoved(MouseEvent e) { 

      //showing up as false atm 
      a = new Point(e.getPoint()); 
      System.out.println(a); 
      if (makeSquare||makeCircle) { 
       Shape b = shapes.get(shapes.size()-1); 
       b.updateLocation((int) a.getX(), (int) a.getY()); 

      } 


     } 

     public void mouseDragged(MouseEvent e) { 
      //only check if over a JSlider 
     } 

     //complete methods: 
     public void mouseEntered(MouseEvent e) { 
      System.out.println("entered"); 
      //nothing, Mouse re-entering doesn't effect the program. 
     } 

     public void mouseExited(MouseEvent e) { 
      System.out.println("exited"); 
      makeSquare = false; 
      makeCircle = false; 
      makeSquiggle = false; 
      //if mouse leaves the window while trying to make one of these, stop it. 

     } 
    } 



} 

代码:

package smys01; 

public interface Shape { 
    public void updateLocation(int newXPos, int newYPos); 
    public void updateDimensions(int newXDim, int newYDim); 
    public void delete(); 
    public void purge(); 
    public void restore(); 
    public int[] getDim(); 
} 

代码广场: 注意!这段代码被写回了一些,并且有一些部分根本不相关,甚至完整(但完全没有使用)。这是为构造,updateDimensions()方法,和更新位置()方法

package smys01; 
import java.awt.Color; 
public class Square implements Shape{ 
    //tbr=to be returned. 
    boolean deleted=false; 
    boolean purged=false; 
    private int xPos, yPos, xDim, yDim; 
    private int saveXPos, saveYPos, saveXDim, saveYDim, saveR, saveG, saveB, saveA; 
    private Color fill; 
    public Square(int initX, int initY, Color a){ 
     xPos=initX; 
     yPos=initY; 
     xDim=50; 
     yDim=50; 
     fill=a; 
    } 
    public void updateDimensions(int newXDim, int newYDim){ 
     if(purged||deleted) 
      return; 
     if(newXDim<=2){ 
      xDim=2; 
     }else{ 
      xDim=newXDim; 
     } 
     if(newYDim<=2){ 
      yDim=2; 
     }else{ 
      yDim=newYDim; 
     } 

    } 
    public void updateLocation(int newXPos, int newYPos){ 
     if(purged){ 
      return; 
     } 
     if(newXPos<=5){ 
      xPos=5; 


     }else{ 
      xPos=newXPos; 

     } 
     if(newYPos<=25){ 
      yPos=25; 
     }else{ 
      yPos=newYPos; 
     } 


       } 
     public void delete(){ 
     if(!deleted){ 
      saveXPos=xPos; 
      saveYPos=yPos; 
      saveXDim=xDim; 
      saveYDim=yDim; 
      saveR=fill.getRed(); 
      saveB=fill.getBlue(); 
      saveG=fill.getGreen(); 
      saveA=fill.getAlpha(); 
      deleted=true; 
      xPos=-5; 
      yPos=-5; 
      xDim=1; 
      yDim=1; 
         } 
    } 
    public void purge(){ 
     saveXPos=-10; 
     saveYPos=-10; 
     saveXDim=3; 
     saveYDim=3; 
     //use in an if statement, and if true (will be, set the square value to null, so this reference will go away, preventing data overflow 
    } 
    public void restore(){ 
     xPos=saveXPos; 
     yPos=saveYPos; 
     xDim=saveXDim; 
     yDim=saveYDim; 
     deleted=false; 
    } 
    public int[] getDim(){ 
     int[] tbr={xPos,yPos, xDim, yDim,fill.getRed(), fill.getBlue(), fill.getGreen(), fill.getAlpha()}; 
     return tbr; 
    } 
    public String toString(){ 
     String tbr="Square: ("+xPos+", "+yPos+"); ("+xDim+", "+yDim+"); ("+fill.toString(); 
     return tbr; 
    } 

} 

为Circle类的代码是完全相同的,但对象类型允许的paintComponent方法来区分它们。

我想调用mouseMoved时调用paintComponent,但我似乎无法得到它来做到这一点。我尝试过使用repaint(),并且我试图找出几个小时。到目前为止,我已经看到,基本上,Swing会在需要时调用paintComponent(当窗口大小发生变化或窗口被最小化并重新打开时)。

但是,我不确定如何在按下按钮或移动鼠标时调用它,并且repaint()对此不起作用。

我很抱歉,如果一些代码是sl,的,我已经重写了几次,有些部分是不必要的,但仍然存在。

有没有办法从匿名操作类或FrameListener类中主动调用paintComponent方法?

+2

你试过调用'repaint'吗?考虑提供一个[可运行的示例](https://stackoverflow.com/help/mcve),它可以证明你的问题。这不是代码转储,而是您正在做的事情的一个例子,它突出了您遇到的问题。这会导致更少的混淆和更好的响应 – MadProgrammer

+0

@MadProgrammer是的,我曾尝试在mousePressed()和mouseMoved()中调用repaint,并且它什么也不做。我将包含上面的完整代码,代替可运行示例。 –

+1

然后,你将要创建一个有效的[mcve],一个** small **,其实这个程序我们可以编译和运行,没有外部依赖关系(如数据库或图像),而且直接向我们展示你的问题。 –

回答

1

经过来自@MadProgrammer的一些输入,我想出了什么不起作用。 mouseListener被附加到JFrame而不是JPanel,所以事件被触发,但paintComponent(通过repaint())不是。我将它添加到面板并将repaint()添加到mouseMoved()方法的末尾,并且它完美地工作。