Animate/scroll text - java

I am wondering to know about how to make scrolling text. Just like text which can scroll from right to the left. How to animate text in Java GUI?

maybe not an answer for OP, but I can't see reason, very simple by implements Swing Timer, (may be with Translucent container) and put there a JLabel, (updates to the JLabel could be from Array of Chars to avoids resize of container), for example
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
import javax.swing.Timer;
public class SlideTextSwing {
private JWindow window = new JWindow();
private JLabel label = new JLabel("Slide Text Swing, Slide Text Swing, ..........");
private JPanel windowContents = new JPanel();
public SlideTextSwing() {
windowContents.add(label);
window.add(windowContents);
window.pack();
window.setLocationRelativeTo(null);
final int desiredWidth = window.getWidth();
window.getContentPane().setLayout(null);
window.setSize(0, window.getHeight());
window.setVisible(true);
Timer timer = new Timer(20, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int newWidth = Math.min(window.getWidth() + 1, desiredWidth);
window.setSize(newWidth, window.getHeight());
windowContents.setLocation(newWidth - desiredWidth, 0);
if (newWidth >= desiredWidth) {
((Timer) e.getSource()).stop();
label.setForeground(Color.red);
mainKill();
}
}
});
timer.start();
}
public void mainKill() {
Timer timer = new Timer(500, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
timer.start();
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
SlideTextSwing windowTest = new SlideTextSwing();
}
});
}
}

Related

Prevent JButton repaint() after click

I have a button. I want to change the background after I click on it. My problem here is the button auto call paintComponent(). How can prevent this? I expect after clicking the button the button will be blue, but it will still be red.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonDemo extends JButton implements ActionListener{
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.RED);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(500, 500);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.setBackground(Color.BLUE);
}
}
My personal gut feeling is that JButton is probably not suited to your desired goal.
Essentially, you want to control when and how the "selected" state of the piece is changed.
Personally, I would have some kind of controller which monitored the mouse events in some way (probably having the piece component delegate the event back to the controller) and some kind of model which control when pieces become selected, this would then notify the controller of the state change and it would make appropriate updates to the UI.
But that's a long process to setup. Instead, I'm demonstrating a simple concept where a component can be selected with the mouse, but only the controller can de-select. In this example, this will allow only a single piece to be selected
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(5, 5));
ChangeListener listener = new ChangeListener() {
private PiecePane selectedPiece;
#Override
public void stateChanged(ChangeEvent e) {
if (!(e.getSource() instanceof PiecePane)) { return; }
PiecePane piece = (PiecePane) e.getSource();
// Want to ignore events from the selected piece, as this
// might interfer with the changing of the pieces
if (selectedPiece == piece) { return; }
if (selectedPiece != null) {
selectedPiece.setSelecetd(false);
selectedPiece = null;
}
selectedPiece = piece;
}
};
for (int index = 0; index < 5 * 5; index++) {
PiecePane pane = new PiecePane();
pane.addChangeListener(listener);
add(pane);
}
}
}
public class PiecePane extends JPanel {
private boolean selecetd;
private Color selectedBackground;
private Color normalBackground;
private MouseListener mouseListener;
public PiecePane() {
setBorder(new LineBorder(Color.DARK_GRAY));
mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
setSelecetd(true);
}
};
setNormalBackground(Color.BLUE);
setSelectedBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void addNotify() {
super.addNotify();
addMouseListener(mouseListener);
}
#Override
public void removeNotify() {
super.removeNotify();
removeMouseListener(mouseListener);
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
protected void fireSelectionChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners.length == 0) {
return;
}
ChangeEvent evt = new ChangeEvent(this);
for (int index = listeners.length - 1; index >= 0; index--) {
listeners[index].stateChanged(evt);
}
}
public boolean isSelected() {
return selecetd;
}
public void setSelecetd(boolean selecetd) {
if (selecetd == this.selecetd) { return; }
this.selecetd = selecetd;
updateSelectedState();
fireSelectionChanged();
}
public Color getSelectedBackground() {
return selectedBackground;
}
public void setSelectedBackground(Color selectedBackground) {
this.selectedBackground = selectedBackground;
updateSelectedState();
}
public Color getNormalBackground() {
return normalBackground;
}
public void setNormalBackground(Color normalBackground) {
this.normalBackground = normalBackground;
updateSelectedState();
}
protected void updateSelectedState() {
if (isSelected()) {
setBackground(getSelectedBackground());
} else {
setBackground(getNormalBackground());
}
}
}
}
I created a toggle button.
You set the primary color and the alternate color in the class constructor.
When you call the switchColors method, the JButton background changes from the primary color to the alternate color. When you call the switchColors method again, the JButton background changes from the alternate color to the primary color.
In the following example, I put the switchColors method in the actionListener so you can see the color change. Each time you left-click on the JButton, the background color changes.
You would call the switchColors method when you want the JButton background to change from blue to red, and again when you want the JButton background to change from red to blue. It's under your control.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonDemo extends JButton
implements ActionListener {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Button Demo");
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo(Color.BLUE,
Color.RED));
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
private boolean primaryBackground;
private Color primaryColor;
private Color alternateColor;
public ButtonDemo(Color primaryColor,
Color alternateColor) {
this.primaryColor = primaryColor;
this.alternateColor = alternateColor;
this.primaryBackground = true;
this.setText("BUTTON TEXT");
this.setBackground(primaryColor);
this.addActionListener(this);
}
public void switchColors() {
primaryBackground = !primaryBackground;
Color color = primaryBackground ? primaryColor :
alternateColor;
this.setBackground(color);
}
#Override
public void actionPerformed(ActionEvent e) {
switchColors();
}
}
If you want to change the background for a short while you can do it with swing Timer:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ButtonDemo extends JButton implements ActionListener{
private static final int DELAY = 600; //milliseconds
private final Timer timer;
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
Color defaultCloor = getBackground();
timer = new Timer(DELAY, e-> setBackground(defaultCloor));
timer.setRepeats(false);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(300, 200);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
this.setBackground(Color.RED);
timer.start();
}
}

