1

我正在研究水平显示移动横幅的小程序,当此文本横幅到达小程序窗口的右边界时,它应该从左边界的开始反转,我编写以下类来完成工作,问题是当文本横幅到达右侧横幅时它崩溃,小程序进入无限循环:

    import java.applet.*;
    import java.awt.*;
    import java.net.*;
    import java.io.*;
    import javax.swing.*;

    /*
    <applet code="banner" width=300 height=50>
    </applet>
    */
    public class TextBanner extends Applet implements Runnable 
    {
        String msg = "Islam Hamdy", temp="";
        Thread t = null;
        int state;
        boolean stopFlag;
        int x;
        String[] revMsg;
        int msgWidth;
        boolean isReached;

         public void init() 
        {

            setBackground(Color.BLACK);
            setForeground(Color.YELLOW);
        }

        // Start thread

        public void start() 
        {

            t = new Thread(this);
            stopFlag = false;
            t.start();
        }

        // Entry point for the thread that runs the banner.

        public void run() 
        {

            // Display banner
            while(true) 
            {
                try 
                {
                    repaint();
                    Thread.sleep(550);
                    if(stopFlag)
                        break;
                } catch(InterruptedException e) {}
            }
        }

        // Pause the banner.

        public void stop() 
        {
            stopFlag = true;
            t = null;
        }

        // Display the banner.

        public void paint(Graphics g) 
        {
        String temp2="";
        System.out.println("Temp-->"+temp);
        int result=x+msgWidth; 
        FontMetrics fm = g.getFontMetrics();
        msgWidth=fm.stringWidth(msg);
        g.setFont(new Font("ALGERIAN", Font.PLAIN, 30));        
        g.drawString(msg, x, 40);
        x+=10;
        if(x>bounds().width){
        x=0;
    }
        if(result+130>bounds().width){
         x=0;
        while((x<=bounds().width)){
        for(int i=msg.length()-1;i>0;i--){
        temp2=Character.toString(msg.charAt(i));
        temp=temp2+temp;
                    // it crashes here
        System.out.println("Before draw");
            g.drawString(temp, x, 40);
        System.out.println("After draw");
        repaint();
               }
            x++;
            }       // end while
         }          //end if

      }

     }
4

2 回答 2

1

让我们从...

  • 使用 Swing over AWT 组件(JApplet而不是Applet
  • 不要覆盖paint顶级容器的方法。有很多原因,主要影响你的是顶级容器没有双缓冲。
  • 永远不要从事件调度线程以外的任何线程更新 UI,事实上,对于你想要做的事情,aThread简直是过度杀戮。
  • 不要使用该paint方法更新动画状态。您已尝试在该paint方法中执行所有动画,但这不是paint工作方式。将paint其视为电影中的一帧,由线程决定(在您的情况下)到哪一帧,实际上,它应该准备应该画什么。
  • 您无法控制油漆系统。 repaint是对绘画子系统执行更新的“请求”。重绘管理器将决定何时进行实际重绘。这使得执行更新有点棘手......

更新了示例

在此处输入图像描述在此处输入图像描述

public class Reverse extends JApplet {

    // Set colors and initialize thread.
    public void init() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                setBackground(Color.BLACK);
                setForeground(Color.YELLOW);
                setLayout(new BorderLayout());
                add(new TextPane());
            }
        });
    }

    // Start thread
    public void start() {
    }

    // Pause the banner.
    public void stop() {
    }

    public class TextPane extends JPanel {

        int state;
        boolean stopFlag;
        char ch;
        int xPos;
        String masterMsg = "Islam Hamdy", temp = "";
        String msg = masterMsg;
        String revMsg;
        int msgWidth;

        private int direction = 10;

        public TextPane() {
            setOpaque(false);
            setBackground(Color.BLACK);
            setForeground(Color.YELLOW);

            setFont(new Font("ALGERIAN", Font.PLAIN, 30));

            // This only needs to be done one...
            StringBuilder sb = new StringBuilder(masterMsg.length());
            for (int index = 0; index < masterMsg.length(); index++) {
                sb.append(masterMsg.charAt((masterMsg.length() - index) - 1));
            }
            revMsg = sb.toString();

            // Main animation engine.  This is responsible for making
            // the decisions on where the animation is up to and how
            // to react to the edge cases...
            Timer timer = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos += direction;
                    FontMetrics fm = getFontMetrics(getFont());
                    if (xPos > getWidth()) { // this condition fires when the text banner reaches the right banner
                        direction *= -1;
                        msg = revMsg;
                    } else if (xPos < -fm.stringWidth(masterMsg)) {
                        direction *= -1;
                        msg = masterMsg;
                    }
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println(xPos);
            FontMetrics fm = g.getFontMetrics();
            msgWidth = fm.stringWidth(msg);
            g.drawString(msg, xPos, 40);
        }
    }
}

