Swing - windowStateChanged event trouble - java

I have a JFrame where some elements (one, for now) have to be centered manually on the contentPane when resizing the window or changing the window state. Resizing event (componentResized) works fine but the windowStateChanged event is causing problems because it doesn't seem to "update" the contentPane's new size properly - it keeps the previous value. This can be seen by simply printing the result of getSize called on contentPane.
Centering is done by programmatically changing the constraint of the component (using putConstraint, SpringLayout). The issue is that getWidth used in that method returns "wrong" values which results in an uncentered component.
Maybe another listener is needed here?
Additional info: Eclipse with WindowBuilder, Linux Mint 15
Any kind of advice is appreciated.
addWindowStateListener(new WindowStateListener()
{
public void windowStateChanged(WindowEvent e)
{
System.out.println(contentPane.getSize()); // returns old size
tfArrayPanelCenter();
}
});
public void tfArrayPanelCenter()
{
int padding = (contentPane.getWidth()
- tfArrayPanel.getPreferredSize().width - HGAP) / 2;
sl_contentPane.putConstraint(SpringLayout.WEST, tfArrayPanel, padding,
SpringLayout.WEST, contentPane);
}
As requested I'm posting more code - a simple game of hangman. I think the JFrame constructor should be enough (other stuff is non-GUI):
/**
* Create the frame.
*/
public MainWindow()
{
addWindowStateListener(new WindowStateListener()
{
// no "#Override" was generated but it is the same with it
public void windowStateChanged(WindowEvent e)
{
System.out.println("EVENT: " + contentPane.getSize() + ", "
+ getExtendedState() + ", " + e.getOldState()); // amusingly, states are actually correct - interchanging between 0 (Frame.NORMAL) and 6 (Frame.MAXIMIZED_BOTH) when I maximize and "unmaximize"
tfArrayPanelCenter();
}
});
addComponentListener(new ComponentAdapter()
{
#Override
public void componentResized(ComponentEvent e)
{
tfArrayPanelCenter();
}
});
setTitle("Hangman");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 790, 620);
setLocationRelativeTo(null);
GameMechanics.setMainWindow(this);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
sl_contentPane = new SpringLayout(); // I've declared this as a field, it is normally generated as a local variable
contentPane.setLayout(sl_contentPane);
newGame = new JButton("New Game");
newGame.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
newGame.setVisible(false);
lblGame.setVisible(true);
lblGame.setBtnHintStatus(true);
lblGame.setLblTriesLeftCountText(Integer
.toString(GameMechanics.TRIES));
lblGame.paint(triesLeft);
inputChars = new ArrayList<Character>();
GameMechanics.loadWord();
initControls(GameMechanics.getGuessingWord().length());
lblTest.setText(GameMechanics.getGuessingWord().toUpperCase());
}
});
newGame.setFont(new Font("Tempus Sans ITC", Font.BOLD, 12));
sl_contentPane.putConstraint(SpringLayout.NORTH, newGame, 10,
SpringLayout.NORTH, contentPane);
sl_contentPane.putConstraint(SpringLayout.WEST, newGame, 10,
SpringLayout.WEST, contentPane);
newGame.setPreferredSize(new Dimension(100, 40));
newGame.setFocusPainted(false);
contentPane.add(newGame);
tfArrayPanel = new JPanel();
sl_contentPane.putConstraint(SpringLayout.SOUTH, tfArrayPanel, -10,
SpringLayout.SOUTH, contentPane);
sl_contentPane.putConstraint(SpringLayout.WEST, tfArrayPanel, 400,
SpringLayout.WEST, contentPane);
contentPane.add(tfArrayPanel);
tfArrayPanel.setLayout(new FlowLayout(FlowLayout.CENTER, HGAP, VGAP));
lblTest = new JLabel("New label");
sl_contentPane.putConstraint(SpringLayout.NORTH, lblTest, 15,
SpringLayout.NORTH, contentPane);
sl_contentPane.putConstraint(SpringLayout.WEST, lblTest, 416,
SpringLayout.WEST, contentPane);
contentPane.add(lblTest);
lblGame = new GameLabels(); // custom JPanel imported into the Palette and used from there on the MainWindow
sl_contentPane.putConstraint(SpringLayout.SOUTH, lblGame, -60,
SpringLayout.SOUTH, contentPane);
sl_contentPane.putConstraint(SpringLayout.WEST, lblGame, 10,
SpringLayout.WEST, contentPane);
lblGame.setPreferredSize(new Dimension(315, 130));
lblGame.setLayout(null);
lblGame.setVisible(false);
lblGame.setMainWindow(this);
contentPane.add(lblGame);
}

