文本横幅小程序反转显示文本

时间:2012-12-20 03:33:00

标签: java multithreading applet

我正在处理水平显示移动横幅的applet以及此文本横幅 到达applet窗口的右边界它应该从左边界的开头反转出来,我写下面的类来做工作,问题是当文本横幅到达正确的横幅它崩溃时,applet转到无限循环:

    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

      }

     }

2 个答案:

答案 0 :(得分:1)

让我们从...开始......

  • 使用Swing over AWT组件(JApplet代替Applet
  • 不要覆盖顶级容器的paint方法。有很多原因,影响你的主要原因是顶级容器不是双缓冲的。
  • 事实上,不要从事件调度线程以外的任何线程更新UI,事实上,对于你想要做的事情,Thread只是过度杀戮。
  • 请勿使用paint方法更新动画状态。您已尝试在paint方法中执行所有动画,这不是paint的工作方式。将paint视为电影中的一个框架,由(在您的情况下)线程来确定哪个框架在哪里,事实上,它应该准备应该绘制的内容。
  • 您无法控制涂料系统。 repaint是对paint子系统执行更新的“请求”。重绘经理将决定何时进行实际重绘。这使得执行更新有点棘手......

更新了示例

enter image description here enter image description here

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

答案 1 :(得分:1)

我现在认为你的意思是'应该跳回到开始',但这会滑回来。但是,除此之外,出于两个原因,我不会考虑这类小程序。

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

  3. 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

    enter image description here

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