繁体   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