"Any kind of advice is appreciated."
Not sure if it fully fits your requirements, but if all you want to do is keep a set of components constantly centered (no matter size of the containing frame), as comments pointed out, you can just wrap everything in a GridBagLayout
import java.awt.GridBagLayout;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class CenteringWithGridBag {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JPanel gridBagPanel = new JPanel(new GridBagLayout());
gridBagPanel.setBorder(new TitledBorder("JPanel with GridBagLayout"));
JPanel innerPanel = new JPanel();
innerPanel.setBorder(new TitledBorder("JPanel Wrap"));
innerPanel.add(new JButton("Button"));
gridBagPanel.add(innerPanel);
JFrame frame = new JFrame("GridBagLayout Test");
frame.add(gridBagPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}

I don't think you need WindowStateListener for this because whenever you maximize or minimize or get the window in normal state the componentResized is called. Just remove the WindowStateListener and it works fine. You said componentResized is working for you, then you probably don't need WindowStateListener
addComponentListener(new ComponentAdapter()
{
#Override
public void componentResized(ComponentEvent e)
{
tfArrayPanelCenter();
}
});

Upon reading kleopatra's suggestion I approached the problem in another way. All I've done was putting the EAST constraint too (there were only WEST and SOUTH before) on the JPanel that needed to be centered. JPanel's FlowLayout handles the actual centering of the elements located within it.
To be honest, this doesn't truly answer the question itself but it is a solution to my troubles regarding the centering of components. Good enough, I guess.

Related

Java Swing Pixels Being Inaccurate

I am designing a Java app with Swing, and I have trouble designing the GUI without a layout.
My purpose is to design a GUI with one JPanel and four JButtons. I've done the math to set buttons and panel on the right place and coded like the following:
import java.awt.*;
import javax.swing.*;
public class MainFrame extends JFrame {
public MainFrame() {
this.setTitle("Example Frame");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
JPanel randomPanel = new JPanel();
randomPanel.setOpaque(true);
randomPanel.setBackground(Color.RED);
randomPanel.setBounds(10, 10, 430, 530);
JButton addButton = new JButton("Add");
addButton.setBounds(10, 550, 100, 40);
addButton.setBackground(Color.GRAY);
JButton deleteButton = new JButton("Delete");
deleteButton.setBounds(120, 550, 100, 40);
deleteButton.setBackground(Color.GRAY);
JButton refreshButton = new JButton("Refresh");
refreshButton.setBounds(230, 550, 100, 40);
refreshButton.setBackground(Color.GRAY);
JButton devButton = new JButton("Developer");
devButton.setBounds(340, 550, 100, 40);
devButton.setBackground(Color.GRAY);
this.add(randomPanel);
this.add(addButton);
this.add(deleteButton);
this.add(refreshButton);
this.add(devButton);
this.setSize(900, 600);
this.setResizable(false);
this.setVisible(true);
}
public static void main(String[] args) {
new MainFrame();
}
}
Following to the code, the components are expected to be placed as following:
However, the actual form was displayed as following:
The components exceed the form, which does not match with the expected look.
What is the problem of this and what should be done for an accurate placement of components?
There are two main problems...
setLayout(null)
setSize
What you've not taken into account is the fact that the amount of space available to the content of the window, is the size of the window MINUS the frame decorations.
Pixel perfect layouts are an illusion in modern UI development and are best avoided.
You could have a look at:
What's wrong with the Null Layout in Java?
Why is it frowned upon to use a null layout in Swing?
Why null layout and absolute positions are bad practice in Java Swing?
for more details.
A better solution is to make use one or more available layout managers. The example below simply makes use of BorderLayout and GridLayout with the help of EmptyBorder to provide some padding
See Laying Out Components Within a Container for more details
Benefits
Adaptable layout:
The example uses pack to "pack" the window around the content, automatically, without you having to adapt your code to the currently running OS (or frame decorations provided by different look and feels)
The user can change the size of the window and the content will resize automatically - bonus to the user.
The layout will adapt to the user's system settings, so if they are using a font larger then you've designed for, it won't completely blow up in your face
Want to add more buttons? No worries, knock yourself out, just add more buttons, the layout will adapt automatically, no need to "pixel push" ever component on the screen
Runnable example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
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(10, 10, 10, 10));
add(new SizablePane(430, 530));
JPanel buttonPane = new JPanel(new GridLayout(1, 3, 20, 0));
buttonPane.setBorder(new EmptyBorder(10, 0, 0, 0));
buttonPane.add(new JButton("Add"));
buttonPane.add(new JButton("Delete"));
buttonPane.add(new JButton("Refresh"));
buttonPane.add(new JButton("Developer"));
add(buttonPane, BorderLayout.SOUTH);
}
}
public class SizablePane extends JPanel {
private Dimension size;
public SizablePane(int width, int height) {
size = new Dimension(width, height);
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return size;
}
}
}
Need to add more buttons? Easy...
JPanel buttonPane = new JPanel(new GridLayout(1, 0, 20, 0));
buttonPane.setBorder(new EmptyBorder(10, 0, 0, 0));
buttonPane.add(new JButton("Add"));
buttonPane.add(new JButton("Delete"));
buttonPane.add(new JButton("Refresh"));
buttonPane.add(new JButton("Developer"));
buttonPane.add(new JButton("Some"));
buttonPane.add(new JButton("More"));
buttonPane.add(new JButton("Buttons"));
I'm quite late, I don't think this will be helpful to OP anymore... But to anyone else in the same situation.
As others mentioned, when you setSize on a JFrame, that includes the title bar and borders. There's a way to get the size values for those, but... If you want to lay things out manually in your content pane, why not prepare a content pane first, then add it to the JFrame?
class MainPanel extends JPanel {
public MainPanel() {
setLayout(null);
setPreferredSize(new Dimension(900, 600));
// JFrame will have some layouting going on,
// it won't listen to setSize
JPanel randomPanel = new JPanel();
randomPanel.setOpaque(true);
randomPanel.setBackground(Color.RED);
randomPanel.setBounds(10, 10, 430, 530);
JButton addButton = new JButton("Add");
addButton.setBounds(10, 550, 100, 40);
addButton.setBackground(Color.GRAY);
JButton deleteButton = new JButton("Delete");
deleteButton.setBounds(120, 550, 100, 40);
deleteButton.setBackground(Color.GRAY);
JButton refreshButton = new JButton("Refresh");
refreshButton.setBounds(230, 550, 100, 40);
refreshButton.setBackground(Color.GRAY);
JButton devButton = new JButton("Developer");
devButton.setBounds(340, 550, 100, 40);
devButton.setBackground(Color.GRAY);
this.add(randomPanel);
this.add(addButton);
this.add(deleteButton);
this.add(refreshButton);
this.add(devButton);
}
public static void main(String[] args) {
JFrame mainFrame = new JFrame();
mainFrame.setTitle("Example Frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setContentPane(new MainPanel());
mainFrame.pack();
mainFrame.setResizable(false);
mainFrame.setVisible(true);
}
}
If you mess with JFrame directly you're sort of bypassing the component system. Whereas this way, you're doing components just fine! Now, you have a JFrame fit to a single child panel, which has some things laid out manually.
This is how I normally do things, in such a situation.
P.S. "Don't lay things out manually, just use layout managers" is not something you can apply everywhere. You may need custom components sometimes, especially for something like a video game, where you have a game screen that you're custom rendering. Inside the game screen, you would be doing manual layout. They can coexist just fine, as long as you know which is which.
You need to override the getInsets() method of the underlying JFrame.
#Override
public Insets getInsets() {
return new Insets(0, 0, 0, 0);
}
Take a look at this question for more information.

JPanel not showing when added to JFrame

I am creating a GUI in java. Currently i have an empty JFrame and am trying to add a JPanel to it. The JPanel contains buttons, text etc. However none of this is being displayed. My code is as follows:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class memoDisplayUI {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JTextArea jTextBox = new JTextArea();
JScrollPane scroll = new JScrollPane();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
memoDisplayUI frame = new memoDisplayUI();
frame.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public memoDisplayUI() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame.getContentPane().setBackground(new Color(255, 255, 255));
frame.getContentPane().setLayout(null);
frame.setBounds(100, 100, 270, 400);
frame.setUndecorated(true); //REMOVES MENU BAR
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel lblMemos = new JLabel("MEMOS");
lblMemos.setForeground(new Color(100, 149, 237));
lblMemos.setFont(new Font("Moire", Font.BOLD, 30));
lblMemos.setBounds(16, 16, 234, 37);
panel.add(lblMemos);
JButton button = new JButton("");
button.setBackground(new Color(100, 149, 237));
button.setBounds(7, 350, 40, 40);
panel.add(button);
button.setIcon(new ImageIcon("back.png"));
JButton button_1 = new JButton("");
button_1.setBackground(new Color(100, 149, 237));
button_1.setBounds(113, 350, 40, 40);
panel.add(button_1);
button_1.setIcon(new ImageIcon("Edit.png"));
JButton button_2 = new JButton("");
button_2.setBackground(new Color(100, 149, 237));
button_2.setBounds(220, 350, 40, 40);
panel.add(button_2);
button_2.setIcon(new ImageIcon("memo.png"));
JButton btnExit = new JButton("");
btnExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
btnExit.setBorder(null);
btnExit.setIcon(new ImageIcon("Exit.jpg"));
btnExit.setBounds(216, 19, 40, 40);
panel.add(btnExit);
jTextBox = new JTextArea();
scroll.setViewportView(jTextBox); // add scroll panel
jTextBox.setTabSize(4);
jTextBox.setLineWrap(true);
jTextBox.setBackground(new Color(192, 192, 192));
jTextBox.setBounds(8, 60, 255, 286);
panel.add(jTextBox);
frame.getContentPane().add(panel);
}
}
Could someone please advise as to why this is?
Thanks very much :)
Edit
From a few tweaks to the code, it appears this is the desired layout (in a non-resizable GUI).
I think you used null to get a "place it wherever fits"? Then use a FlowLayout
frame.setLayout(new FlowLayout());
That should fix it :)
Could someone please advise as to why this is?
Using null layouts and not calling pack().
The image I edited into the question was obtained as a screenshot of the GUI after I had commented out the call to setUndecorated(true) and dragged it a little bigger. Doing so causes the JRE to validate the component structure (what pack() would do) and thereby make the components appear.
As I mentioned in a comment:
..a better question would be "How to layout this GUI?" (so long as you provide an attempt)
And that leads me to my first comment. (Now in longer form)
Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. To organize the components for a robust GUI, instead use layout managers, or combinations of them1, along with layout padding & borders for white space2.
So coming back to:
(so long as you provide an attempt)
Look over those two examples to see how they work, then attempt to combine some layouts and padding to create a frame that can then be packed to reduce to the natural size.
And a tip the the JTextArea. Suggest a size in columns x rows combined with the Font size.
1: You should never call setLayout(null).
2: Try frame.validate() to layout the components with your layout.
Replace
frame.getContentPane().setLayout(null);
with
frame.getContentPane().setLayout(new BorderLayout());
Good luck.
Edit: For future reference, to decide which LayoutManager should be used in your case, you should refer to this Visual Guide to LayoutManagers.
Just remove/comment this line from the above code at line number 46.
// frame.getContentPane().setLayout(null);
It should work fine..
Maybe you shoul replace :
frame.getContentPane().add(panel);
by
frame.setContentPane(panel);
Hope it helped

