I'm using the Nimbus L&F and trying to change the background color. I'm setting the color with this: iFrame.getContentPane().setBackground(Color.BLACK);. However it ends up with a small area at the top with the default color. And even worse. If I re-size the JInternalFrame this area changes it color from a darker gray into a lighter one. I searched for this problem and at least i figured out that it has to be a problem caused by the title bar.
Picture of the JInternalFrame
Is there a way to solve this problem? Is this a known bug? Thank you.
Edit:
A small programm, where it happens.
Following line causes the problem: ret.put("defaultFont", new Font("Arial", Font.BOLD, 16)); Is this the wrong way to set the default font ?
package jInternalFrameTest;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
public class JInternalFrameTest extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public JInternalFrameTest() {
super("JInternalFrame Background Demo");
int inset = 50;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(inset, inset, screenSize.width - inset * 2, screenSize.height - inset * 2);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
createGUI();
}
private void createGUI() {
MyInternalFrame frame = new MyInternalFrame();
frame.setVisible(true);
this.getLayeredPane().add(frame, JLayeredPane.DRAG_LAYER);
try {
frame.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
try {
UIManager.setLookAndFeel(new NimbusLookAndFeel(){
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public UIDefaults getDefaults() {
UIDefaults ret = super.getDefaults();
ret.put("defaultFont", new Font("Arial", Font.BOLD, 16));
return ret;
}
});
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
}
new JInternalFrameTest().setVisible(true);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
class MyInternalFrame extends JInternalFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public MyInternalFrame() {
super("IFrame", true, // resizable
true, // closable
true, // maximizable
true);// iconifiable
setSize(300, 300);
getContentPane().setBackground(Color.BLACK);
pack();
}
}
}
Related
I was wondering why the JTextArea prints the same line twice. Im using multithreading and im new to this concept. I was wondering if that's where the issue is. As of looking it over I tried seeing if any run methods were called twice to cause such a thing. There aren't any loops in the code either. The line that says "Prints twice?" in the GameThread class is where the issue starts. Thanks for help.
Main Menu Class
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.Font;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.awt.event.ActionEvent;
public class MainMenu {
private JFrame menu;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainMenu window = new MainMenu();
window.menu.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
* #throws IOException
*/
public MainMenu() throws IOException {
initialize();
}
/**
* Initialize the contents of the frame.
* #throws IOException
*/
private void initialize() throws IOException {
menu = new JFrame();
menu.getContentPane().setBackground(Color.BLACK);
menu.setTitle("Zombie Game");
menu.setBounds(100, 100, 574, 374);
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu.getContentPane().setLayout(null);
JButton btnPlay = new JButton("Play");
// button action on click
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
GameScreen enterGame = new GameScreen();
menu.setVisible(false);
enterGame.run();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
JLabel lblNewLabel = new JLabel("Zombie Survival");
lblNewLabel.setFont(new Font("Tahoma", Font.BOLD, 40));
lblNewLabel.setForeground(Color.WHITE);
lblNewLabel.setBounds(118, 34, 381, 73);
menu.getContentPane().add(lblNewLabel);
btnPlay.setBackground(Color.WHITE);
btnPlay.setForeground(Color.RED);
btnPlay.setFont(new Font("Tahoma", Font.BOLD, 17));
btnPlay.setToolTipText("Click to begin.");
btnPlay.setBounds(225, 190, 118, 54);
menu.getContentPane().add(btnPlay);
}
}
Game Board
import java.awt.EventQueue;
import java.io.PrintStream;
import javax.swing.JFrame;
import java.awt.Color;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.JTextArea;
import java.awt.Font;
import javax.swing.JScrollPane;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class GameScreen {
private JFrame gameFrm;
/**
* Launch the application.
*/
public void run() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameScreen window = new GameScreen();
window.gameFrm.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
* #throws InterruptedException
*/
public GameScreen() throws InterruptedException {
initialize();
}
/**
* Initialize the contents of the frame.
* #throws InterruptedException
*/
private void initialize() throws InterruptedException {
gameFrm = new JFrame();
gameFrm.getContentPane().setBackground(Color.BLACK);
gameFrm.getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 478, 718, 134);
gameFrm.getContentPane().add(scrollPane);
JTextArea displayTextArea = new JTextArea();
displayTextArea.setLineWrap(true);
displayTextArea.setWrapStyleWord(true);
displayTextArea.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
}
}
});
scrollPane.setViewportView(displayTextArea);
displayTextArea.setFont(new Font("Monospaced", Font.PLAIN, 18));
displayTextArea.setForeground(Color.WHITE);
displayTextArea.setBackground(Color.BLACK);
PrintStream printStream = new PrintStream(new CustomOutputStream(displayTextArea));
System.setOut(printStream);
JLabel forestPicture = new JLabel("New label");
forestPicture.setIcon(new ImageIcon("C:\\Users\\fstal\\Documents\\Java Programs\\UpdatedZombieGame\\src\\gameForest.jpg"));
forestPicture.setBounds(0, 0, 738, 622);
gameFrm.getContentPane().add(forestPicture);
gameFrm.setBackground(Color.WHITE);
gameFrm.setTitle("Zombie Game");
gameFrm.setBounds(100, 100, 752, 659);
gameFrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Game work
GameThread gThread = new GameThread();
gThread.start();
}
}
Thread Class
public class GameThread extends Thread {
static String [] zombies = {"Zombie", "Fast Zombie", "Big Zombie", "Crawler"};
static String [] bag = {"Assault Rifle", "SMG", "Shotgun", "Sniper"};
static int [] zHealth = {100, 90, 200, 50};
static int [] damage = {90, 80, 100, 200};
static int playerHealth = 50;
public void run() {
try {
System.out.println("Zombies are coming!");
//Thread.sleep(2000);
System.out.println("Prints twice?");
}
catch (Exception e) {
e.printStackTrace();
}
}
}
CustomOutputStream Class for TextArea
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JTextArea;
public class CustomOutputStream extends OutputStream {
private JTextArea displayTextArea;
CustomOutputStream(JTextArea textArea) {
this.displayTextArea = textArea;
}
#Override
public void write(int b) throws IOException {
// redirects data to the text area
displayTextArea.append(String.valueOf((char)b));
// scrolls the text area to the end of data
displayTextArea.setCaretPosition(displayTextArea.getDocument().getLength());
}
}
You're creating two instance of the GameScreen, so your output get's printed twice
When you perform...
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
GameScreen enterGame = new GameScreen();
menu.setVisible(false);
enterGame.run();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
It calls the GameScreen constructor, which calls initialize()
/**
* Create the application.
*
* #throws InterruptedException
*/
public GameScreen() throws InterruptedException {
initialize();
}
And when you call run, it does it again...
/**
* Launch the application.
*/
public void run() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GameScreen window = new GameScreen();
window.gameFrm.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
You really don't need to do this again in run.
Now that we've discussed that problem, you have a number of other issues.
Firstly, Swing is NOT thread safe and you should never modify the UI (or anything the UI relies on) from outside the context of the Event Dispatching Thread.
See Concurrency in Swing for some more details (and possible solutions)
Second, null layouts are generally a bad idea - it made a mess of your UI on my PC. You should really take the time to learn how to use the various layout managers available in the API - see Laying Out Components Within a Container
im trying to do a bar that show some messages and I got a trouble with it, check the image below to see what I have so far:
http://i.stack.imgur.com/xSMtY.png
So, in the top bar, i have a panel made by myself that contains labels, each message is a label and it will roll in the panel, the problem is when the message go out of the screen i want her to go to the end of the queue, but since im using BoxLayout in my made up JPanel i can't do it, in the white bar, i got the same layout and i get the same problem, i dont know how i can keep rooling without break the chain...
(In Java)
If anyone of you can help me i will be glad for it...
Thank you all in advance for your time :)
Edit: as requested i will post some code here:
this is my custom panel code:
package smstest;
import entidades.MensagemParaEcra;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import static java.lang.Thread.sleep;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
*
* #author NEMESIS
*/
public class MyPanel extends JPanel {
private JLabel label;
//private MyPanel panel;
private LinkedList<String> texto;
private LinkedList<MensagemParaEcra> msgs;
private LinkedList<JLabel> labels;
private int x = 0, tamanho;
public MyPanel() {
texto = new LinkedList<>();
msgs = new LinkedList<>();
labels = new LinkedList<>();
//config panel
this.setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
this.setBackground(Color.black);
Dimension dim = new Dimension(1500, 30);
tamanho = 1500;
this.setPreferredSize(dim);
this.repaint();
this.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent e) {
tamanho = MyPanel.this.getWidth();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
}
#Override
public void componentHidden(ComponentEvent e) {
}
});
// start the scrolling of the labels
start();
}
public void addMensagem(MensagemParaEcra msg) {
labels.add(new JLabel(msg.getTexto() + " -- "));
refresh();
}
public void removerMsg(int id) {
int size = msgs.size();
for (int i = 0; i < size; i++) {
if (msgs.get(i).getId() == id) {
msgs.remove(i);
}
}
refresh();
}
private void refresh() {
int size = labels.size();
labels.get(0).setLocation(0, 0);
for (int i = 0; i < size; i++) {
labels.get(i).setForeground(Color.white);
labels.get(i).setFont(new Font("Tahoma", Font.BOLD, 40));
labels.get(i).setOpaque(true);
labels.get(i).setBackground(Color.red);
MyPanel.this.add(labels.get(i));
// since im using a box layout it's useless but otherwise this
// may add my labels one after the other
if (i > 0) {
int largura = labels.get(i - 1).getWidth();
labels.get(i).setLocation(x + largura, 0);
} else {
labels.get(i).setLocation(x, 0);
}
}
}
private void start() {
final Runnable running = new Runnable() {
#Override
public void run() {
MyPanel.this.repaint();
}
};
Thread t = new Thread() {
public void run() {
while (true) {
for (JLabel lb : labels) {
// make the labels get 3 pixels to the left
lb.setLocation(lb.getLocation().x -3, 0);
}
try {
SwingUtilities.invokeAndWait(running);
sleep(30);
} catch (InterruptedException ex) {
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(MyPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
t.start();
}
}
And this is the frame that have the 2 bars for the scrolling text:
package smstest;
import entidades.DadosDaAplicacao;
import entidades.MensagemParaEcra;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import static java.lang.Thread.sleep;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
/**
*
* #author NEMESIS
*/
public final class MonitorDeMensagensFrame extends javax.swing.JFrame {
private static final MonitorDeMensagensFrame instance = new MonitorDeMensagensFrame();
private static Point point = new Point();
private int tamanho = 1500;
private JLabel label;
private JLabel label1;
/**
* Creates new form MonitorDeMensagensFrame
*/
public MonitorDeMensagensFrame() {
initComponents();
MyPanel topPanel = new MyPanel();
// its an undecorated frame so i have the listers to move it
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
point.x = e.getX();
point.y = e.getY();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
Point p = getLocation();
setLocation(p.x + e.getX() - point.x, p.y + e.getY() - point.y);
}
});
// setting the size of the frame
setSize(getRes().width, 73);
setLocation(0, 0);
PanelMsg.repaint();
// create the labels for the below bar
criarPub();
// add messages to the upper bar using a method in MyPanel
// this messages now are made up for tests
topPanel.addMensagem(new MensagemParaEcra(0, "msg 1"));
topPanel.addMensagem(new MensagemParaEcra(1, "msg 2"));
topPanel.addMensagem(new MensagemParaEcra(2, "msg 3"));
topPanel.addMensagem(new MensagemParaEcra(3, "msg 4"));
topPanel.addMensagem(new MensagemParaEcra(4, "msg 5"));
topPanel.addMensagem(new MensagemParaEcra(5, "msg 6"));
topPanel.addMensagem(new MensagemParaEcra(6, "msg 7"));
// start the rolling text on the below bar
startPub();
}
private Dimension getRes() {
Toolkit toolkit = Toolkit.getDefaultToolkit();
// Get the current screen size
Dimension scrnsize = toolkit.getScreenSize();
return scrnsize;
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
PanelMsg = new javax.swing.JPanel();
PanelPublicidade = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setUndecorated(true);
getContentPane().setLayout(new java.awt.GridLayout(2, 0));
PanelMsg.setBackground(new java.awt.Color(255, 0, 0));
PanelMsg.setMinimumSize(new java.awt.Dimension(173, 20));
PanelMsg.setLayout(new java.awt.BorderLayout());
getContentPane().add(PanelMsg);
PanelPublicidade.setBackground(new java.awt.Color(102, 255, 102));
PanelPublicidade.setMinimumSize(new java.awt.Dimension(403, 25));
javax.swing.GroupLayout PanelPublicidadeLayout = new javax.swing.GroupLayout(PanelPublicidade);
PanelPublicidade.setLayout(PanelPublicidadeLayout);
PanelPublicidadeLayout.setHorizontalGroup(
PanelPublicidadeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 806, Short.MAX_VALUE)
);
PanelPublicidadeLayout.setVerticalGroup(
PanelPublicidadeLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 26, Short.MAX_VALUE)
);
getContentPane().add(PanelPublicidade);
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MonitorDeMensagensFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MonitorDeMensagensFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MonitorDeMensagensFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MonitorDeMensagensFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MonitorDeMensagensFrame().setVisible(true);
}
});
}
public static MonitorDeMensagensFrame getInstance() {
return instance;
}
public void criarPub() {
String msg = DadosDaAplicacao.getInstance().getMsgPublicidade();
PanelPublicidade.setLayout(new BoxLayout(PanelPublicidade, BoxLayout.X_AXIS));
PanelPublicidade.setBackground(Color.black);
Dimension dim = new Dimension(1500, 30);
PanelPublicidade.setPreferredSize(dim);
PanelPublicidade.repaint();
PanelPublicidade.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent e) {
tamanho = PanelMsg.getWidth();
}
#Override
public void componentMoved(ComponentEvent e) {
}
#Override
public void componentShown(ComponentEvent e) {
}
#Override
public void componentHidden(ComponentEvent e) {
}
});
label = new JLabel("");
label1 = new JLabel("");
label.setText(msg + " ");
label1.setText(msg + " ");
label.setForeground(Color.black);
label.setFont(new Font("Tahoma", Font.PLAIN, 40));
label.setOpaque(true);
label.setBackground(Color.white);
label1.setForeground(Color.black);
label1.setFont(new Font("Tahoma", Font.PLAIN, 40));
label1.setOpaque(true);
label1.setBackground(Color.white);
PanelPublicidade.add(label);
PanelPublicidade.add(label1);
label.setLocation(PanelPublicidade.getLocation().x, PanelPublicidade.getLocation().y);
label1.setLocation(label.getWidth(), label.getLocation().y);
PanelPublicidade.repaint();
}
public void startPub() {
final int tamanho = label.getWidth();
final Runnable running = new Runnable() {
#Override
public void run() {
PanelPublicidade.repaint();
}
};
Thread t = new Thread() {
#Override
public void run() {
while (true) {
label.setLocation(label.getLocation().x - 3,0);
label1.setLocation(label1.getLocation().x - 3, 0);
// if(label.getLocation().x + tamanho == 0){
// label.setLocation(label1.getLocation().x, 0);
// }
try {
SwingUtilities.invokeAndWait(running);
sleep(28);
} catch (InterruptedException ex) {
Logger.getLogger(MonitorDeMensagensFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(MonitorDeMensagensFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
t.start();
}
// Variables declaration - do not modify
private javax.swing.JPanel PanelMsg;
private javax.swing.JPanel PanelPublicidade;
// End of variables declaration
}
There is the code...
Thank you for the help :)
I have a JMenu of 16 JMenuItems, of which I want 3 items to be displayed upfront and the rest 13 items to fade in with a 500 ms delay. Is there a way to do this animation in Java?
This is not as easy as it sounds.
Basically I originally thought "I'll attach a popup listener to the popup menu that the menu items are added to"...but apparently this doesn't work so well. The menu popup is built dynamically on demand. Makes sense, but it's still a pain.
So instead, I've found that if I wait for addNotify I can simply start the animation engine.
The animation engine is a simple concept. It has a javax.swing.Timer that ticks at a regular interval. Coupled with a start time and a duration, we can calculate the progress of the animation and generate the alpha value as required.
The only thing left is then to notify all the interested parties that the animation has changed and voila...
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class FadeMenu {
private AnimationEngine engine;
public static void main(String[] args) {
new FadeMenu();
}
public FadeMenu() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
engine = new AnimationEngine();
JMenuBar mb = new JMenuBar();
JMenu flip = new JMenu("Flip");
flip.add("Static 1");
flip.add("Static 2");
flip.add("Static 3");
flip.add(new FadeMenuItem("Fade 1"));
flip.add(new FadeMenuItem("Fade 2"));
flip.add(new FadeMenuItem("Fade 3"));
flip.add(new FadeMenuItem("Fade 4"));
mb.add(flip);
JFrame frame = new JFrame("Testing");
frame.setJMenuBar(mb);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class FadeMenuItem extends JMenuItem {
public FadeMenuItem(String text) {
super(text);
engine.addTimingListener(new TimingListener() {
#Override
public void timingEvent() {
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setComposite(AlphaComposite.SrcOver.derive(engine.getAlpha()));
super.paintComponent(g2d);
g2d.dispose();
}
#Override
public void removeNotify() {
Container parent = getParent();
if (parent instanceof JPopupMenu) {
JPopupMenu menu = (JPopupMenu) parent;
engine.stop();
}
super.removeNotify();
}
#Override
public void addNotify() {
super.addNotify();
Container parent = getParent();
if (parent instanceof JPopupMenu) {
JPopupMenu menu = (JPopupMenu) parent;
engine.restart();
}
}
}
public interface TimingListener {
public void timingEvent();
}
public class AnimationEngine {
private Timer fade;
private float alpha;
private long startTime;
private long duration = 1000;
private List<TimingListener> listeners;
public AnimationEngine() {
listeners = new ArrayList<>(5);
fade = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
long elapsed = System.currentTimeMillis() - startTime;
if (elapsed >= duration) {
((Timer) e.getSource()).stop();
alpha = 1f;
} else {
alpha = (float) elapsed / (float) duration;
}
fireTimingEvent();
}
});
fade.setRepeats(true);
fade.setCoalesce(true);
fade.setInitialDelay(500);
}
public void addTimingListener(TimingListener listener) {
listeners.add(listener);
}
public void removeTimingListener(TimingListener listener) {
listeners.add(listener);
}
protected void fireTimingEvent() {
for (TimingListener listener : listeners) {
listener.timingEvent();
}
}
public void restart() {
fade.stop();
alpha = 0;
fireTimingEvent();
startTime = System.currentTimeMillis();
fade.start();
}
public float getAlpha() {
return alpha;
}
public void stop() {
fade.stop();
}
}
}
While this works on Windows, I'd be concerned that it might not work on other platforms, as the means by which the menus are generated are controlled (in part) by the UI delegate. This could become very messy, very quickly
start a timer to fire an event to fade in
I've been wondering if for example:
JTextPane chatTextArea = new JTextPane();
s.replaceAll(":\\)", emoticon());
public String emoticon(){
chatTextArea.insertIcon(new ImageIcon(ChatFrame.class.getResource("/smile.png")));
return "`";
}
can put a picture and a "`" everywhere ":)" is found. When I run it like this if s contains a ":)" then the whole s gets replaced just by the icon.
Is there a way to do it?
Here is a small example I made (+1 to #StanislavL for the original), simply uses DocumentListener and checks when a matching sequence for an emoticon is entered and replaces it with appropriate image:
NB: SPACE must be pressed or another character/emoticon typed to show image
import java.awt.Dimension;
import java.awt.Image;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.Utilities;
public class JTextPaneWithEmoticon {
private JFrame frame;
private JTextPane textPane;
static ImageIcon smiley, sad;
static final String SMILEY_EMOTICON = ":)", SAD_EMOTICON = ":(";
String[] emoticons = {SMILEY_EMOTICON, SAD_EMOTICON};
private void initComponents() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textPane = new JTextPane();
//add docuemntlistener to check for emoticon insert i.e :)
((AbstractDocument) textPane.getDocument()).addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(final DocumentEvent de) {
//We should surround our code with SwingUtilities.invokeLater() because we cannot change document during mutation intercepted in the listener.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
StyledDocument doc = (StyledDocument) de.getDocument();
int start = Utilities.getRowStart(textPane, Math.max(0, de.getOffset() - 1));
int end = Utilities.getWordStart(textPane, de.getOffset() + de.getLength());
String text = doc.getText(start, end - start);
for (String emoticon : emoticons) {//for each emoticon
int i = text.indexOf(emoticon);
while (i >= 0) {
final SimpleAttributeSet attrs = new SimpleAttributeSet(doc.getCharacterElement(start + i).getAttributes());
if (StyleConstants.getIcon(attrs) == null) {
switch (emoticon) {//check which emtoticon picture to apply
case SMILEY_EMOTICON:
StyleConstants.setIcon(attrs, smiley);
break;
case SAD_EMOTICON:
StyleConstants.setIcon(attrs, sad);
break;
}
doc.remove(start + i, emoticon.length());
doc.insertString(start + i, emoticon, attrs);
}
i = text.indexOf(emoticon, i + emoticon.length());
}
}
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
}
});
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(new Dimension(300, 300));
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {//attempt to get icon for emoticons
smiley = new ImageIcon(ImageIO.read(new URL("http://facelets.com/media/catalog/product/cache/1/image/9df78eab33525d08d6e5fb8d27136e95/e/m/emoticons0001.png")).getScaledInstance(24, 24, Image.SCALE_SMOOTH));
sad = new ImageIcon(ImageIO.read(new URL("http://zambia.primaryblogger.co.uk/files/2012/04/sad.jpg")).getScaledInstance(24, 24, Image.SCALE_SMOOTH));
} catch (Exception ex) {
ex.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JTextPaneWithEmoticon().initComponents();
}
});
}
}
References:
How to add smileys in java swing?
I want to have the user press a button to kick off a background thread.
While the thread is processing, I want two things to happen:
1) A WAIT_CURSOR should be displayed.
2) The application should not respond to mouse events.
As per the setCursor documentation "This cursor image is displayed when the contains method for this component returns true for the current cursor location, and this Component is visible, displayable, and enabled. ".
I want my application to be disabled while this background thread is processing.
Any ideas how to get the functionality I want?
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class WaitCursor extends JFrame
{
private static final long serialVersionUID = 1L;
public WaitCursor()
{
setResizable(false);
setName(getClass().getSimpleName());
setTitle("My Frame");
setSize(300, 300);
getContentPane().add(new MyButtonPanel());
}
private class MyButtonPanel extends JPanel
{
private static final long serialVersionUID = 1L;
public MyButtonPanel()
{
JButton btnStart = new JButton("Start");
btnStart.addActionListener(new BtnStartActionListener());
add(btnStart);
}
private class BtnStartActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
// Change to WAIT_CURSOR
Component root = SwingUtilities.getRoot((JButton) e.getSource());
JOptionPane.showMessageDialog(root, "Wait 10 seconds");
root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed
root.setEnabled(false);
new Thread(new TimeKiller(root)).start();
}
}
}
private class TimeKiller implements Runnable
{
Component _root;
public TimeKiller(Component root)
{
_root = root;
}
public void run()
{
try
{
Thread.sleep(10 * 1000);
}
catch (InterruptedException e)
{
// Ignore it
}
// Change back to DEFAULT CURSOR
JOptionPane.showMessageDialog(_root, "Done waiting");
_root.setCursor(Cursor.getDefaultCursor());
_root.setEnabled(true);
}
}
private static void createAndShowGUI()
{
// Create and set up the window.
WaitCursor frame = new WaitCursor();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
});
}
}
One way to disable it is to use the glass pane to block mouse input.
For example:
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import javax.swing.*;
#SuppressWarnings("serial")
public class WaitCursor2 extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private JComponent glassPane;
private JButton runBackgroundProcBtn;
private JTextArea textarea = new JTextArea(15, 30);
public WaitCursor2(JComponent glassPane) {
this.glassPane = glassPane;
glassPane.setFocusable(true);
glassPane.addMouseListener(new MouseAdapter() {
}); // so it will trap mouse events.
add(new JTextField(10));
add(runBackgroundProcBtn = new JButton(new AbstractAction(
"Run Background Process") {
#Override
public void actionPerformed(ActionEvent arg0) {
runBackgroundProcessAction();
}
}));
add(new JScrollPane(textarea));
}
private void runBackgroundProcessAction() {
disableSystem(true);
glassPane.setVisible(true);
new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
long sleepTime = 5000;
Thread.sleep(sleepTime);
return null;
}
#Override
protected void done() {
disableSystem(false);
}
}.execute();
}
public void disableSystem(boolean disable) {
glassPane.setVisible(disable);
runBackgroundProcBtn.setEnabled(!disable);
if (disable) {
System.out.println("started");
glassPane.requestFocusInWindow(); // so can't add text to text components
glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
} else {
System.out.println("done");
glassPane.setCursor(Cursor.getDefaultCursor());
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("WaitCursor2");
WaitCursor2 mainPanel = new WaitCursor2((JComponent) frame.getGlassPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
The glass pane will trap mouse events if it set visible and given a MouseListener. It will lose t his ability if it is set invisible. Likewise it will pull the caret from text components if you make it focusable and give it focus.
added a field current_active and at method actionPerformed, do a simple check. Albeit it is not perfect but for simple app, i think this do the trick. A crude way of solving your two requirement. :-) Hope it works for you too.
import java.awt.Component;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class WaitCursor extends JFrame
{
private static boolean current_active = false;
public WaitCursor()
{
setResizable(false);
setName(getClass().getSimpleName());
setTitle("My Frame");
setSize(300, 300);
getContentPane().add(new MyButtonPanel());
}
private class MyButtonPanel extends JPanel
{
public MyButtonPanel()
{
JButton btnStart = new JButton("Start");
btnStart.addActionListener(new BtnStartActionListener());
add(btnStart);
}
private class BtnStartActionListener implements ActionListener
{
// change to wait_cursor
public void actionPerformed(ActionEvent e)
{
if (!current_active)
{
Component root = SwingUtilities.getRoot((JButton) e.getSource());
JOptionPane.showMessageDialog(root, "Wait 10 seconds");
root.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// TODO: Disabling the root component prevents the WAIT_CURSOR from being displayed
//root.setEnabled(false);
current_active = true;
new Thread(new TimeKiller(root)).start();
}
}
}
}
private class TimeKiller implements Runnable
{
Component m_root;
public TimeKiller(Component p_root)
{
m_root = p_root;
}
#Override
public void run()
{
try
{
Thread.sleep(10 * 1000);
}
catch (InterruptedException e)
{
//Ignore it
}
// Change back to DEFAULT CURSOR
JOptionPane.showMessageDialog(m_root, "Done waiting");
m_root.setCursor(Cursor.getDefaultCursor());
current_active = false;
}
}
// create and setup the window.
public static void createAndShowGUI()
{
WaitCursor frame = new WaitCursor();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
try
{
createAndShowGUI();
}
catch (Exception e)
{
e.printStackTrace();
System.exit(0);
}
}
});
}
}