Using a thread to repaint() components

It doesn't appear that my thread ever starts. Either that or the run method isn't actually doing anything, for which reason I could not explain.
I have a listener on my button StartRace and it should start the thread which will increment the length of each rectangle until one of them is long enough to be declared winner (by surpassing the width of the window, 250px).
I get all of the components initially painted to the screen, but they're never repainted. Is there something wrong with the way I call the method? Do I have classes nested within others that shouldn't be?
//--------------------------------------------------------------
// Start a race between blue and red, track the winner
// Use threads to manage each rectangle's movement
// Allow for user interaction, like stopping and starting
//--------------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class ConcurrencyRace extends JFrame
{
private ConcurrencyPanel panel = new ConcurrencyPanel();
private JButton startRace = new JButton("Start The Race!");
private JButton stopRace = new JButton("Stop The Race!");
private JLabel winnerText = new JLabel("Winner: ");
private int blueDraw = 5, redDraw = 5;
private Random rn = new Random();
//-----------------------------------------------------------------
// Creates and displays the main program frame.
//-----------------------------------------------------------------
public ConcurrencyRace() {
super("Concurrency");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Container cp = getContentPane();
cp.add(panel, BorderLayout.CENTER);
JPanel p = new JPanel();
p.add(startRace);
p.add(stopRace);
cp.add(p, BorderLayout.NORTH);
cp.add(winnerText, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main (String[] args)
{
ConcurrencyRace tRun = new ConcurrencyRace();
tRun.setVisible(true);
}
private class ConcurrencyPanel extends JPanel
{
public class runnerThread extends Thread {
#Override
public void run() {
while (blueDraw < 250 && redDraw < 250) {
panel.validate();
panel.repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
}
}
}
public ConcurrencyPanel ()
{
setPreferredSize(new Dimension(600,250));
}
private class ButtonListener implements ActionListener {
runnerThread rectDraw = new runnerThread();
//--------------------------------------------------------------
// Starts the thread to draw each rectangle ("racer")
//--------------------------------------------------------------
public void actionPerformed (ActionEvent event)
{
if (event.getSource() == startRace) {
rectDraw.start();
}
}
}
#Override
public void paintComponent (Graphics page) {
super.paintComponent(page);
page.setColor(Color.blue);
page.fillRect(0,80,blueDraw,20);
page.setColor(Color.red);
page.fillRect(0,120,redDraw,20);
blueDraw += rn.nextInt(10) + 1;
redDraw += rn.nextInt(10) + 1;
page.dispose();
}
}
}
Primarily
You never add a ActionListener to either of your buttons, so nothing is responding when they are activated
Additionally
The state management is all over the place. blueDraw and redDraw should be instance fields of ConcurrencyPanel.
Don't update the state of the UI (or variables which the UI relies on) from within any paint method. Paint methods should paint the state, not change it. Updating the blueDraw and redDraw should be done in a specific method, which can be called when a update is required.
All of that leads me to believe you'd be better of using a Swing Timer
Conceptually...
You could do something like this...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ConcurrencyRace {
//-----------------------------------------------------------------
// Creates and displays the main program frame.
//-----------------------------------------------------------------
public ConcurrencyRace() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Timer timer = new Timer(200, null);
JFrame frame = new JFrame();
frame.add(new ButtonPane(timer), BorderLayout.NORTH);
frame.add(new RacePane(timer));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new ConcurrencyRace();
}
public class ButtonPane extends JPanel {
private JButton startRace = new JButton("Start The Race!");
private JButton stopRace = new JButton("Stop The Race!");
public ButtonPane(Timer timer) {
startRace.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopRace.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
setLayout(new GridBagLayout());
add(startRace);
add(stopRace);
}
}
private class RacePane extends JPanel {
private int blueDraw = 5, redDraw = 5;
private Random rn = new Random();
public RacePane(Timer timer) {
timer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (updateState()) {
((Timer)e.getSource()).stop();
}
}
});
}
protected boolean updateState() {
blueDraw += rn.nextInt(10) + 1;
redDraw += rn.nextInt(10) + 1;
repaint();
return blueDraw >= getWidth() || redDraw >= getWidth();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 250);
}
#Override
public void paintComponent(Graphics page) {
System.out.println(">>");
super.paintComponent(page);
page.setColor(Color.blue);
page.fillRect(0, 80, blueDraw, 20);
page.setColor(Color.red);
page.fillRect(0, 120, redDraw, 20);
}
}
}
This maintains the Timer as the central concept, which is shared between the buttons and race panels.
I've not added support for generating notification of a winner, this would be done via a simple observer pattern passed to the RacePane