更新了其他示例

现在,如果您想变得更加聪明...您可以利用负缩放过程,这将为您反转图形...

更新计时器...

            Timer timer = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    xPos += direction;
                    FontMetrics fm = getFontMetrics(getFont());
                    System.out.println(xPos + "; " + scale);
                    if (scale > 0 && xPos > getWidth()) { // this condition fires when the text banner reaches the right banner
                        xPos = -(getWidth() + fm.stringWidth(msg));
                        scale = -1;
                    } else if (scale < 0 && xPos >= 0) {
                        xPos = -fm.stringWidth(msg);
                        scale = 1;
                    }
                    repaint();
                }
            });

和更新的绘画方法......

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.scale(scale, 1);
            FontMetrics fm = g2d.getFontMetrics();
            msgWidth = fm.stringWidth(msg);
            g2d.drawString(msg, xPos, 40);
            g2d.dispose();
        }

更新为“弹跳”...

这替换了TextPane上一个示例中的

当文本超出右边界时,它会“反转”方向并返回到左侧,直到超出该边界,它会再次“反转”......

public class TextPane    public class TextPane extends JPanel {

    int state;
    boolean stopFlag;
    char ch;
    int xPos;
    String msg = "Islam Hamdy";
    int msgWidth;

    private int direction = 10;

    public TextPane() {
        setBackground(Color.BLACK);
        setForeground(Color.YELLOW);

        setFont(new Font("ALGERIAN", Font.PLAIN, 30));

        Timer timer = new Timer(100, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                xPos += direction;
                FontMetrics fm = getFontMetrics(getFont());
                if (xPos > getWidth()) {
                    direction *= -1;
                } else if (xPos < -fm.stringWidth(msg)) {
                    direction *= -1;
                }
                repaint();
            }
        });
        timer.setRepeats(true);
        timer.setCoalesce(true);
        timer.start();

    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        FontMetrics fm = g2d.getFontMetrics();
        msgWidth = fm.stringWidth(msg);
        g2d.drawString(msg, xPos, 40);
        g2d.dispose();
    }
}
于 2012-12-20T03:46:56.673 回答
1

我现在认为您的意思是“应该跳回到起点”,但这又滑了回去。但顺便说一句,我不会考虑为这类事情使用小程序,原因有两个。

  1. 滚动文本很糟糕。
  2. 如果页面“必须有”滚动文本,最好使用 HTML 和 JS(和 CSS)。

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

/*
 * <applet code="TextBanner" width=600 height=50> </applet>
 */
public class TextBanner extends JApplet {

    private TextBannerPanel banner;

    // Set colors and initialize thread.
    @Override
    public void init() {
        banner = new TextBannerPanel("Islam Hamdy");
        add(banner);
    }

    // Start animation
    @Override
    public void start() {
        banner.start();
    }

    // Stop animation
    @Override
    public void stop() {
        banner.stop();
    }
}

