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
Related
I have frame with JFormattedTextField(s). My simplified code can look like:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100,100);
frame.setLayout(new GridLayout(2,2));
JFormattedTextField field1 = new JFormattedTextField(NumberFormat.getInstance());
field1.setValue(0.4);
frame.add(new JLabel("value A"));
frame.add(field1);
JFormattedTextField field2 = new JFormattedTextField(NumberFormat.getInstance());
field2.setValue(0.8);
frame.add(new JLabel("value B"));
frame.add(field2);
frame.setVisible(true);
which generates:
Goal
When I click/focus on any of JFormattedTextField I would like it to automatically place caret at the end
Problem
I tried using following solutions before calling frame.setVisible(true); but none of them seems to work
from How to set AUTO-SCROLLING of JTextArea in Java GUI?
field1.setCaretPosition(field1.getDocument().getLength());
from https://tips4java.wordpress.com/2008/10/22/text-area-scrolling/ ((DefaultCaret)field2.getCaret()).setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
Works without issue for me....
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
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.JTextField;
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;
JTextField textField = new JTextField("This is a test");
add(textField, gbc);
JButton button = new JButton("This is a button");
add(button, gbc);
button.setFocusable(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (textField.getCaretPosition() != 0) {
textField.setCaretPosition(0);
} else {
textField.setCaretPosition(textField.getText().length());
}
textField.requestFocusInWindow();
}
});
}
}
}
Provide a runnable example which doesn't work if you still have issues
Update with JFormattedTextField....
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
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;
JFormattedTextField textField = new JFormattedTextField("This is a test");
textField.setValue(0.8d);
add(textField, gbc);
JButton button = new JButton("This is a button");
add(button, gbc);
button.setFocusable(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (textField.getCaretPosition() != 0) {
textField.setCaretPosition(0);
} else {
textField.setCaretPosition(textField.getText().length());
}
textField.requestFocusInWindow();
}
});
}
}
}
Updated with "set at beginning"
Okay, I just want to point out that I have personally dislike of JFormattedTextField, it does a lot of "things" at times which don't always make sense.
An "old" trick I've used, when implementing a "auto select all on focus gain", is to offload the request to the end of the Event Dispatching Thread, this places the request AFTER all the "funky stuff" that the JFormattedTextField does when the field becomes focused...
JFormattedTextField textField = new JFormattedTextField("This is a test");
textField.setValue(0.8d);
add(textField, gbc);
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent arg0) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
textField.setCaretPosition(textField.getText().length());
}
});
}
});
Yes, I'm serious ...
package swingtraining;
import static java.awt.Color.BLACK;
import static java.awt.Color.RED;
import java.awt.EventQueue;
import static java.awt.Font.BOLD;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
public class JFrameWithAButton extends JFrame {
public JFrameWithAButton(){
setSize(400,400);
setTitle("Swing is hard");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String args[]){
JPanel Jp1 = new JPanel();
Jp1.setOpaque(true);
Jp1.setBackground(RED);
JButton Jbt = new JButton();
Jbt.setLayout(null);
Jbt.setSize(200,200);
Jbt.setBounds(new Rectangle(new Point(200, 200)));
Jbt.setText("Hello!");
EventQueue.invokeLater(new Runnable(){
public void run(){
JFrameWithAButton ex = new JFrameWithAButton();
ex.setVisible(true);
ex.add(Jp1);
Jp1.add(Jbt);
}
});
}
}
Sorry if the code's a bit mom's spaghetti-esque, but I just can't crack this cookie >.> Even with layout set to null it doesn't move. Any suggestions of how I get this JButton to not only move to the middle of the window but also grow 200 by 200 pixels?
Any suggestions of how I get this JButton to not only move to the middle of the window but also grow 200 by 200 pixels?
I can think of a few, none of which use null layouts
GridBagConstraints
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 javax.swing.JButton;
import javax.swing.JFrame;
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.ipadx = 200;
gbc.ipady = 200;
add(new JButton("Hello"), gbc);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
JButton#setMargin
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.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
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();
JButton btn = new JButton("Hello");
btn.setMargin(new Insets(100, 100, 100, 100));
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
EmptyBorder
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
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 BorderLayout());
setBorder(new EmptyBorder(50, 50, 50, 50));
JButton btn = new JButton("Hello");
add(btn);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
You could use combination of them, maybe using an EmptyBorder and GridBagConstraints to further constrain the layout.
The great benefit of these examples, is, for the most part, if the font size changes or the rendering requirements for the fonts change, the layout is capable of compensating
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
And because it's always a fun read, Why is it frowned upon to use a null layout in SWING?
if you wanna define any component size manually you have to set the mother component's layout: null
so you have to set Jframe layout null to define Jpanel size and location
then you have to set JPanel layout null to define Jbutton size and location in it
final JPanel Jp1 = new JPanel();
Jp1.setOpaque(true);
Jp1.setBackground(RED);
Jp1.setLayout(null);
final JButton Jbt = new JButton();
// Jbt.setLayout(null); not needed!
Jbt.setBounds(10, 10, 100, 40);
// Jbt.setBounds(new Rectangle(new Point(200, 200))); not in this style
Jbt.setText("Hello!");
Jp1.add(Jbt);
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrameWithAButton ex = new JFrameWithAButton();
ex.setVisible(true);
ex.add(Jp1);
}
});
don't forget to define size and location both when you are adding a component in a null layout Jpanel or Jframe and ...
For some reason, when I run "frame.setBackground(new Color(1.0f,1.0f,1.0f,0.0f));", then change my button's icon and repaint (even with paintImmediately) the icon of my button refuses to change. Just commenting out that line has it working again, but I kinda want that to work.
public static void main (String[] args) throws Exception
{
robot = new Robot();
frame = new JDialog();
frame.setUndecorated(true);
frame.setSize(59,61);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice defaultScreen = ge.getDefaultScreenDevice();
Rectangle rect = defaultScreen.getDefaultConfiguration().getBounds();
int x = (int) rect.getMaxX() - frame.getWidth() - 17;
int y = (int) rect.getMaxY() - frame.getHeight() - 40;
frame.setLocation(x, y);
frame.setAlwaysOnTop(true);
frame.setBackground(new Color(1.0f,1.0f,1.0f,0.0f));
panel = new JPanel(new BorderLayout());
panel.setBackground(new Color(1.0f,1.0f,1.0f,0.0f));
frame.add(panel);
InputStream in = HelloWorld.class.getResourceAsStream("/Working/mic2.png");
notRecording = new ImageIcon(ImageIO.read(in));
in = HelloWorld.class.getResourceAsStream("/Working/mic3.png");
recording = new ImageIcon(ImageIO.read(in));
button = new JButton(notRecording);
button.setContentAreaFilled(false);
button.setBorder(BorderFactory.createEmptyBorder());
panel.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
try
{
record();
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println("Exception");
}
}
});
frame.setVisible(true);
}
When I later run
button.setIcon(recording);
button.paintImmediately(button.getBounds());
Nothing happens.
Edit:
I've read over the other thread, and checked the answer they provided, but I can't seem to find any other source that verifies SWING can't handle alpha values, and in fact most sources recommend it. Additionally, calling setOpaque according to setOpaque(true/false); Java seems to imply that using setOpaque is a much more complex concept than just transparency. Additionally, replacing setBackground with setOpaque doesn't work, so I don't think the thread should be closed due to the other thread covering a similar material.
Here's an example of what isn't working for me. In theory, this would leave just the text, or at least only the section that the button occupies of the dialog remaining visible, with the rest not opaque.
import javax.swing.*;
import java.awt.*;
public class RunnableExample
{
public static void main(String[] args)
{
JDialog dialog = new JDialog();
dialog.setUndecorated(true);
dialog.setSize(59,61);
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.setAlwaysOnTop(true);
dialog.getRootPane().setOpaque(false);
JPanel panel = new JPanel();
panel.setOpaque(false);
dialog.add(panel);
JButton button = new JButton("test");
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setOpaque(false);
panel.add(button);
dialog.setVisible(true);
}
}
To make a window transparent, you must use setBackground (on an instance of window class, like JFrame or JDialog) and pass it a transparent color (new Color(0, 0, 0, 0))`), this is the ONLY time you can use a alpha based color on a Swing component.
Swing doesn't know how to paint components with a alpha based color, it only knows how to deal with fully transparent or fully opaque components, which is controlled via setOpaque, for example...
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
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();
}
JDialog dialog = new JDialog();
dialog.setUndecorated(true);
dialog.setBackground(new Color(0, 0, 0, 0));
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.setAlwaysOnTop(true);
dialog.getRootPane().setOpaque(false);
JPanel panel = new JPanel();
panel.setOpaque(false);
dialog.add(panel);
JButton button = new JButton("test");
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setOpaque(false);
panel.add(button);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
});
}
}
I can further prove it by adding
panel.setBorder(new CompoundBorder(new LineBorder(Color.RED), new EmptyBorder(10, 10, 10, 10)));
to the code, which produces
The red line is actually the output of the frame (technically the panel, but for this, it's the same thing)
And because there's something wrong with the button/icons...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
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();
}
JDialog dialog = new JDialog();
dialog.setUndecorated(true);
dialog.setBackground(new Color(0, 0, 0, 0));
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.setAlwaysOnTop(true);
dialog.getRootPane().setOpaque(false);
JPanel panel = new JPanel();
panel.setOpaque(false);
dialog.add(panel);
try {
JButton button = new JButton(new ImageIcon(ImageIO.read(getClass().getResource("/play.png"))));
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setOpaque(false);
panel.add(button);
panel.setBorder(new CompoundBorder(new LineBorder(Color.RED), new EmptyBorder(10, 10, 10, 10)));
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
try {
button.setIcon(new ImageIcon(ImageIO.read(getClass().getResource("/record.png"))));
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
});
}
}
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);
}
}
}
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);
}
}
}