簡體   English   中英

Java:Swing中的重繪不起作用

[英]Java: Repaint in Swing Not Working

我正在學習Java swing,並且無法使用以下程序。 它創建一個小框架,頂部有一個退出按鈕。 目的是在單擊鼠標的任何地方顯示坐標。 當我單擊鼠標時2發生了不需要的事情:

  1. 鼠標單擊將覆蓋退出按鈕,並且不再響應(而不是響應事件和退出,而是在退出按鈕的頂部顯示坐標)。
  2. 當我單擊新位置時,舊位置的坐標仍然存在。

此討論基礎上,我在進行repaint() revalidate()之前使用了removeAll()revalidate() ,但這沒有幫助。 這段代碼是從這里獲取的,用來對在線文檔進行研究的原因代碼。

有指針嗎?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JLabel;

public class QuitCoordinateTest {
  public static void main(String[] args){
    GUI gui = new GUI();
  }
}

class MyFrame extends JFrame implements ActionListener{
  int clickX;
  int clickY;

  public void paint(Graphics g){
    g.drawString("" + clickX + ", " + clickY, clickX, clickY);
  }

  public void actionPerformed(ActionEvent e){
    System.exit(0);
  }
}
//=======================================================//

class GUI extends MyFrame {
  JButton quitButton = new JButton("Quit");

  public GUI(){

    MyFrame displayWindow = new MyFrame();
    displayWindow.setTitle("Title");

    /*
    JPanel buttonPanel = new JPanel();
    buttonPanel.add(quitButton);
    displayWindow.getContentPane().add(buttonPanel,BorderLayout.NORTH);
    JPanel textPanel = new JPanel();
    */

    displayWindow.getContentPane().add(quitButton,BorderLayout.NORTH);
    quitButton.addActionListener(displayWindow);
    displayWindow.setSize(201,201);
    displayWindow.setVisible(true); 
//    displayWindow.pack();

    displayWindow.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

    displayWindow.addMouseListener(new MouseProc(displayWindow));

  }//end constructor

}//end class GUI definition
//=======================================================//

//This listener class monitors for mouse presses and 
// displays the coordinates of the mouse pointer when the
// mouse is pressed on the source object. 

class MouseProc extends MouseAdapter{
  MyFrame refToWin;

  MouseProc(MyFrame inWin){
    refToWin = inWin;
  }

  //Override the mousePressed method to determine and 
  // display the coordinates when the mouse is pressed.
  public void mousePressed(MouseEvent e){

    refToWin.removeAll();
    refToWin.clickX = e.getX();
    refToWin.clickY = e.getY();

    //Force the JFrame object to be repainted in order to
    // display the coordinate information.

    refToWin.removeAll();
    refToWin.validate();
    refToWin.repaint();

  }
}
  1. repaint()工作正常。
  2. 避免直接在JFrame上繪制。
  3. 而是在protected void paintComponent(Graphics g)繪制protected void paintComponent(Graphics g)方法重寫,然后將其顯示在JFrame中。
  4. 確保在paintComponent覆蓋內部調用paintComponent(g)paintComponent(g)方法-這將擦除舊圖像,這是問題之一的原因。
  5. 在代碼中使用合理的注釋。 過多的注釋和過多的文本分散了您的注意力,使您難以理解代碼。
  6. 只需在JFrame上調用removeAll()即可-刪除所有組件,包括按鈕。 你怎么叫這個 您確定要調用此方法嗎?
  7. 次要的選擇-您將要避免直接設置另一個類的字段,例如clickX和clickY字段。 而是將它們設為私有,並且僅允許外部類通過公共方法對其進行修改。 盡管對於這個小程序來說可能無關緊要,但是當您開始擴大程序規模並創建具有復雜交互作用的大型程序時,這將非常重要。 這里成功的關鍵是限制和控制類之間的所有通信,以避免難以發現的副作用。

例如,類似...

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      String str = String.format("[%d, %d]", clickX, clickY);
      g.drawString(str, clickX, clickY);
   }

   public int getClickX() {
      return clickX;
   }

   public void setClickX(int clickX) {
      this.clickX = clickX;
   }

   public int getClickY() {
      return clickY;
   }

   public void setClickY(int clickY) {
      this.clickY = clickY;
   }

例如

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class DetectClicks extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = 650;
   private int clickX;
   private int clickY;

   public DetectClicks() {
      MyMouseListener mouseAdapter = new MyMouseListener(this);
      addMouseListener(mouseAdapter);
      addMouseMotionListener(mouseAdapter); // to allow dragging!
   }

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

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      String str = String.format("[%d, %d]", clickX, clickY);
      g.drawString(str, clickX, clickY);
   }

   public int getClickX() {
      return clickX;
   }

   public void setClickX(int clickX) {
      this.clickX = clickX;
   }

   public int getClickY() {
      return clickY;
   }

   public void setClickY(int clickY) {
      this.clickY = clickY;
   }

   private static void createAndShowGui() {
      DetectClicks mainPanel = new DetectClicks();

      JFrame frame = new JFrame("DetectClicks");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

class MyMouseListener extends MouseAdapter {
   private DetectClicks detectClicks;

   public MyMouseListener(DetectClicks detectClicks) {
      this.detectClicks = detectClicks;
   }

   @Override
   public void mousePressed(MouseEvent evt) {
      showPoint(evt);
   }

   @Override
   public void mouseDragged(MouseEvent evt) {
      showPoint(evt);
   }

   private void showPoint(MouseEvent evt) {
      detectClicks.setClickX(evt.getX());
      detectClicks.setClickY(evt.getY());
      detectClicks.repaint();
   }

}

您的事件被打印坐標的處理程序占用,您需要重新分發該事件,以便按鈕可以看到它。 您可以在座標顯示事件處理常式中執行以下操作:

Component c = e.getComponent();  
c.getParent().dispatchEvent( e ); 

另外,我很想使用框架的玻璃窗格,並用坐標將JLabel放在上面,而不是弄亂繪畫方法。

您不必使用任何repaint(),invalidate()等。我強烈建議您使用

SwingUtilities.invokeLater(new Runnable() {

            public void run() {
             //TODO udpdate UI compontents, layouts etc.
            }
});

這樣可以確保UI組件實時更新。 因為我們不知道系統何時更新UI層次結構,所以我們無法強制執行。 這使系統可以自行確定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM