Java:在Swing中重新绘制不工作
我正在学习JavaSwing,在下面的程序中遇到了问题。它创建了一个小框架,顶部有一个退出按钮。目标是在单击鼠标的任何位置显示坐标。当我单击鼠标时,发生了两件不需要的事情:Java:在Swing中重新绘制不工作,java,swing,repaint,Java,Swing,Repaint,我正在学习JavaSwing,在下面的程序中遇到了问题。它创建了一个小框架,顶部有一个退出按钮。目标是在单击鼠标的任何位置显示坐标。当我单击鼠标时,发生了两件不需要的事情: “退出”按钮被鼠标单击覆盖,不再响应(它不会响应事件和退出,而是在“退出”按钮顶部显示坐标) 当我在新位置单击时,旧位置的坐标将保持不变 我使用了removeAll()和revalidate(),然后根据进行了repaint(),但这没有帮助。此代码取自,代码表示要研究在线文档以了解发生这种情况的原因 有什么建议吗 impo
removeAll()
和revalidate()
,然后根据进行了repaint()
,但这没有帮助。此代码取自,代码表示要研究在线文档以了解发生这种情况的原因
有什么建议吗
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();
}
}
repaint()
工作正常受保护的void paintComponent(图形g)
方法覆盖中绘制paintComponent(g)
方法——这将擦除旧图像,这是您出现问题的原因之一removeAll()
就可以做到这一点——删除包括按钮在内的所有组件。你为什么叫这个?是否确实要调用此方法例如,像
@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();
}
}
repaint()
工作正常受保护的void paintComponent(图形g)
方法覆盖中绘制paintComponent(g)
方法——这将擦除旧图像,这是您出现问题的原因之一removeAll()
就可以做到这一点——删除包括按钮在内的所有组件。你为什么叫这个?是否确实要调用此方法例如,像
@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,而不是混乱的绘画方法 打印坐标的处理程序正在使用事件,您需要重新修补事件,以便按钮可以看到它。您可以在坐标显示事件处理程序中这样做:
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层次结构,所以无法强制更新。这允许系统自行决定。您不必使用任何repaint()、invalidate()等。 我强烈建议使用
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//TODO udpdate UI compontents, layouts etc.
}
});
这保证了UI组件的实时更新。因为我们不知道系统何时更新UI层次结构,所以无法强制更新。这允许系统自行决定。谢谢!我更新了代码以显示添加的quitButton。对不起,新的秋千。我假设您的意思是为(a)按钮和(b)坐标区域创建JPanel,并在其中使用绘画。我尝试创建JPanel以避免坐标重叠在quit按钮上。它会更改外观和窗口大小。我必须提供一个201x201窗口,其退出按钮跨越顶部窗口的宽度。我将致力于确定JPanel的大小。我使用removeAll删除基于链接讨论的旧坐标。看来super能解决这个问题。谢谢!我更新了代码以显示添加的quitButton。对不起,新的秋千。我假设您的意思是为(a)按钮和(b)坐标区域创建JPanel,并在其中使用绘画。我尝试创建JPanel以避免坐标重叠在quit按钮上。它会更改外观和窗口大小。我必须提供一个201x201窗口,其退出按钮跨越顶部窗口的宽度。我将致力于确定JPanel的大小。我使用removeAll删除基于链接讨论的旧坐标。看来super会解决这个问题。