为什么这个JFrame中的文本不会闪烁?

时间:2017-02-04 21:15:59

标签: java swing awt

当我遇到这个程序时,我正在研究O' Reilly的学习Java:第4版中的一个例子:

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,所以非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

问题是因为你没有真正重写paintComponent方法 paintComponenet != paintComponent

始终预先删除您认为的所有方法,并覆盖@Override注释,因为这样编译器会在编译时警告你你的假设不正确的时候。

另外的问题是:在你自己的覆盖中调用super.paintComponent(g)方法,以便组件自己做家务绘画,包括消除空像素。

例如,改变这个:

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);
}

我自己,我使用Swing Timer和JLabel来做这件事,而不是穿线和绘画。

或者至少是一个Swing Timer。例如:

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());
    }
}