In Java, how could I make a letter flash on the screen depending on a BPM value the user provides?

With Swing, I've created a window and want a letter to flash on the screen depending on the BPM (Beats per minute) the user inputs, and I was wondering how I would go about timing the flashing accurately. I tried using a Swing Timer but it is not very accurate and I see a lot of pauses or lag. I've heard something about using System.nanoTime() and System.currentTimeMillis() but have no clue how to implement them to create a timer. Any help would be appreciated!
Note.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.*;
import java.awt.*;
public class Note extends JFrame implements ActionListener {
JPanel mainScreen = new JPanel();
JPanel south = new JPanel();
JPanel north = new JPanel();
//emptyNumberMain = how many empty panels you want to use
public int emptyNumberMain = 2;
JPanel[] emptyMain = new JPanel[emptyNumberMain];
JLabel title = new JLabel("Fretboard Trainer!");
JButton start = new JButton("Start!");
public static void main(String[] args) {
new Note();
}
public Note() {
super("Random Note!");
setSize(300,300);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//creates emptyNumberMain amount of empty panels
for (int i = 0; i < emptyNumberMain; i++) {
emptyMain[i] = new JPanel();
}
mainScreen.setLayout(new BorderLayout());
south.setLayout(new GridLayout(1,1));
south.add(emptyMain[0]);
south.add(start);
south.add(emptyMain[1]);
north.setLayout(new GridLayout(1,2));
north.add(title);
title.setHorizontalAlignment(JLabel.CENTER);
title.setFont(title.getFont().deriveFont(32f));
start.addActionListener(this);
mainScreen.add(north, BorderLayout.NORTH);
mainScreen.add(south, BorderLayout.SOUTH);
add(mainScreen);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == start) {
dispose();
new RandomNote();
}
}
}
RandomNote.java
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import java.util.Random;
import javax.swing.Timer;
import javax.swing.JSlider;
import java.awt.event.*;
import java.awt.*;
public class RandomNote extends JFrame {
JPanel noteScreen = new JPanel();
JPanel center = new JPanel();
JPanel southSlider = new JPanel();
JLabel bpm = new JLabel();
//emptyNumber = how many empty panels you want to use
int emptyNumber = 2;
JPanel[] empty = new JPanel[emptyNumber];
JLabel rndNote = new JLabel();
JSlider slider = new JSlider(0,200,100);
Timer timer2 = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
bpm.setText(Integer.toString(slider.getValue()));
timer.setDelay((int) ((60.0/slider.getValue()) * 1000));
}
});
public RandomNote() {
super("Random Notes!");
timer.start();
timer2.start();
setSize(500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
//creates variable emptyNumber amount of empty panels
for (int i = 0; i < emptyNumber; i++) {
empty[i] = new JPanel();
}
noteScreen.setLayout(new BorderLayout());
center.setLayout(new GridLayout(1,1));
center.add(rndNote);
southSlider.setLayout(new GridLayout(3,1));
slider.setLabelTable(slider.createStandardLabels(20));
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(20);
southSlider.add(slider);
southSlider.add(bpm);
rndNote.setHorizontalAlignment(JLabel.CENTER);
rndNote.setFont(rndNote.getFont().deriveFont(32f));
noteScreen.add(center, BorderLayout.CENTER);
noteScreen.add(southSlider, BorderLayout.SOUTH);
add(noteScreen);
setVisible(true);
}
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
rndNote.setText(noteOutput());
}
});
public static String noteOutput() {
Random rand = new Random();
String[] note = {"A", "B", "C", "D", "E", "F", "G"};
int randNum = rand.nextInt(7);
return note[randNum];
}
}
The immediate thing that jumps out at me is this...
Timer timer2 = new Timer(100, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
bpm.setText(Integer.toString(slider.getValue()));
timer.setDelay((int) ((60.0/slider.getValue()) * 1000));
}
});
Why do you need to update the text and reset the timer every 100 milliseconds?
So, the simple answer would be to use a ChangeListener on the JSlider to determine when the slider's value changes. I'd recommend having a look at How to Use Sliders for more details
As a runnable concept...
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
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("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private AnimatableLabel label;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
label = new AnimatableLabel("BMP");
label.setHorizontalAlignment(JLabel.CENTER);
add(label, gbc);
label.start();
JSlider slider = new JSlider(10, 200);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
label.setBPM(slider.getValue());
}
});
slider.setValue(60);
add(slider, gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class AnimatableLabel extends JLabel {
private Timer pulseTimer;
private Timer fadeTimer;
private double bpm = 60;
private double alpha = 0;
private Long pulsedAt;
public AnimatableLabel(String text, Icon icon, int horizontalAlignment) {
super(text, icon, horizontalAlignment);
setBackground(Color.RED);
initTimer();
}
public AnimatableLabel(String text, int horizontalAlignment) {
super(text, horizontalAlignment);
setBackground(Color.RED);
initTimer();
}
public AnimatableLabel(String text) {
super(text);
setBackground(Color.RED);
initTimer();
}
public AnimatableLabel(Icon image, int horizontalAlignment) {
super(image, horizontalAlignment);
setBackground(Color.RED);
initTimer();
}
public AnimatableLabel(Icon image) {
super(image);
setBackground(Color.RED);
initTimer();
}
public AnimatableLabel() {
setBackground(Color.RED);
initTimer();
}
public void start() {
updateTimer();
}
public void stop() {
pulseTimer.stop();
fadeTimer.stop();
}
protected void initTimer() {
pulseTimer = new Timer((int)(getDuration()), new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pulsedAt = System.currentTimeMillis();
alpha = 1.0;
repaint();
}
});
pulseTimer.setInitialDelay(0);
pulseTimer.setCoalesce(true);
fadeTimer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (pulsedAt == null) {
return;
}
long fadingDuration = System.currentTimeMillis() - pulsedAt;
alpha = 1.0 - (fadingDuration / getDuration());
if (alpha > 1.0) {
alpha = 1.0;
} else if (alpha < 0.0) {
alpha = 0.0;
}
repaint();
}
});
fadeTimer.setCoalesce(true);
}
protected double getDuration() {
return (60.0 / bpm) * 1000.0;
}
protected void updateTimer() {
fadeTimer.stop();
pulseTimer.stop();
pulseTimer.setDelay((int)getDuration());
pulseTimer.start();
fadeTimer.start();
}
public void setBPM(double bpm) {
this.bpm = bpm;
setText(Double.toString(bpm));
updateTimer();
}
public double getBPM() {
return bpm;
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive((float)alpha));
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
}
}

