从滚动文本中删除华丽/不安 [英] Removing flashiness/ shakiness from scrolling text

查看:116
本文介绍了从滚动文本中删除华丽/不安的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于制作了一台能够满足我想要的功能的代码,但现在唯一的问题是它看起来有点不稳定,看起来像是在旧电视上显示的。

以下是我的代码:

  import java.awt.Color; 
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Scroll1 extends JPanel {
private int x;
private int x2;
private int y;
private int width;
私人字符串文本;
private Font f =(new Font(SansSerif,Font.PLAIN,24));
public Sc​​roll1(int startX)
{
x = Integer.MIN_VALUE;
x2 = Integer.MIN_VALUE;
y = 150;
text =我们很高兴地宣布,Actavis已经完成了对Auden Mckenzie的收购,Auden Mckenzie是一家充满活力和快速发展的公司,专注于在英国开发,授权和销售仿制药和专有品牌。
}
@Override
public void paintComponent(Graphics g)
{
g.setFont(f);
if(x == Integer.MIN_VALUE){
width = g.getFontMetrics()。stringWidth(text);
x = 0;

$ b $ if(x2 == Integer.MIN_VALUE){
x2 = g.getFontMetrics()。stringWidth(text);
}
g.setColor(Color.white);

g.fillRect(this.getX(),this.getY(),(int)this.getBounds()。getWidth(),(int)this.getBounds()。getHeight()) ;
g.setColor(Color.black);
g.drawString(text,x,y);
g.drawString(text,x2,y);

$ b $ public void start()throws InterruptedException {
while(true){
while(x> =(-width)&& x2!= Integer.MIN_VALUE){
x--;
x2--;
y = getHeight()/ 2;
Thread.sleep(15);
这个。
validate();
repaint();
if(x2 <= - width)
{
x2 = width;



if(x <-width&& x!= Integer.MIN_VALUE)
{
x = width;


$ b public static void main(String [] args){
JFrame frame = new JFrame(Scrolling Panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Scroll1 scrolling = new Scroll1(-100);

frame.getContentPane()。add(scrolling);
frame.setSize(400,300);
frame.setVisible(true);
尝试{
scrolling.start();
} catch(InterruptedException e){
// TODO自动生成的catch块
e.printStackTrace();




解决方案


  1. 在执行自定义绘画之前调用 super.paintComponent
  2. 首选Swing <$ c $在EDT和你内部触发 Thread ,如Swing Timers 的c> Timer paintComponent 方法和 Thread

  3. paintComponent 实际上不应该对渲染状态做出决定,而应该只绘制当前状态。
  4. t)需要 g.fillRect(this.getX(),this.getY(),(int)this.getBounds()。getWidth(),(int)this.getBounds()。getHeight()) ; ,只需设置面板的背景颜色,并允许绘画例程完成他们的工作。绘画是从 0x0 完成的,是组件的顶部/左角

  5. 您的 while 循环在你的 start 方法中,它似乎不允许它运行(至少在我的测试中)




你能帮我试试把它转移到摇摆计时器还是给我一个很好的资源去做?

你能付我吗? ;)

首先,让它完全错开免费是不可能的,因为这个过程依赖于系统保持最新的能力与您的请求。例如,你真的不需要以> 60fps运行,严重的是,25fps甚至15fps会更适合你正在尝试做的事情。您可以使用移动增量控制滚动的速度,而不是使用

以下示例使用Swing Timer ,as做了我之前的例子,但是这个例子还会创建一个连续循环,如果显示的文本数量少于可见区域的宽度,它会添加一个新消息来追踪它。



这个例子能够显示不同长度的多种不同信息,但我猜这是一个奖金

  import java.awt.Color; 
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Scroll1 extends JPanel {

private String text;
private Font f =(new Font(SansSerif,Font.PLAIN,24));

私人列表< TickerTap> tickerTaps;

公共Scroll1(int startX){
text =我们很高兴地宣布,Actavis已经完成了对Auden Mckenzie的收购,Auden Mckenzie是一家充满活力并且快速增长的公司,专注于开发,在英国推广仿制药和自主品牌。;
setFont(f);
setBackground(Color.WHITE);
tickerTaps = new ArrayList<>(4);

Timer timer = new Timer(40,new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
FontMetrics fm = getFontMetrics(getFont ));
if(tickerTaps.isEmpty()){
tickerTaps.add(new TickerTap(text,getWidth()));
}

TickerTap tap [] = tickerTaps.toArray(new TickerTap [tickerTaps.size()]);
int visibleWidth = 0;
for(TickerTap tap:taps){
tap.move(); $ (tap.getxPos()<= -messageWidth){
tickerTaps.remove(tap);
() } else {
visibleWidth + = tap.getxPos()+ messageWidth;
}
}

while(visibleWid th < getWidth()){
TickerTap last = tickerTaps.get(tickerTaps.size() - 1);
int xPos = last.getxPos()+ fm.stringWidth(last.getMessage());
String message =*+ text;
TickerTap next = new TickerTap(message,xPos);
visibleWidth + = next.getxPos()+ fm.stringWidth(next.getMessage());
tickerTaps.add(next);
}

repaint();
}
});
timer.start();
}

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d =(Graphics2D)g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_PURE);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); (TickerTap tap:tickerTaps){
FontMetrics fm = g2d.getFontMetrics();


int y =((getHeight() - fm.getHeight())/ 2)+ fm.getAscent();
g2d.setColor(Color.black);
g2d.drawString(tap.getMessage(),tap.getxPos(),y);
}
}

public class TickerTap {

private String message;
private int xPos;

public TickerTap(String message,int xPos){
this.message = message;
this.xPos = xPos;
}

public String getMessage(){
return message;
}

public int getxPos(){
return xPos;
}

public void move(){
xPos - = 2;



public static void main(String [] args){
EventQueue.invokeLater(new Runnable(){
@Override
公共无效的run(){
尝试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}赶上(ClassNotFoundException的| InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException前){
ex.printStackTrace();
}

的JFrame帧=新的JFrame( 滚动面板);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Scroll1滚动= new Scroll1(-100);

frame.getContentPane()。add(scrolling);
frame.setSize(400,300);
frame.setVisible(true) ;
}
});


查看如何使用Swing计时器了解更多详情。 定时实际上是真正理解的,如果你简单地把它看成是一种循环

I have finally made a ticker that functions how I want it to, but the only problem now is that it seems kind of shaky and looks like it is being displayed on an old tv. How do I make it look smoother?

Here is my code:

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Scroll1 extends JPanel{
    private int x;
    private int x2;
    private int y;
    private int width;
    private String text;
    private Font f=(new Font("SansSerif", Font.PLAIN,24));
    public Scroll1(int startX)
    {
        x=Integer.MIN_VALUE;
        x2=Integer.MIN_VALUE;
        y=150;
        text= "We are pleased to announce that Actavis has completed the acquisition of Auden Mckenzie, a dynamic and fast growing company focused on the development, licensing and marketing of generic medicines and proprietary brands in the UK.  ";
    }
    @Override
    public void paintComponent(Graphics g)
    {
            g.setFont(f);
          if ( x == Integer.MIN_VALUE ){
              width=g.getFontMetrics().stringWidth(text);
                x = 0;

            }
          if ( x2 == Integer.MIN_VALUE ){
                x2 = g.getFontMetrics().stringWidth(text);
            }
        g.setColor(Color.white);

        g.fillRect(this.getX(), this.getY(), (int)this.getBounds().getWidth(), (int)this.getBounds().getHeight());
        g.setColor(Color.black);
        g.drawString(text, x, y);
        g.drawString(text, x2, y);
    }

    public void start() throws InterruptedException{
        while(true){
            while(x>= (-width)&&x2!=Integer.MIN_VALUE){
                x--;
                x2--;
                y = getHeight()/2;
                Thread.sleep(15);
                this.
                validate();
                repaint();
                if(x2<=-width)
                {
                    x2=width;
                }
            }

            if(x<-width&&x!=Integer.MIN_VALUE)
            {
                x=width;    
            }
        }
    }
    public static void main(String[] args) {
        JFrame frame = new JFrame("Scrolling Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Scroll1 scrolling = new Scroll1(-100);

        frame.getContentPane().add(scrolling);
        frame.setSize(400, 300);
        frame.setVisible(true);
        try {
            scrolling.start();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

解决方案

  1. Call super.paintComponent before you perform custom painting
  2. Prefer Swing Timer of a Thread, as Swing Timers are triggered within the EDT and you run less risk of having dirty reads between the paintComponent method and the Thread
  3. paintComponent really shouldn't be making decisions about the rendering state, instead it should just paint the current state.
  4. You don't need g.fillRect(this.getX(), this.getY(), (int) this.getBounds().getWidth(), (int) this.getBounds().getHeight());, just set the background color of the panel and allow the painting routines to do their jobs. Painting is done from 0x0, been the top/left corner of the component
  5. There is an issue with your while loop in your start method which doesn't seem to allow it to run (at least in my testing)

Can you help me try to transfer it over to a swing timer or give me a good source to do so?

Can you pay me? ;)

First, getting it to be completely "stagger" free isn't going to be possible, as the process is reliant on the system's capability of keeping up to date with your requests. For example, you really don't need to it be running at > 60fps, seriously, 25fps or even 15fps would be more the suitable for what you are trying to do. You control the speed of the scroll by using the movement delta instead

The following example uses a Swing Timer, as did my previous example, but this example will also create a "continuous" loop, where if the amount of text been displayed is less then the width of the visible area, it will add a "new" message to trail it.

This example would be capable of display multiple different messages of varying lengths but I guess, that's a bonus

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Scroll1 extends JPanel {

    private String text;
    private Font f = (new Font("SansSerif", Font.PLAIN, 24));

    private List<TickerTap> tickerTaps;

    public Scroll1(int startX) {
        text = "We are pleased to announce that Actavis has completed the acquisition of Auden Mckenzie, a dynamic and fast growing company focused on the development, licensing and marketing of generic medicines and proprietary brands in the UK.";
        setFont(f);
        setBackground(Color.WHITE);
        tickerTaps = new ArrayList<>(4);

        Timer timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FontMetrics fm = getFontMetrics(getFont());
                if (tickerTaps.isEmpty()) {
                    tickerTaps.add(new TickerTap(text, getWidth()));
                }

                TickerTap taps[] = tickerTaps.toArray(new TickerTap[tickerTaps.size()]);
                int visibleWidth = 0;
                for (TickerTap tap : taps) {
                    tap.move();
                    int messageWidth = fm.stringWidth(tap.getMessage());
                    if (tap.getxPos() <= -messageWidth) {
                        tickerTaps.remove(tap);
                    } else {
                        visibleWidth += tap.getxPos() + messageWidth;
                    }
                }

                while (visibleWidth < getWidth()) {
                    TickerTap last = tickerTaps.get(tickerTaps.size() - 1);
                    int xPos = last.getxPos() + fm.stringWidth(last.getMessage());
                    String message = " * " + text;
                    TickerTap next = new TickerTap(message, xPos);
                    visibleWidth += next.getxPos() + fm.stringWidth(next.getMessage());
                    tickerTaps.add(next);
                }

                repaint();
            }
        });
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        for (TickerTap tap : tickerTaps) {
            FontMetrics fm = g2d.getFontMetrics();
            int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
            g2d.setColor(Color.black);
            g2d.drawString(tap.getMessage(), tap.getxPos(), y);
        }
    }

    public class TickerTap {

        private String message;
        private int xPos;

        public TickerTap(String message, int xPos) {
            this.message = message;
            this.xPos = xPos;
        }

        public String getMessage() {
            return message;
        }

        public int getxPos() {
            return xPos;
        }

        public void move() {
            xPos -= 2;
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Scrolling Panel");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                Scroll1 scrolling = new Scroll1(-100);

                frame.getContentPane().add(scrolling);
                frame.setSize(400, 300);
                frame.setVisible(true);
            }
        });
    }
}

Take a look at How to use Swing Timers for more details. Timer is actually really to understand if you simply think of it like a kind of loop

这篇关于从滚动文本中删除华丽/不安的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