Adding vertical spacing to NORTH component in BorderLayout

I have a JFrame with a BorderLayout. I added a JPanel to the NORTH side of the JFrame. In this panel I want to add components to it in an absolute positioning. In the Center side of the JFrame I added another JPanel which should take a huge space. However when I run the application I see nothing from the North JPanel as the Center JPanel occupied all the space of the JFrame! How can I give vertical space to the North JPanel?
I really need to used absolute positioning for the north JPanel.
Here's my code:
public class AAAA extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
AAAA frame = new AAAA();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public AAAA() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1136, 520);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.NORTH);
panel.setLayout(null);
JButton btnNewButton = new JButton("New button");
btnNewButton.setBounds(0, 0, 117, 29);
panel.add(btnNewButton);
JPanel panel_1 = new JPanel();
contentPane.add(panel_1, BorderLayout.CENTER);
}
}
Update 1
I see you have already selected an answer (prematurely, I think). Here is the first iteration of what I believe you are trying to achieve. Without need for setting bounds or preferred sizes..
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class AAAA extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
AAAA frame = new AAAA();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public AAAA() {
super("Laid Out");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// OMG! If you can make a GUI break at 1336 px wide, it should be
// possible to make it break at ..much smaller!
//setBounds(100, 100, 1136, 520);
setBackground(Color.YELLOW);
contentPane = new JPanel();
contentPane.setBackground(Color.BLUE);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
// make it a FlowLayout as FlowLayout.LEADING with no spacing to
// make the button snug up against the top left
JPanel panel = new JPanel(
new FlowLayout(FlowLayout.LEADING, 0, 0));
panel.setBackground(Color.GREEN);
contentPane.add(panel, BorderLayout.NORTH);
//panel.setPreferredSize(new Dimension(1024,400));
JButton btnNewButton = new JButton("New button");
// we change the margin to make the button bigger than natural size.
btnNewButton.setMargin(new Insets(6, 22, 6, 22));
panel.add(btnNewButton);
JPanel panel_1 = new JPanel();
// create a solic color image to both pad the GUI and
// provide visual indication of where it is.
BufferedImage bi = new BufferedImage(
400,200,BufferedImage.TYPE_INT_RGB);
JLabel padder = new JLabel(new ImageIcon(bi));
panel_1.add(padder);
panel_1.setBackground(Color.RED);
contentPane.add(panel_1, BorderLayout.CENTER);
pack();
setMinimumSize(getSize());
}
}
I really need to used absolute positioning for the north JPanel.
Why? If we know why you think you need to do this we can probably offer a better approach.
Don't use a null layout. Swing was designed to be used with layout managers.
The BorderLayout will respect the preferred height of the component added to the NORTH. The preferred height is zero so nothing is displayed.
Note: I am not suggesting that you set the preferred height of the panel, that is the job of the layout manager and that is why you should always use a layout manager. Layout managers do more than just set the size/location of a component.

