问题描述
我工作的小程序,水平显示一个移动的横幅,当这个文本标识
到达小程序窗口应该出现在左边界开始逆转的右边界,我写了下面的类做的工作,问题是,当文本标识到达崩溃的右旗,小程序去无限循环:
进口java.applet中的*。
进口java.awt中的*。
进口java.net *。
进口java.io. *;
进口的javax.swing *。 / *
<小程序code =大旗WIDTH = 300 HEIGHT = 50>
< /小程序>
* /
公共类TextBanner扩展的Applet实现Runnable
{
弦乐味精=伊斯兰HamdyTEMP =;
线程t = NULL;
INT状态;
布尔stopFlag;
INT X;
的String [] revMsg;
INT msgWidth;
布尔isReached; 公共无效的init()
{ 的setBackground(Color.BLACK);
setForeground(Color.YELLOW);
} //开始线程 公共无效的start()
{ T =新的Thread(本);
stopFlag = FALSE;
t.start();
} //入口点为运行旗帜线程。 公共无效的run()
{ //显示旗帜
而(真)
{
尝试
{
重绘();
视频下载(550);
如果(stopFlag)
打破;
}赶上(InterruptedException的E){}
}
} //暂停旗帜。 公共无效停止()
{
stopFlag = TRUE;
T = NULL;
} //显示的旗帜。 公共无效漆(图形G)
{
串TEMP2 =;
的System.out.println(温度 - >中+温度);
INT结果= X + msgWidth;
FontMetrics对象FM = g.getFontMetrics();
msgWidth = fm.stringWidth(MSG);
g.setFont(新字体(阿尔及利亚,Font.PLAIN,30));
g.drawString(MSG中,x,40);
X + = 10;
如果(X>界限()宽。){
X = 0;
}
如果(结果+ 130方式>界()宽){
X = 0;
而((X< =界限()宽)){
的for(int i = msg.length() - 1; I> 0; I - ){
TEMP2 = Character.toString(msg.charAt(I));
TEMP = TEMP2 +温度;
//崩溃这里
的System.out.println(抽签之前);
g.drawString(温度中,x,40);
的System.out.println(经过抽奖);
重绘();
}
X ++;
} //结束时
} //万一 } }
让我们先从...
- 在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< -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< -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 bannerreaches 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 ofApplet
) - 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 thepaint
method, this is not howpaint
works. Think ofpaint
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();
}
}
这篇关于文字横幅小程序扭转这一文本里显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!