Marquee Effect in Java Swing

Marquee effect in Java Swing

Here's an example using javax.swing.Timer.

Marquee.png

import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

/** @see http://stackoverflow.com/questions/3617326 */
public class MarqueeTest {

private void display() {
JFrame f = new JFrame("MarqueeTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String s = "Tomorrow, and tomorrow, and tomorrow, "
+ "creeps in this petty pace from day to day, "
+ "to the last syllable of recorded time; ... "
+ "It is a tale told by an idiot, full of "
+ "sound and fury signifying nothing.";
MarqueePanel mp = new MarqueePanel(s, 32);
f.add(mp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
mp.start();
}

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
new MarqueeTest().display();
}
});
}
}

/** Side-scroll n characters of s. */
class MarqueePanel extends JPanel implements ActionListener {

private static final int RATE = 12;
private final Timer timer = new Timer(1000 / RATE, this);
private final JLabel label = new JLabel();
private final String s;
private final int n;
private int index;

public MarqueePanel(String s, int n) {
if (s == null || n < 1) {
throw new IllegalArgumentException("Null string or n < 1");
}
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
sb.append(' ');
}
this.s = sb + s + sb;
this.n = n;
label.setFont(new Font("Serif", Font.ITALIC, 36));
label.setText(sb.toString());
this.add(label);
}

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

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

@Override
public void actionPerformed(ActionEvent e) {
index++;
if (index > s.length() - n) {
index = 0;
}
label.setText(s.substring(index, index + n));
}
}

Animating or 'scrolling' text upward within a JFrame

Here is some old code I had lying around that may help:

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

public class ScrollingScrollPane extends JScrollPane implements ActionListener
{
private int scrollOffset;
private Timer timer;
private boolean firstTime = true;
private int locationY;

public ScrollingScrollPane(JComponent component, int delay, int scrollOffset)
{
super(component);

this.scrollOffset = scrollOffset;

setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);

component.setVisible( false );
component.setSize( component.getPreferredSize() );
getViewport().setBackground( component.getBackground() );
getViewport().setLayout( null );

timer = new Timer(delay, this);
}

public void startScrolling()
{
locationY = getViewport().getExtentSize().height;
JComponent component = (JComponent)getViewport().getView();
component.setVisible( true );
component.setLocation(0, locationY);
timer.start();
}

public void actionPerformed(ActionEvent e)
{
JComponent component = (JComponent)getViewport().getView();
locationY -= scrollOffset;
Dimension d = getViewport().getExtentSize();
component.setBounds(0, locationY, d.width, d.height);
// component.setLocation(0, locationY);
// component.setSize( getViewport().getExtentSize() );
// System.out.println(locationY);

if (component.getPreferredSize().height + locationY < 0)
timer.stop();
}

public static void main(String[] args)
{
JTextPane textPane = new JTextPane();
textPane.setEditable(false);
StyledDocument doc = textPane.getStyledDocument();

SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes(0, 0, center, false);

SimpleAttributeSet keyWord = new SimpleAttributeSet();
StyleConstants.setFontSize(keyWord, 16);
StyleConstants.setBold(keyWord, true);

SimpleAttributeSet red = new SimpleAttributeSet();
StyleConstants.setForeground(red, Color.RED);

try
{
doc.insertString(doc.getLength(), "In a Galaxy", keyWord );
doc.insertString(doc.getLength(), "\n", null );
doc.insertString(doc.getLength(), "\nfar", red );
doc.insertString(doc.getLength(), "\n", null );
doc.insertString(doc.getLength(), "\nfar", red );
doc.insertString(doc.getLength(), "\n", null );
doc.insertString(doc.getLength(), "\naway", red );
doc.insertString(doc.getLength(), "\n", null );
doc.insertString(doc.getLength(), "\n...", null );
}
catch(Exception e) {}

ScrollingScrollPane scrollPane = new ScrollingScrollPane(textPane, 50, 1);

JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( scrollPane );
// frame.setResizable( false );
frame.setSize(300, 300);
frame.setVisible(true);

scrollPane.startScrolling();
}
}

How to create running text with jlabel?