Java strechable JTextfield

I'm currently working on a browser in Java. I want to have a back button on the top left and to its right a JTextfield with the URL. I want the button to always have the same size but the textfield to change it's width to match the JFrame's width. It doesn't work with BorderLayout and I've tried this:
SpringLayout sl = new SpringLayout();
setLayout(sl);
sl.putConstraint(SpringLayout.WEST, back, 5, SpringLayout.WEST, this);
sl.putConstraint(SpringLayout.NORTH, back, 5, SpringLayout.NORTH, this);
sl.putConstraint(SpringLayout.WEST, addressBar, 5, SpringLayout.EAST, back);
sl.putConstraint(SpringLayout.NORTH, addressBar, 5, SpringLayout.NORTH, this);
sl.putConstraint(SpringLayout.SOUTH, back, 25, SpringLayout.NORTH, this);
sl.putConstraint(SpringLayout.SOUTH, addressBar, 25, SpringLayout.NORTH, this);
sl.putConstraint(SpringLayout.EAST, addressBar, 5, SpringLayout.EAST, this);
add(back);
add(addressBar);
where "back" is a JButton and addressBar a JTextField. The button seems to work but the addressBar just doen't draw at all.
Any suggestions?
There are many ways to solve this, and one in fact involves BorderLayout by nesting JPanels. Put the button into a BorderLayout.WEST position of a BorderLayout using container, but the JTextField BorderLayout.CENTER in the same container, and then put that container into the main container BorderLayout.CENTER.
GridBagLayout could also solve this, but again, often the best/simplest solution will involve nesting JPanels (for your containers), each with its own layout manager.
Edit
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;
public class BrowserFoo {
private static void createAndShowGui() {
JPanel topPanel = new JPanel(new BorderLayout(2, 2));
topPanel.add(new JButton("Back"), BorderLayout.WEST);
topPanel.add(new JTextField(20), BorderLayout.CENTER);
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.add(Box.createRigidArea(new Dimension(400, 400)));
JFrame frame = new JFrame("BrowserFoo");
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();
}
});
}
}
Note that if you re-size this GUI, the textarea and button remain in proper location.