class TextBannerPanel extends JPanel {

    String msg;
    int x;
    int diff = 5;
    Timer timer;
    Font font = new Font("ALGERIAN", Font.PLAIN, 30);

    public TextBannerPanel() {
        new TextBannerPanel("Scrolling Text Banner");
    }

    public TextBannerPanel(String msg) {
        this.msg = msg;
        setBackground(Color.BLACK);
        setForeground(Color.YELLOW);
        ActionListener animate = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                repaint();
            }
        };
        timer = new Timer(100, animate);
    }

    // Display the banner.
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setFont(font);

        FontMetrics fm = g.getFontMetrics();
        int w = (int) fm.getStringBounds(msg, g).getWidth();

        g.drawString(msg, x, 40);

        x += diff;

        diff = x+w > getWidth() ? -5 : diff;
        diff = x < 0 ? 5 : diff;
    }

    public void start() {
        timer.start();
    }

    public void stop() {
        timer.stop();
    }
}

旧答案

..应该..出现反转.."Islam Hamdy"

另见JArabicInUnicode

在此处输入图像描述

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

/**
 * "Peace Be Upon You", "Aslam Alykm' to which the common reply is "Wa alaykum
 * as salaam", "And upon you, peace". Information obtained from the document
 * http://www.unicode.org/charts/PDF/U0600.pdf Copyright &copy; 1991-2003
 * Unicode, Inc. All rights reserved. Arabic is written and read from right to
 * left. This source is adapted from the original 'Peace' source written by
 * mromarkhan ("Peace be unto you").
 *
 * @author Omar Khan
 * @author Andrew Thompson
 * @version 2004-05-31
 */
public class JArabicInUnicode extends JFrame {

    /**
     * Unicode constant used in this example.
     */
    public final static String ALEF = "\u0627",
            LAM = "\u0644",
            SEEN = "\u0633",
            MEEM = "\u0645",
            AIN = "\u0639",
            YEH = "\u064A",
            KAF = "\u0643",
            HEH = "\u0647";
    /**
     * An array of the letters that spell 'Aslam Alykm'.
     */
    String text[] = {
        ALEF, //a 
        LAM + SEEN, //s 
        LAM, //l 
        ALEF, //a 
        MEEM, //m 
        " ",
        AIN, //a 
        LAM, //l 
        YEH, //y 
        KAF, //k 
        MEEM //m 
    };

    /**
     * Displays the letters of the phrase 'Aslam Alykm' as well as the words
     * spelt out letter by letter.
     */
    public JArabicInUnicode() {
        super("Peace be upon you");

        JTextArea textwod = new JTextArea(7, 10);
        textwod.setEditable(false);
        textwod.setFont(new Font("null", Font.PLAIN, 22));

        String EOL = System.getProperty("line.separator");

    // write the phrase to the text area 
    textwod.append(getCharacters() + EOL);

        // now spell it, one letter at a time 
        for (int ii = 0; ii <= text.length; ii++) {
            textwod.append(getCharacters(ii) + EOL);
        }
        textwod.setCaretPosition(0);

        getContentPane().add(
                new JScrollPane(textwod,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
                BorderLayout.CENTER);

        pack();
        setMinimumSize(getPreferredSize());
        try {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setLocationRelativeTo(null);
        } catch (Exception e) {
        }  // allows to run under 1.2 

    }

    /**
     * Get a string of the entire phrase.
     */
    String getCharacters() {
        return getCharacters(text.length);
    }

    /**
     * Get a string of the 1st 'num' characters of the phrase.
     */
    String getCharacters(int num) {
        StringBuffer sb = new StringBuffer();
        for (int ii = 1; ii < num; ii++) {
            sb.append(text[ii]);
        }
        return sb.toString();
    }

    /**
     * Instantiate an ArabicInUnicode frame.
     */
    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                new JArabicInUnicode().setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}
于 2012-12-20T03:56:12.470 回答