You should use javax.swing.Timer to schedule JLabel updates. Please, see simplified code snippet below:

JFrame frame = new JFrame("Test");
frame.setSize(300, 300);
JLabel label = new JLabel("This is text!!!");
frame.add(label);
frame.setVisible(true);

final int labelWidth = 300;
final AtomicInteger labelPadding = new AtomicInteger();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
label.setBorder(new EmptyBorder(0, labelPadding.getAndIncrement() % labelWidth, 0, 0));
}
});
timer.start();

Note that AtomicInteger is not necessary, but you need some final holder to be able to use it inside inner class or lambda.

Auto loop-scrolling active contents in JPanel - marquee text

You might be able to use the Marquee Panel. The code uses real components so you should be able to add and react to any listener you add to the components.

Edit:

Oops, I don't know what I was thinking, my code uses the Graphics.translate(...) method to paint the components so using a MouseListener directly won't work.

Edit2:

Maybe the following code will help. Just add the method to the MarqueePanel class:

public Component getComponentAtPoint(Point p)
{
int translatedX = p.x + scrollOffset;

if (isWrap())
{
int preferredWidth = super.getPreferredSize().width;
preferredWidth += getWrapAmount();
translatedX = translatedX % preferredWidth;
}

Point translated = new Point(translatedX, p.y);

for (Component c: getComponents())
{
if (c.getBounds().contains(translated))
return c;
}

return null;
}

Now you can add a MouseListener to the MarqueePanel and then invoke this method in order to determine which component the MouseEvent was generated for. Once you know which component was clicked you will manually need to invoke an Action for that component. Or you could try redispatching the MouseEvent to the component. You wouuld need to recreate the MouseEvent to make the component the source of the event instead of the panel being the source. You would also need to covert the event X/Y locations to be relative to the component and not the panel. The SwingUtils class should help with this.

How to add marquee behaviour to JLabel

Please see http://forums.sun.com/thread.jspa?forumID=57&threadID=605616 for details about how to do this :)

(Edit: I would probably use System.currentTimeMillis() directly inside the paint() method instead of using a timer, and then divide / modulo (%) it to get it into the required range for 'x offset' on the examples). By increasing the size of the division number, you can change the speed ((System.currentTimeMillis() / 200) % 50).

(Edit 2: I just updated the code below to fix a problem with repainting. Now we schedule a repaint within the paint method; maybe there's a better way but this works :))

(Edit 3: Errr, I tried with a longer string and it messed up. That was easy to fix (increase range by width again to compensate for negative values, subtract by width)

package mt;

import java.awt.Graphics;

import javax.swing.Icon;
import javax.swing.JLabel;

public class MyJLabel extends JLabel {
public static final int MARQUEE_SPEED_DIV = 5;
public static final int REPAINT_WITHIN_MS = 5;

/**
*
*/
private static final long serialVersionUID = -7737312573505856484L;

/**
*
*/
public MyJLabel() {
super();
// TODO Auto-generated constructor stub
}

/**
* @param image
* @param horizontalAlignment
*/
public MyJLabel(Icon image, int horizontalAlignment) {
super(image, horizontalAlignment);
// TODO Auto-generated constructor stub
}

/**
* @param image
*/
public MyJLabel(Icon image) {
super(image);
// TODO Auto-generated constructor stub
}

/**
* @param text
* @param icon
* @param horizontalAlignment
*/
public MyJLabel(String text, Icon icon, int horizontalAlignment) {
super(text, icon, horizontalAlignment);
// TODO Auto-generated constructor stub
}

/**
* @param text
* @param horizontalAlignment
*/
public MyJLabel(String text, int horizontalAlignment) {
super(text, horizontalAlignment);
// TODO Auto-generated constructor stub
}

/**
* @param text
*/
public MyJLabel(String text) {
super(text);
}

/* (non-Javadoc)
* @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
*/
@Override
protected void paintComponent(Graphics g) {
g.translate((int)((System.currentTimeMillis() / MARQUEE_SPEED_DIV) % (getWidth() * 2)) - getWidth(), 0);
super.paintComponent(g);
repaint(REPAINT_WITHIN_MS);
}
}


Related Topics



Leave a reply



Submit