Java 为什么JFrame中的文本不闪烁?

Java 为什么JFrame中的文本不闪烁?,java,swing,awt,Java,Swing,Awt,我在O'Reilly学习Java:4th Edition的过程中遇到了一个例子: import java.awt.*; import java.awt.event.*; import javax.swing.*; public class HelloJava4 { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code applic

我在O'Reilly学习Java:4th Edition的过程中遇到了一个例子:

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

public class HelloJava4 {

/**
 * @param args the command line arguments
 */

public static void main(String[] args) {
    // TODO code application logic here
    JFrame frame = new JFrame("HelloJava4");
    frame.add(new HelloComponent4("Hello, Java!"));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 300);
    frame.setVisible(true);
}
}

class HelloComponent4 extends JComponent implements MouseMotionListener, ActionListener, Runnable {
String theMessage;
int messageX = 125, messageY = 95;

JButton theButton;

int colorIndex; //Current index into someColors
static Color[] someColors = {Color.black, Color.red, Color.green, Color.blue, Color.magenta};

boolean blinkState;

public HelloComponent4(String message){
    theMessage = message;
    theButton = new JButton("Change Color");
    setLayout(new FlowLayout());
    add(theButton);
    theButton.addActionListener(this);
    addMouseMotionListener(this);
    Thread t = new Thread(this);
    t.start();
}

public void paintComponenet(Graphics g){
    g.setColor(blinkState ? getBackground() : currentColor());
    g.drawString(theMessage, messageX, messageY);
}

@Override
public void mouseDragged(MouseEvent e){
    messageX = e.getX();
    messageY = e.getY();
    repaint();
}

@Override
public void mouseMoved(MouseEvent e){}

@Override
public void actionPerformed(ActionEvent e){
    if(e.getSource() == theButton)
        changeColor();
}

synchronized private void changeColor(){
    if(++colorIndex == someColors.length)
        colorIndex = 0;
    setForeground(currentColor());
    repaint();
}

synchronized private Color currentColor(){
    return someColors[colorIndex];
}

@Override
public void run(){
    try{
        while(true){
            blinkState = !blinkState; //Toggle blinkState
            repaint(); //show the change
            Thread.sleep(300);
        }
    } catch(InterruptedException ie){}
}
}
程序应该使文本“Hello,Java!”在方框中闪烁。由于某种原因,文本甚至没有出现。显示“更改颜色”的JButton在那里,但它不起作用(或者我无法看到它起作用,因为JFrame/HelloComponent4中没有文本)


我不熟悉Swing或AWT,因此非常感谢您的帮助。

问题在于您没有真正覆盖paintComponent方法,因为
paintComponenet!=油漆组件

始终使用
@Override
注释预先挂起您认为要覆盖的所有方法,因为这样,当您的假设不正确时,编译器将在编译时警告您

另一个次要问题是:在您自己的覆盖中调用
super.paintComponent(g)
方法,以便组件自己进行内部绘制,包括清除空像素

e、 例如,改变这一点:

public void paintComponenet(Graphics g) {
    g.setColor(blinkState ? getBackground() : currentColor());
    g.drawString(theMessage, messageX, messageY);
}
为此:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(blinkState ? getBackground() : currentColor());
    g.drawString(theMessage, messageX, messageY);
}
我自己,我会使用一个摆动计时器和一个JLabel来做这件事,而不是线程和绘画

