2017-02-11 76 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()方法的末尾,並且它完美地工作。

相關問題