Programmatically expand sub JMenuItems

I would like to programmatically expand a particular JMenuItem in a JPopup. For example in the code below
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
public class AutoExpandSubMenusDemo extends JFrame {
private final JPopupMenu popup = new JPopupMenu("Popup");
public AutoExpandSubMenusDemo() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
JMenu menuB = new JMenu("B");
menuB.add(new JMenuItem("X"));
JMenuItem menuY = menuB.add(new JMenuItem("Y"));
menuB.add(new JMenuItem("Z"));
popup.add(new JMenuItem("A"));
popup.add(menuB);
popup.add(new JMenuItem("C"));
final JButton button = new JButton("Show Popup Menu");
button.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
popup.show(button, 0, button.getHeight());
// Show menuY
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
getContentPane().add(buttonPanel);
}
public static void main(String[] args) {
AutoExpandSubMenusDemo f = new AutoExpandSubMenusDemo();
f.setSize(500, 300);
f.setVisible(true);
}
}
I would like to expand the popup menu so that the items B(menuB)/Y(menuY) are expanded and selected when the button is pressed.
Sorry if this is something that's easy to do but I've searched around and can't figure it out.
I did find the
MenuSelectionManager.defaultManager().setSelectedPath(...)
however this didn't work when I tried it and the javadoc specifies that it is called from the LaF and should not be called by clients.
Any help is much appreciated.
While I don't recommend doing this, since the documentation itself advises against it, here's how you could do it:
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
public class AutoExpandSubMenusDemo extends JFrame {
private final JPopupMenu popup = new JPopupMenu("Popup");
public AutoExpandSubMenusDemo() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
final JMenu menuB = new JMenu("B");
menuB.add(new JMenuItem("X"));
final JMenuItem menuY = menuB.add(new JMenuItem("Y"));
menuB.add(new JMenuItem("Z"));
popup.add(new JMenuItem("A"));
popup.add(menuB);
popup.add(new JMenuItem("C"));
final JButton button = new JButton("Show Popup Menu");
button.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
popup.show(button, 0, button.getHeight());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuB.setPopupMenuVisible(true);
MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{popup, menuB, menuY});
}
});
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
getContentPane().add(buttonPanel);
}
public static void main(String[] args) {
AutoExpandSubMenusDemo f = new AutoExpandSubMenusDemo();
f.setSize(500, 300);
f.setVisible(true);
}
}
Most of this code is yours. I only added:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuB.setPopupMenuVisible(true);
MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{popup, menuB, menuY});
}
});
which seems to work.
You could avoid abusing MenuSelectionManager via 'MenuItem.setArmed(boolean)'.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuB.setPopupMenuVisible(true);
menuB.setArmed(true);
menuY.setArmed(true);
}
});
The popup staying visible after selecting another menu item or dismissing the JPopupMenu still needs to be addressed though.
Another way is to fake a mouse event... :D
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MouseEvent event = new MouseEvent(
menuB, MouseEvent.MOUSE_ENTERED, 0, 0, 0, 0, 0, false);
menuB.dispatchEvent(event);
menuY.setArmed(true);
}
});
This way it is as if the user actually used the mouse.
Another example:
MenuSelectionManager.defaultManager().setSelectedPath(
new MenuElement[] {popup, menuB, menuB.getPopupMenu()});
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AutoExpandSubMenusDemo2 extends JFrame {
private final JPopupMenu popup = new JPopupMenu("Popup");
public AutoExpandSubMenusDemo2() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
final JMenu menuB = new JMenu("B");
menuB.add(new JMenuItem("X"));
final JMenuItem menuY = menuB.add(new JMenuItem("Y"));
menuB.add(new JMenuItem("Z"));
popup.add(new JMenuItem("A"));
popup.add(menuB);
popup.add(new JMenuItem("C"));
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(new AbstractAction("Show menuB Popup") {
#Override public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
popup.show(button, 0, button.getHeight());
//[Bug ID: JDK-6949414 JMenu.buildMenuElementArray() endless loop]
//( http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6949414 )
//menuB.doClick();
MenuSelectionManager.defaultManager().setSelectedPath(
new MenuElement[] {popup, menuB, menuB.getPopupMenu()});
}
}));
buttonPanel.add(new JButton(new AbstractAction("Select menuY") {
#Override public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
popup.show(button, 0, button.getHeight());
MenuSelectionManager.defaultManager().setSelectedPath(
new MenuElement[] {popup, menuB, menuB.getPopupMenu(), menuY});
}
}));
getContentPane().add(buttonPanel);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new AutoExpandSubMenusDemo2();
f.setSize(500, 300);
f.setVisible(true);
}
}