或者至少是一个摆动计时器。例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class HelloJava4b extends JPanel {
    // don't have component class implement listener interfaces
    private static final int PREF_W = 400;
    private static final int PREF_H = PREF_W;
    public static final Color[] COLORS = { Color.black, Color.red, Color.green, Color.blue,
            Color.magenta };
    private static final int TIMER_DELAY = 300;
    private static final Font TEXT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 40);
    private int colorsIndex = 0;
    private boolean blinkState = false;
    private String text;
    private int messageX = 125;
    private int messageY = 95;

    public HelloJava4b(String text) {
        this.text = text;
        add(new JButton(new ButtonAction("Change Color")));

        // create Swing Timer and start
        new Timer(TIMER_DELAY, new TimerListener()).start();

        // create mouse listener and add
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    // size component per its preferred size
    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Color c = blinkState ? getBackground() : COLORS[colorsIndex];
        g.setColor(c);

        // make rendering smoother
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setFont(TEXT_FONT);  // and bigger
        g.drawString(text, messageX, messageY);
    }

    // button's Action
    private class ButtonAction extends AbstractAction {
        public ButtonAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic); // alt-char hot key
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            colorsIndex++;
            colorsIndex %= COLORS.length;
        }
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            blinkState = !blinkState;
            repaint();
        }
    }

    // my combination mouse listener and motion listener
    private class MyMouse extends MouseAdapter {
        private boolean moving = false;

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                return;
            }
            moving = true;
            messageX = e.getX();
            messageY = e.getY();
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // if not moving, then right button not pressed
            if (moving) {
                messageX = e.getX();
                messageY = e.getY();
                repaint();
                moving = false;
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (moving) {
                messageX = e.getX();
                messageY = e.getY();
                repaint();
            }
        }
    }

    private static void createAndShowGui() {
        HelloJava4b mainPanel = new HelloJava4b("Hello All!");

        JFrame frame = new JFrame("Hello Java");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

问题是您没有真正覆盖paintComponent方法,因为
paintComponenet!=油漆组件

始终使用
@Override
注释预先挂起您认为要覆盖的所有方法,因为这样,当您的假设不正确时,编译器将在编译时警告您

另一个次要问题是:在您自己的覆盖中调用
super.paintComponent(g)
方法,以便组件自己进行内部绘制,包括清除空像素

e、 例如,改变这一点:

public void paintComponenet(Graphics g) {
    g.setColor(blinkState ? getBackground() : currentColor());
    g.drawString(theMessage, messageX, messageY);
}
为此:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(blinkState ? getBackground() : currentColor());
    g.drawString(theMessage, messageX, messageY);
}
我自己,我会使用一个摆动计时器和一个JLabel来做这件事,而不是线程和绘画

或者至少是一个摆动计时器。例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class HelloJava4b extends JPanel {
    // don't have component class implement listener interfaces
    private static final int PREF_W = 400;
    private static final int PREF_H = PREF_W;
    public static final Color[] COLORS = { Color.black, Color.red, Color.green, Color.blue,
            Color.magenta };
    private static final int TIMER_DELAY = 300;
    private static final Font TEXT_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 40);
    private int colorsIndex = 0;
    private boolean blinkState = false;
    private String text;
    private int messageX = 125;
    private int messageY = 95;

    public HelloJava4b(String text) {
        this.text = text;
        add(new JButton(new ButtonAction("Change Color")));

        // create Swing Timer and start
        new Timer(TIMER_DELAY, new TimerListener()).start();

        // create mouse listener and add
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
    }

    // size component per its preferred size
    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Color c = blinkState ? getBackground() : COLORS[colorsIndex];
        g.setColor(c);

        // make rendering smoother
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2.setFont(TEXT_FONT);  // and bigger
        g.drawString(text, messageX, messageY);
    }

    // button's Action
    private class ButtonAction extends AbstractAction {
        public ButtonAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic); // alt-char hot key
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            colorsIndex++;
            colorsIndex %= COLORS.length;
        }
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            blinkState = !blinkState;
            repaint();
        }
    }

    // my combination mouse listener and motion listener
    private class MyMouse extends MouseAdapter {
        private boolean moving = false;

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                return;
            }
            moving = true;
            messageX = e.getX();
            messageY = e.getY();
            repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            // if not moving, then right button not pressed
            if (moving) {
                messageX = e.getX();
                messageY = e.getY();
                repaint();
                moving = false;
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (moving) {
                messageX = e.getX();
                messageY = e.getY();
                repaint();
            }
        }
    }

    private static void createAndShowGui() {
        HelloJava4b mainPanel = new HelloJava4b("Hello All!");

        JFrame frame = new JFrame("Hello Java");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

非常感谢你。这是非常重要的helpful@NiteshKartha:不客气。请注意答案。非常感谢。这是非常重要的helpful@NiteshKartha:不客气。注意要回答的问题。