Transparent JPanel

I want to create a semi-transparent JPanel. I've done it by simply using RGBA value of color constructor but problem is when i m using event handling is not woking properly. My requirement is a semi transparent Jpanel when mouse enters it border of this panel became visible and if mouse exit the border shoud not visible. I have done this by following code but problem is its not working properly for transparent backgroud (RGBA) but it working fine for RGB color.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class MDCW extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MDCW frame = new MDCW();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MDCW() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1013, 551);
contentPane = new JPanel();
contentPane.setBackground(new Color(0, 139, 139));
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
final JPanel panel = new JPanel();
panel.setBackground(new Color(0, 0, 0,50));
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
panel.setBorder(new LineBorder(new Color(255, 255, 255), 5));
}
#Override
public void mouseExited(MouseEvent e) {
panel.setBorder(null);
}
});
panel.setBounds(360, 155, 215, 215);
contentPane.add(panel);
final JPanel panel_1 = new JPanel();
panel_1.setBackground(new Color(0, 0, 0));
panel_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
panel_1.setBorder(new LineBorder(new Color(255, 255, 255), 5));
}
#Override
public void mouseExited(MouseEvent e) {
panel_1.setBorder(null);
}
});
panel_1.setBounds(84, 155, 215, 215);
contentPane.add(panel_1);
}
}
JPanel does not support semi-transparent backgrounds. There are two steps needed to take care of this problem:
First, to have any correctly-functioning transparency at all, you must setOpaque(false) on the panel; otherwise you will have glitches, because an opaque panel is assumed to completely cover what is underneath its bounds.
However, when opaque is false, the panel also does not draw its background at all (!) so you will have to draw a background in paintComponent.
Here is a drop-in replacement class which will take care of both of these steps.
private class TransparentPanel extends JPanel {
{
setOpaque(false);
}
public void paintComponent(Graphics g) {
g.setColor(getBackground());
Rectangle r = g.getClipBounds();
g.fillRect(r.x, r.y, r.width, r.height);
super.paintComponent(g);
}
}
I’ve checked that it works in your program if I change the first panel creation to:
final JPanel panel = new TransparentPanel();
It's easy to do it like so:
// initialise JPanel
JPanel somePanel = new JPanel(new GridBagLayout());
somePanel.setBackground(new Color(0,0,0,x);
x in this case is the level of transparency you're looking for
0 being invisible, 100 being solid.
e.g:
somePanel.setBackground(new Color(0,0,0,55)
See:
http://docs.oracle.com/javase/7/docs/api/java/awt/Color.html
http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html

Categories

Resources