Keylistener not working with fullscreen

I have created a program in which a window opens which says click to start.When we press start button it opens another window and make it fullscreen. I have add keylistener to this fullscreen window to move an image.But its not working. If you wanna see the code please ask me .
public g1(){
panel = new JPanel();
cake = new ImageIcon("G:\\naman1.jpg").getImage();
start = new JButton("Start");
restart = new JButton("Restart");
exit = new JButton("EXIT");
panel.add(start);
panel.setFocusable(true);
start.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
new g1().run(); //this method is from superclass it calls init }
}
);
panel.setBackground(Color.GRAY);
}
public void init(){
super.init(); //it makes the window fullscreen
Window w = s.getFullScreenWindow();
w.setFocusable(true);
w.addKeyListener(this);}
Try this:
The MainFrame
package moveimages;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
JButton startBtn;
public MainFrame() {
this.setTitle("Moving Images");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(initComponents());
this.setSize(new Dimension(1024, 768));
this.setVisible(true);
}
private JPanel initComponents() {
JPanel jPanel = new JPanel();
startBtn = new JButton("start");
startBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final ImageWindow imageWindow = new ImageWindow();
}
});
jPanel.add(startBtn);
return jPanel;
}
}
This is the ImageWindow
package moveimages;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class ImageWindow extends JFrame {
public ImageWindow() {
this.add(new JLabel("Window"));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setSize(screenSize.width, screenSize.height);
final ImagePanel imagePanel = new ImagePanel();
this.getContentPane().add(imagePanel);
this.setVisible(true);
}
class ImagePanel extends JPanel {
URL url;
int panelX;
int panelY;
boolean isDragged;
ImagePanel() {
this.panelX = this.getWidth();
this.panelY = this.getHeight();
try {
this.url = new URL("http://i.stack.imgur.com/XZ4V5.jpg");
final ImageIcon icon = new ImageIcon(url);
final JLabel imageLabel = new JLabel(icon);
Action moveLeft = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
if(imageLabel.getX() - 1 > 0)
imageLabel.setLocation(imageLabel.getX()-1, imageLabel.getY());
}
};
Action moveUp = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
if(imageLabel.getY() - 1 > 0) {
imageLabel.setLocation(imageLabel.getX(), imageLabel.getY()-1);
}
}
};
Action moveDown = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
if(getParent().getHeight()-icon.getIconHeight() > imageLabel.getY() + 1) {
imageLabel.setLocation(imageLabel.getX(), imageLabel.getY()+1);
}
}
};
Action moveRight = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
if(getParent().getWidth()-icon.getIconWidth() > imageLabel.getX()+1) {
imageLabel.setLocation(imageLabel.getX()+1, imageLabel.getY());
}
}
};
imageLabel.getInputMap().put(KeyStroke.getKeyStroke("A"), "moveLeft");
imageLabel.getInputMap().put(KeyStroke.getKeyStroke("W"), "moveUp");
imageLabel.getInputMap().put(KeyStroke.getKeyStroke("S"), "moveDown");
imageLabel.getInputMap().put(KeyStroke.getKeyStroke("D"), "moveRight");
imageLabel.getActionMap().put("moveLeft", moveLeft);
imageLabel.getActionMap().put("moveUp", moveUp);
imageLabel.getActionMap().put("moveDown", moveDown);
imageLabel.getActionMap().put("moveRight", moveRight);
this.add(imageLabel);
} catch (MalformedURLException ex) {
Logger.getLogger(ImageWindow.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Start the App
package moveimages;
import javax.swing.SwingUtilities;
public class MoveImages {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MainFrame frame = new MainFrame();
});
}
}
Maybe it helps you to refactor your current app.

Categories

Resources