Java 为什么JFrame中的文本不闪烁?
我在O'Reilly学习Java:4th Edition的过程中遇到了一个例子: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
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:不客气。注意要回答的问题。