0

I'm about to embark on writing a (I think it will be) quick program involving a pulling headlines from a stock website and inserting them into an ArrayList of a class I'm going to create called Funds/Tickers/WhatHaveYou. That's not the huge problem. The main problem I have is this:

I want to have just one window, and that window will just continuously scroll the headlines. You can click on the headlines and that will bring up a browser to the article to read.

I initially thought you could do this with JLabels, but I did a few experiments and I could only get Strings to move accross the screen, not JLabels/JButtons/clickable things. Is there a way I can have JLabels or hyperlinks scroll accross the window in Java?

Cheers, David

jDave1984
  • 896
  • 4
  • 13
  • 43
  • How were you moving the strings? I mean exactly _were_ the strings? Were the JLabels, were you painting them? Are you using a timer? – Paul Samsotha Jan 27 '14 at 16:15
  • I was just using the Graphics class to print out a string onto a JPanel and moving them that way – jDave1984 Jan 28 '14 at 14:13

4 Answers4

2

In this example, entries from an RSS feed are added to a JTextPane. A HyperlinkListener can be added to receive events representing clicks on hyerlinks.

image

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

I want to have just one window, and that window will just continuously scroll the headlines.

You can use the Marquee Panel for this.

You can click on the headlines and that will bring up a browser to the article to read.

The above class doesn't support clicking on the components. However, I have been playing around a little with this concept. It seems to work OK when using a JLabel but I don't think it works for other components.

1) First you need to add a couple of methods to the MarqueePanel class that will translate the mouse point to map to the real component on the panel (in case you are using the wrapping option):

@Override
public Component getComponentAt(int x, int y)
{
    Point translated = getTranslatedPoint(x, y);

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

    return null;
}

public Point getTranslatedPoint(int x, int y)
{
    int translatedX = x + scrollOffset;

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

    return new Point(translatedX, y);
}

2) Then you can add a MouseListener to the panel. With code like the following you can now access the label that was clicked:

marquee.addMouseListener( new MouseAdapter()
{
    @Override
    public void mousePressed(MouseEvent e)
    {
        Component c = marquee.getComponentAt(e.getPoint());

        if (c == null) return;

        if (c insstanceof JLabel)
        {
            JLabel label = (JLabel)c;
            System.out.println(label.getText());
        }
    }
});
camickr
  • 321,443
  • 19
  • 166
  • 288
1

Maybe what you need is a a EditorPane:

http://docs.oracle.com/javase/tutorial/uiswing/components/editorpane.html

Hope it helps.

eltabo
  • 3,749
  • 1
  • 21
  • 33
0

I was working on this yesterday, when you first posted your question. I got tired and stopped messing with it. Basically what I did was use JPanel, and set their locations with each timer tick. I doubt it's the most optimal way, and I got really tired of trying to fix some of the problem, so I just stopped. You're free to play around with it, see if you can get any better results from it. The most frustrating part is when you click the panel, everything shifts for a quick second. Hopefully you can do something with it, or at least get some ideas. I just didn't want to scrap it, in case maybe you could make something of it.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestLabelMove {

    List<MovingLabel> labels;
    private int count = 1;
    private JLabel statusLabel;
    private final int SEPARATION = 100;
    private final int SCREEN_W = 800;
    int XLOC = SCREEN_W;

    public TestLabelMove() {

        statusLabel = new JLabel("Status");
        statusLabel.setHorizontalAlignment(JLabel.CENTER);

        JFrame frame = new JFrame("Test Labels");
        frame.add(statusLabel, BorderLayout.CENTER);
        frame.add(new LabelPanel(), BorderLayout.SOUTH);
        frame.setSize(800, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }

    private class LabelPanel extends JPanel {


        private static final int INC = 5;

        public LabelPanel() {
            labels = new LinkedList<>();
            for (int i = 0; i < 8; i++) {
                MovingLabel label = new MovingLabel(XLOC);
                labels.add(label);
                XLOC -= SEPARATION;
                add(label);
            }

            Timer timer = new Timer(100, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    for (MovingLabel label : labels) {
                        if (isWrap(label.getXLoc())) {
                            label.setXLoc(SCREEN_W);
                            label.setLocation(label.getXLoc(), 0);
                        } else {
                            label.setLocation(label.getXLoc(), 0);
                            label.setXLoc(label.getXLoc() - INC);
                        }
                    }

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

    public boolean isWrap(int x) {
        return x <= -40;
    }

    private class MovingLabel extends JPanel {

        int xLoc;
        String phrase;
        public MovingLabel(int xLoc) {
            this.xLoc = xLoc;
            phrase = "Panel " + count;
            count++;

            this.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    statusLabel.setText(phrase);
                    repaint();
                }
            });
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Font font = new Font("Helvetica", Font.BOLD, 14);
            FontMetrics fm = g.getFontMetrics(font);
            int w = fm.stringWidth(phrase);
            int h = fm.getAscent();
            g.setFont(font);
            g.drawString(phrase, getWidth()/2 - w/2, getHeight()/2 + h/2);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 20);
        }

        public void setXLoc(int xLoc) {
            this.xLoc = xLoc;
        }

        public int getXLoc() {
            return xLoc;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TestLabelMove();
            }
        });
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720