且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

文字横幅小程序扭转这一文本里显示

更新时间:2022-10-17 12:16:07

让我们先从...


  • 在AWT组件使用Swing( JApplet的而不是 Applet的

  • 请不要覆盖油漆顶层容器的方法。有很多的原因,是要影响你的主要一个是顶层容器不是双缓冲。

  • 不得,于是乎,更新其他任何线程的UI事件指派线程,其实对于你正在尝试做的,一个简直是超必杀

  • 请不要更新与油漆方法动画状态。你试过在油漆方法中执行你的动画,这是油漆没怎么的作品。想想油漆作为电影的框架,它是由(你的情况)线程,以确定哪些框架阿凡达,而事实上,它应该是preparing应该画什么。

  • 您不控制涂料体系。 重绘是一个请求油漆子系统执行更新。重绘经理将​​决定何时将发生实际的重绘。这使得执行更新有点棘手...

更新与实例

文字横幅小程序扭转这一文本里显示文字横幅小程序扭转这一文本里显示

 公共类反向扩展JApplet的{    //设置颜色并初始化线程。
    公共无效的init(){
        EventQueue.invokeLater(新的Runnable(){
            @覆盖
            公共无效的run(){
                尝试{
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                }赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
                }
                的setBackground(Color.BLACK);
                setForeground(Color.YELLOW);
                的setLayout(新的BorderLayout());
                添加(新TextPane());
            }
        });
    }    //开始线程
    公共无效的start(){
    }    //暂停旗帜。
    公共无效停止(){
    }    公共类TextPane继承JPanel {        INT状态;
        布尔stopFlag;
        焦炭CH;
        诠释XPOS;
        字符串masterMsg =伊斯兰HamdyTEMP =;
        弦乐味精= masterMsg;
        串revMsg;
        INT msgWidth;        私人INT方向= 10;        公共TextPane(){
            setOpaque(假);
            的setBackground(Color.BLACK);
            setForeground(Color.YELLOW);            并入setfont(新字体(阿尔及利亚,Font.PLAIN,30));            //这个只需要做了一个...
            StringBuilder的SB =新的StringBuilder(masterMsg.length());
            对于(INT指数= 0;指数 - LT; masterMsg.length();指数++){
                sb.append(masterMsg.charAt((masterMsg.length() - 指数) - 1));
            }
            revMsg = sb.toString();            //主动画引擎。这是负责使
            //在哪里动画达到怎样的决定
            //向边缘的情况下发生反应...
            定时器定时器=新定时器(100,新的ActionListener(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的五){
                    XPOS + =方向;
                    FontMetrics对象FM = getFontMetrics(的getFont());
                    如果(XPOS>的getWidth()){//当文本旗帜到达右旗这个条件火灾
                        方向* = -1;
                        味精= revMsg;
                    }否则如果(XPOS&L​​T; -fm.stringWidth(masterMsg)){
                        方向* = -1;
                        味精= masterMsg;
                    }
                    重绘();
                }
            });
            timer.setRepeats(真);
            timer.setCoalesce(真);
            timer.start();        }        @覆盖
        保护无效paintComponent(图形G){
            super.paintComponent方法(G);
            的System.out.println(XPOS);
            FontMetrics对象FM = g.getFontMetrics();
            msgWidth = fm.stringWidth(MSG);
            g.drawString(味精,XPOS,40);
        }
    }
}

更新,添加例如

现在,如果你想成为一点点额外的聪明......你可以采取消极的缩放过程的优势,这将扭转图形你...

更新的计时器...

 定时器定时器=新定时器(100,新的ActionListener(){
                @覆盖
                公共无效的actionPerformed(ActionEvent的五){
                    XPOS + =方向;
                    FontMetrics对象FM = getFontMetrics(的getFont());
                    的System.out.println(XPOS +,+规模);
                    如果(规模大于0和放大器;&安培; XPOS>的getWidth()){//当文本旗帜到达右旗这个条件火灾
                        XPOS = - (的getWidth()+ fm.stringWidth(MSG));
                        比例= -1;
                    }否则如果(规模℃,和放大器;&安培; XPOS> = 0){
                        XPOS = -fm.stringWidth(MSG);
                        比例尺= 1;
                    }
                    重绘();
                }
            });

和更新的paint方法...

 保护无效paintComponent(图形G){
            super.paintComponent方法(G);
            Graphics2D的G2D =(Graphics2D的)g.create();
            g2d.scale(规模,1);
            FontMetrics对象FM = g2d.getFontMetrics();
            msgWidth = fm.stringWidth(MSG);
            g2d.drawString(味精,XPOS,40);
            g2d.dispose();
        }

更新了反弹......

这取代了 TextPane 从previous例如

由于超出右边界的文本移动时,它会反向的方向和向后移动到左侧,直到它越过该边界,在那里将反向再次...

TextPane公共类TextPane继承JPanel {
 公共类    INT状态;
    布尔stopFlag;
    焦炭CH;
    诠释XPOS;
    弦乐味精=伊斯兰Hamdy
    INT msgWidth;    私人INT方向= 10;    公共TextPane(){
        的setBackground(Color.BLACK);
        setForeground(Color.YELLOW);        并入setfont(新字体(阿尔及利亚,Font.PLAIN,30));        定时器定时器=新定时器(100,新的ActionListener(){
            @覆盖
            公共无效的actionPerformed(ActionEvent的五){
                XPOS + =方向;
                FontMetrics对象FM = getFontMetrics(的getFont());
                如果(XPOS>的getWidth()){
                    方向* = -1;
                }否则如果(XPOS&L​​T; -fm.stringWidth(MSG)){
                    方向* = -1;
                }
                重绘();
            }
        });
        timer.setRepeats(真);
        timer.setCoalesce(真);
        timer.start();    }    @覆盖
    保护无效paintComponent(图形G){
        super.paintComponent方法(G);
        Graphics2D的G2D =(Graphics2D的)g.create();
        FontMetrics对象FM = g2d.getFontMetrics();
        msgWidth = fm.stringWidth(MSG);
        g2d.drawString(味精,XPOS,40);
        g2d.dispose();
    }
}

i'm working on applet that displays a moving banner horizontally and when this text banner reaches the right boundary of the applet window it should be appear reversed from the start of the left boundary, i write the following class to do the work, the problem is that when the text banner reaches the right banner it crashes, the applet goes to infinite loop:

    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

      }

     }

Let's start with...

  • Use Swing over AWT components (JApplet instead of Applet)
  • Don't override the paint methods of top level containers. There are lots of reasons, the major one that is going to effect you is top level containers are not double buffered.
  • DO NOT, EVER, update the UI from any thread other the Event Dispatching Thread, in fact, for what you are trying to do, a Thread is simply over kill.
  • DO NOT update animation states with the paint method. You've tried to perform ALL you animation within the paint method, this is not how paint works. Think of paint as a frame in film, it is up to (in your case) the thread to determine what frame where up to, and in fact, it should be preparing what should painted.
  • You do not control the paint system. repaint is a "request" to the paint sub system to perform an update. The repaint manager will decide when the actual repaint will occur. This makes performing updates a little tricky...

Updated with Example

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

Updated with additional example

Now, if you want to be a little extra clever...you could take advantage of a negative scaling process, which will reverse the graphics for you...

Updated timer...

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

And the updated paint method...

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

Updated with "bouncing"...

This replaces the TextPane from the previous example

As the text moves beyond the right boundary, it will "reverse" direction and move back to the left, until it passes beyond that boundary, where it will "reverse" again...

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