I created a JPopupmenu and i added a JTextField. When I am using metal or nimbus everything is alright. The problem is when I switch LookAndFeel to Windows. I can not press right ALT, because if I press this key, JPopupmenu will hide.
Can I use right ALT to write national signs in Windows LookAndFeel?
import javax.swing.*;
import java.awt.event.*;
public class Popup extends JFrame {
JPopupMenu popup;
JPanel panel;
JTextField field;
public Popup(){
setSize(500,400);
try {
//UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException | UnsupportedLookAndFeelException e1) {
e1.printStackTrace();
}
SwingUtilities.updateComponentTreeUI(this);
popup = new JPopupMenu();
field = new JTextField(10);
popup.add(field);
JButton button = new JButton("Options");
button.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
panel = new JPanel();
panel.add(button);
add(panel);
}
public static void main(String[] args){
Popup pop = new Popup();
pop.setVisible(true);
}
}
JPopupMenu has a very specific set of operation requirements, and yes, they do change between look and feels, that's kind of the point.
What you could do is create you own popup using an undecorated JFrame. The trick here is to mimic as much of the popup as need, for example, auto closer when another component gains focus, the ability to dismiss the popup with the escape key...etc...
This is just a quick example to provide a proof of concept, I'd personally also add a key binding for the escape key, some kind of listener interface to allow the search pane to request that the popup be dismissed and the ability to auto focus some component when the window was made visible, but that's just me...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestPopup {
public static void main(String[] args) {
new TestPopup();
}
public TestPopup() {
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 JButton show;
public TestPane() {
setLayout(new GridBagLayout());
show = new JButton("...");
show.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PopupWindow window = new PopupWindow();
window.show(show, 0, show.getHeight());
}
});
add(show);
}
}
public class SearchPane extends JPanel {
private JList list;
private JTextField search;
public SearchPane() {
setLayout(new BorderLayout());
list = new JList();
list.setPrototypeCellValue("This is just a test");
list.setVisibleRowCount(20);
search = new JTextField(10);
add(new JScrollPane(list));
add(search, BorderLayout.SOUTH);
}
}
public class PopupWindow extends JFrame {
private SearchPane searchPane;
public PopupWindow() {
setUndecorated(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowFocusListener(new WindowFocusListener() {
#Override
public void windowGainedFocus(WindowEvent e) {
}
#Override
public void windowLostFocus(WindowEvent e) {
dispose();
}
});
searchPane = new SearchPane();
add(searchPane);
pack();
}
public void show(JComponent parent, int x, int y) {
Point point = new Point(x, y);
SwingUtilities.convertPointToScreen(point, parent);
setLocation(point);
setVisible(true);
}
}
}
Related
I am adding multiple Jlabel using for loop. What I want is on mouse click, the color of the selected JLabel should change and set to the default color on click of anotherJLabel.
Since you changed the state of the label, you need someway to change it back. The simplest solution is to maintain a reference to the last label that was changed and when the new label is clicked, reset it's state
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
HighlightMouseListener hml = new HighlightMouseListener();
for (int index = 0; index < 10; index++) {
JLabel label = new JLabel("Hello " + index);
label.addMouseListener(hml);
add(label, gbc);
}
}
}
public class HighlightMouseListener extends MouseAdapter {
private JLabel previous;
#Override
public void mouseClicked(MouseEvent e) {
Component source = e.getComponent();
if (!(source instanceof JLabel)) {
return;
}
JLabel label = (JLabel) source;
if (previous != null) {
previous.setBackground(null);
previous.setForeground(null);
previous.setOpaque(false);
}
previous = label;
label.setForeground(Color.WHITE);
label.setBackground(Color.BLUE);
label.setOpaque(true);
}
}
}
I still wonder if a JList would be a better and simpler solution, but since I don't know what you're doing, it's all I can do
I have created a Swing interface where I want an icon to appear in a JLabel when the cursor is hovered over a button. The icon will change based in which button the cursor hovers over.
Here is the coding I am using at the moment:
public void iconchange()
{
if(btnPlay.isRolloverEnabled() == true)
{
lblIcon.setIcon(new ImageIcon("Images/Play-icon.png"));
}
}
I know the coding above is wrong, so what can I do to achieve the feature I mentioned above?
Use a ChangeListener on the JButton's ButtonModel to monitor changes to the models state, update your UI based on the state of the model, for example...
public class ChangeHandler implements ChangeListener {
private JLabel label;
private Icon armedIcon;
public ChangeHandler(JLabel label, Icon armedIcon) {
this.armedIcon = armedIcon;
this.label = label;
}
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isRollover()) {
label.setIcon(armedIcon);
} else {
label.setIcon(null);
}
}
}
This will update the supplied JLabel, changing it's icon to the specified icon when the ButtonModel it's attached to is in the rollOver state
This could be used something like this...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ButtonModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class RollOver {
public static void main(String[] args) {
new RollOver();
}
public RollOver() {
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 JLabel label;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
// I'm doing this, because I don't have blank icon of 128x128 and my
// icons are both 128x128
label = new JLabel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(128, 128);
}
};
add(label, gbc);
try {
JButton btn = new JButton("Bunnies");
btn.getModel().addChangeListener(new ChangeHandler(label, new ImageIcon(ImageIO.read(getClass().getResource("/Bunny.png")))));
add(btn);
btn = new JButton("Zomnies");
btn.getModel().addChangeListener(new ChangeHandler(label, new ImageIcon(ImageIO.read(getClass().getResource("/Zombi.png")))));
add(btn);
} catch (IOException exp) {
exp.printStackTrace();
}
}
public class ChangeHandler implements ChangeListener {
private JLabel label;
private Icon armedIcon;
public ChangeHandler(JLabel label, Icon armedIcon) {
this.armedIcon = armedIcon;
this.label = label;
}
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isRollover()) {
label.setIcon(armedIcon);
} else {
label.setIcon(null);
}
}
}
}
}
Take a closer look at How to Use Buttons, Check Boxes, and Radio Buttons for more details
Add an MouseListener to btnPlay, and use the mouse exit and enter methods
btnPlay.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
lblIcon.setIcon(new ImageIcon("Images/Play-icon.png"));
}
public void mouseExited(java.awt.event.MouseEvent evt) {
//I assume you want to remove or change the icon afterward
}
});
I need the frame to update and display how many times the Button has been pressed (the button's text to update)
If I can use actionPreformed() to be locked on to specific events (Button press, or the Menu item being pressed), then I think that should help...
Problems:
When Button is pressed it creates more frames
The existing Frame(s) do not update (I only want there to be one frame anyway)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class ButtonFrame implements InternalFrameListener, ActionListener
{
JFrame myFrame = null;
private int clicked;
final String F=("Clicked: "+clicked+" Times!");
public static void main(String[] a)
{
(new ButtonFrame()).test();
}
private void test()
{
myFrame = new JFrame("Internal Frame with a Button");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setSize(400,400);
myFrame.setContentPane(new JDesktopPane());
JMenuBar Start_Bar = new JMenuBar();
JMenu Start_Menu = new JMenu("Frame");
JMenuItem Start_Item = new JMenuItem("Start");
Start_Item.addActionListener(this);
Start_Menu.add(Start_Item);
Start_Bar.add(Start_Menu);
myFrame.setJMenuBar(Start_Bar);
myFrame.setVisible(true);
}
public void actionPerformed(ActionEvent Start_Item)
{
JInternalFrame f = new JInternalFrame("Button Frame");
f.setResizable(true);
f.setClosable(false);
f.setMaximizable(true);
f.setIconifiable(true);
f.setSize(200,200);
f.setLocation(100,100);
f.addInternalFrameListener(this);
f.setVisible(true);
Button objButton1;
objButton1=new Button ("Clicked: "+clicked+" Times!");
objButton1.setBounds(20,90,40,50);
f.add(objButton1);
objButton1.addActionListener(this);
myFrame.getContentPane().add(f);
}
public void actionPreformed(ActionEvent objButton1)
{
clicked++;
}
public void internalFrameActivated(InternalFrameEvent e)
{
System.out.println("Internal Button Ready");
}
public void internalFrameClosed(InternalFrameEvent e)
{
System.out.println("Internal frame closed");
}
public void internalFrameClosing(InternalFrameEvent e)
{
System.out.println("Internal frame closing");
}
public void internalFrameDeactivated(InternalFrameEvent e)
{
System.out.println("Internal frame deactivated");
}
public void internalFrameDeiconified(InternalFrameEvent e)
{
System.out.println("Internal frame deiconified");
}
public void internalFrameIconified(InternalFrameEvent e)
{
System.out.println("Internal frame iconified");
}
public void internalFrameOpened(InternalFrameEvent e)
{
System.out.println("Internal frame opened");
}
}
Based on your description, you solution is screaming isolation and separation of code responsibility, the code responsible for managing the button should be separated from the code managing the frame and desktop pane
This way, you can use separate ActionListeners as well as isolate the functionality to a single instance of the button class
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JDesktopPane dp = new JDesktopPane();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar Start_Bar = new JMenuBar();
JMenu Start_Menu = new JMenu("Frame");
JMenuItem Start_Item = new JMenuItem("Start");
Start_Item.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JInternalFrame f = new JInternalFrame("Button", true, true, true, true);
f.setSize(200, 200);
f.setLocation(100, 100);
f.add(new ButtonPane());
f.setVisible(true);
dp.add(f);
}
});
Start_Menu.add(Start_Item);
Start_Bar.add(Start_Menu);
frame.setJMenuBar(Start_Bar);
frame.add(dp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ButtonPane extends JPanel {
private JButton button;
private int count = 0;
public ButtonPane() {
setLayout(new GridBagLayout());
button = new JButton("0");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
count++;
button.setText(Integer.toString(count));
}
});
add(button);
}
}
}
Example below will display a button with jframe window. I want only button visible, how can it be implement?
public final void initUI() {
JPanel panel = new JPanel();
getContentPane().add(panel);
panel.setLayout(null);
JButton quitButton = new JButton("Quit");
quitButton.setBounds(50, 60, 80, 30);
quitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
panel.add(quitButton);
setTitle("Quit button");
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
Depending on what you mean by "with out jframe or jpanel visible?" you create a transparent window...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GhostButton {
public static void main(String[] args) {
new GhostButton();
}
public GhostButton() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JButton ghostButton = new JButton("Boo!");
ghostButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
frame.setBackground(new Color(0,0,0,0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(ghostButton);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
If you remove frame.setBackground(new Color(0,0,0,0));, you will get a frameless window
ps- This works under Java 7+, there is trick to make it work under Java 6, but I've not posted it here
I am trying to create a button panel where the button that was clicked becomes 'differently colored'; i.e show the background image. p.s I only need this approach(with 2 images), and not anything else. Thanks !
Eg:
public class TestPane extends JPanel {
private BufferedImage imgUnclicked;
private BufferedImage imgClicked;
private Point mousePoint;
public TestPane() {
try {
imgUnclicked = ImageIO.read(new File("C:\\Users\\Me\\Desktop\\tmp\\Uncolored.png"));
imgClicked = ImageIO.read(new File("C:\\Users\\Me\\Desktop\\tmp\\Colored.png"));
} catch (IOException ex) {
Logger.getLogger(Spotlight.class.getName()).log(Level.SEVERE, null, ex);
}
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
mousePoint = e.getPoint();
repaint();
}
});
}
}
#Override
protected void paintComponent(Graphics g) {
//Draw imgClicked
//Draw imgUnclicked with some rectangular area around mouse click subtracted
}
}
No need to reinvent the wheel. Instead use a JToggleButton (appropriately configured). A button will react to both mouse and keyboard input.
import java.awt.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.*;
class ChangeImageOnClick {
public static void main(String[] args) throws Exception {
URL url1 = new URL("http://i.stack.imgur.com/gJmeJ.png");
final Image img1 = ImageIO.read(url1);
URL url2 = new URL("http://i.stack.imgur.com/wCF8S.png");
final Image img2 = ImageIO.read(url2);
Runnable r = new Runnable() {
#Override
public void run() {
JToggleButton btn = new JToggleButton("Click me!");
btn.setIcon(new ImageIcon(img1));
btn.setSelectedIcon(new ImageIcon(img2));
btn.setContentAreaFilled(false);
btn.setBorderPainted(false);
JOptionPane.showMessageDialog(null, btn);
}
};
SwingUtilities.invokeLater(r);
}
}
A different idea. Basically, load an image into a JLabel, set the Layout of the label and add two opaque components to it.
By using a simple MouseListener, you can either make the component invisible or transparent based on your needs...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class HideAndShow {
public static void main(String[] args) {
new HideAndShow();
}
public HideAndShow() {
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 {
public TestPane() {
setLayout(new BorderLayout());
try {
BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/Haibane_Miho___Take_2_by_garrbage.png"));
JLabel label = new JLabel(new ImageIcon(img.getScaledInstance(-1, 200, Image.SCALE_SMOOTH)));
add(label);
label.setLayout(new GridLayout(2, 1));
JPanel top = new JPanel();
top.add(new JLabel("Top"));
JPanel bottom = new JPanel();
bottom.add(new JLabel("Bottom"));
MouseAdapter ma = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
((JPanel)e.getComponent()).setOpaque(false);
repaint();
}
};
top.addMouseListener(ma);
bottom.addMouseListener(ma);
label.add(top);
label.add(bottom);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
Add an ActionListener to your button and call setIcon with the imgClicked.
Something like this:
JButton btn = new JButton();
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
btn.setIcon(imgClicked);
}
});