Basically I want to control the size of the content pane even when the application is in full-screen exclusive mode. I want the content to be square, with black bars taking up unused space. Is there a way to do this? Setting the preferred size doesn't work, it just fills the screen anyway. Here's the gist of my code:
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground(Color.BLACK);
setPreferredSize(Toolkit.getDefaultToolkit().getScreenSize());
setUndecorated(true);
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
getContentPane().setPreferredSize(new Dimension(getHeight(), getHeight()));
getContentPane().setBackground(Color.WHITE);
pack();
This results in the entire screen being white. On my widescreen monitor, I want the middle of the screen to be white, with black bars on the sides. Is there a clean way to do this? I guess I could add a secondary JPanel, size it correctly, and use that for everything, but that seems sloppy. I'd rather use the JFrame's built-in content pane.
Related
I want to add JLabels to JFrame directly. I don't want use JPanel. But I have a position problem. I set layout as null.
I tryed draw line to see what's going on.
#Override
public void paint(Graphics g){
g.setColor(Color.red);
g.drawLine(0, 31, super.getWidth(), 31);
}
And the zero is actually 31.
Drawing screenshot
Why? And how can I fix that?
I want to add JLabels to JFrame directly. I don't want use JPanel.
If you're adding the JLabel "to the JFrame" then you're adding it to the contentPane which is almost always a JPanel, so 99% of the time, you're still using a JPanel, even without trying to.
But I have a position problem. I set layout as null.
Which is almost always a bad thing to do. This makes for GUI's that don't work on all platforms, fighting against the Java philosophy and structure.
And the zero is actually 31.
Why? And how can I fix that?
Because of the top part of the JFrame is taken up by the OS window's menu bar. The contentPane, starts 31 pixels below the top of the JFrame (in your case -- different for different OS's and screen resolutions).
Best to avoid drawing directly on the JFrame, which is actually composed of many sub-components -- the content pane, the root pane, the glass pane,... and instead draw within the paintComponent method of a JPanel that you either add to the contentPane or make as the contentPane. Then 0,0 is the top left of the usable portion of your main window.
Also, please elaborate more on the underlying reason why you're trying to avoid use of a JPanel. Your issue may in fact be an XY Problem type issue.
Positions in a JFrame are relative to the edge of the window, not the content pane. To get the dimensions of the content pane, use getContentPane().getWidth() and getContentPane().getHeight().
I've been using Java Swing for quite some time now and I never found a solution to this problem. When I create a JFrame the window surrounding it is actually smaller than the frame. In the included picture below my JFrame size is 800x600. The 2 white lines crosses at the center of the frame, 400,300. As you can see they are not at the center of the window. If I stretch the window right and down I can see some of the black background of the frame was hidden. When the black background is revealed you can see the the lines do indeed cross at the center (2nd picture).
Why is it working like that? Anything I can do to solve this problem? Im making a game where the playable character is in the center of the screen so this causes me a lot of problem. The 1st image is larger because i've left the code in the background. As we can see it's a standard JFrame creation.
Not centered because part of the frame is hidden:
centered when frame is fully revealed:
my JFrame size is 800x600
You are doing things backward.
The frame has decorations (ie. the title bar and borders). The panel where you do the painting is added to the frame, so therefore it will be less than the size of the frame.
The proper approach is to override the getPreferredSize() method of the JPanel where you do the custom painting to return the desired size of the panel.
Then you add the panel to the frame you invoke the pack() method on the frame. Now the frame will be sized slightly larger (to fit the complete panel and the frame decorations) and your painting will be accurate.
I have a setup that usually works, but I'm finding it a bit of a pain at the moment.
I have a JDialog (formerly a JFrame, but I've changed the UI flow recently to remove redundant JFrames) set to BorderLayout that contains three main JPanels, header, content and footer.
The header JPanel has a background image that is loading fine. However, I'm calling all manner of setMinimumSize / setPreferredSize / etc (I even tried setSize and setBounds out of desperation) and the JPanel isn't being sized correctly. The layout for that component is BoxLayout, and the children sit comfortably within it, but that shouldn't affect what I'm trying to do with the header panel itself.
The only thing that works is setting a size on the parent JDialog. But I don't want to do that / from what I've read it seems like bad design. I'd also have to maths out the potential width / height of all the children, add the margins, etc.
Advice I am not looking for: "use a different LayoutManager."
I want to understand if there's a reason for the child components not being respected.
I can provide code, but isolating a small, runnable segment is difficult given the amount of interlocked systems I'm juggling. Here is the relevant snippet to set the size of the JPanel. The image dimensions are 480 * 96.
public JPanelThemed(BufferedImage image) {
super();
this.backgroundImage = image;
setAllSimilarConstraints(new Dimension(image.getWidth(), image.getHeight()));
setOpaque(false);
}
// for use with BoxLayout as it requires explicit bounds to be set
public void setAllSimilarConstraints(Dimension dim) {
setPreferredSize(dim);
setMinimumSize(dim);
setMaximumSize(dim);
}
I would implement it a bit another way - to ensure that preferred/min/max/Size can not be changed from elsewhere:
public JPanelThemed(BufferedImage image) {
this.backgroundImage = image;
setOpaque(false);
}
public Dimension getPreferredSize() {
return new Dimension(this.backgroundImage.getWidth(), this.backgroundImage.getHeight());
}
If I don't define dimensions, how do I ensure the whole background I'm painting is displayed?
You could use a JLabel to display the ImageIcon. The size of the label will be the size of the image. You then set the layout manager of the label so you can add components to it.
Edit:
do you know why it's commonly-recommended to subclass JPanel when painting backgrounds in Java
When you use a JPanel the size of the panel is based on the components added to the panel and the layout manager you are using. Your custom painting code then needs to paint the image the way your want. That is you can paint the image from (0, 0), or you can center the image on the panel, you can scale the image to make it fit the pane, but the image in no way controls the size of the panel, unless you override the getPreferredSize() method of the panel to use custom code to base the size of the larger of the components or the image. So you are in full control.
When you use the JLabel approach suggested here, the size of the label is always the size of the image. Then components will be positioned based on the layout manager but can be truncated if the image is smaller than the space required by the components.
So based on your requirement that you want to make sure the entire image is displayed, I suggested the JLabel approach, since you don't need to write any custom code. I find this a simple approach when using popup non-resizable dialogs to display a background image and a few components and buttons to close the dialog.
You can also check out Background Panel which provides these common painting features in a reusable class.
Now what I am doing in my program is that I am using setundecorated = true and MAXIMIZED_BOTH So it makes it go full screen and the display looks very nice, But the problem is that there are images (border) on the left and the right side of my screen and also a blue background. What happens is that in changing screens and resolutions these get disturbed and are not shown properly. Those grey patches come up again
History:
I have a java program which I wanted to always open in full screen; I was not able to find a way to do it properly so I had adjusted the minimum to (1370, 727) and maximum size. Thus, it started opening properly on my laptop, but when I changed my laptop's display to LCD, it started giving problems:
It opens in a smaller window:
If I then click on the maximize button, a grey area comes on the side and bottom (I wanted the items on screen to get stretched or center themselves):
And here for example, there is a grey patch at the bottom. Instead, I want the background to cover the whole screen.
Update 1
If I change to stretchable gridbaglayout, this is the code I used and what happens:
Menu.setExtendedState(MAXIMIZED_BOTH);
GridBagLayout gbl = new GridBagLayout();
Menu.setLayout(gbl);
JButton component = new JButton("1");
gbl.layoutContainer(Menu);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.NONE;
gbl.setConstraints(component, gbc);
Menu.add(component);
Menu.pack();
Menu.setVisible(true);
Question
How do I set "this" frame to setExtendedState(MAXIMIZED_BOTH) as I have done to others? (if I do this in main function, I get an error; even if I make a function for this and call it in main I get an error)
How do I get everything to stretch/rearrange themselves according to the extra grey space?
Update 2
My files in this project:
Update 3
This is the current file I am working on "FormTTS.java"
Search for "MAXIMIZED_BOTH" in there and you will find the code I think you will want to check.
Usually, as far as games go, it's preferable to use full screen mode instead of using a maximized window. You can do this in Java by using:
GraphicsEnvironment gfxEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gfxDev = gfxEnv.getDefaultScreenDevice();
Window window = new GameWindow();
gfxDev.setFullScreenWindow(window);
If you still want to use a regular frame and center the content panel, you need to define some of the GridBagLayout constraints. It's impossible to tell which without out seeing the code for the rest of the components on that screen, but consider the following:
GridBagConstraints.fill
GridBagConstraints.anchor
GridBagConstraints.weightx
GridBagConstraints.weighty
And finally, regarding setting the screen to the largest size, it is already addressed here:
Java JFrame Size according to screen resolution
I am also having same requirement as you have, below code works for me.
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(0,0,d.width,d.height); // i assume you have extended JFrame
try this, hope it works for you as well.
MyFrame mFrame= new MyFrame();
mFrame.setVisible(true);
mFrame.setExtendedState(mFrame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
I know this is a terrible answer because I don't have time to write any code. Have you tried creating a listener so you can get the proper maximum size once the window is actually created, and then setting the GridBagConstraints weightx and weighty properties accordingly?
Did you try this code
JFrame frame = new JFrame();
frame.setSize(Toolkit.getDefaultToolkit().getScreenSize());
frame.setVisible(true);
You can get full screen size of any device by "Toolkit.getDefaultToolkit().getScreenSize()" in java. Above code I set frame size to fullscreen.
int height = Toolkit.getDefaultToolkit().getScreenSize().height;
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
You can get hight and width of screen to your code by using above codes. I think this will be a help.
You can easily call
setExtendedState(MAXIMIZED_BOTH); on jframe or
use bellow code to set screen size to any PC.
//size of the screen
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//height of the task bar
Insets scnMax = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
int taskBarSize = scnMax.bottom;
//available size of the screen
setSize(screenSize.width, screenSize.height - taskBarSize);
setLocation(screenSize.width - getWidth(), screenSize.height - taskBarSize - getHeight());
if u want you can remove taskbar size to get full screen anyway this is the code and this will help you.
Try setting image as a background to you JFrame. So it will adjust with frame size
How to set Jframe Background Image in GroupLayout Java
so even in full screen it will be adjusting..
if you use panel then you can resize according to panel, it shows in full panel size
yourinternalframe.setSize(mainPanel.getSize());
yourinternalframe.show();
this may be not seem as your real need, you may do something according to this
I took a look at the code that you attached for FormTTS.java, what I found out is that your screen was set as using the absolute layout hardcoded to some numbers of pixels.
Look at the following code:
Menu.getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
Menu.getContentPane().add(jPanel3, new org.netbeans.lib.awtextra.AbsoluteConstraints(420, 230, 530, 320));
Your JFrame is not using the GridBagLayout, instead it's using AbsoluteLayout from Netbeans library. So I guess you generated these UI codes with the tools from Netbeans.
And then regarding your picture that does not fill all the screen when maximized:
jLabel9.setIcon(new javax.swing.ImageIcon(getClass().getResource("/freetts/equations.png")));
Menu.getContentPane().add(jLabel9, new org.netbeans.lib.awtextra.AbsoluteConstraints(0, 0, 1530, 990));
Same problem here, it's hardcoded to some numbers of pixels.
If you want everything to be centered when you maximized your screen, I think the only way to do is to use the gridbag layout for your JFrame and this requires you to update almost everything in your code. And you will need to fully understand how GridBagLayout works. Here is the place to start.
However if you only want the background image to fill the screen you can follow the steps here to let the picture scaled to fill the size of JLabel:
Resize a picture to fit a JLabel
If it still doesn't work, you should also get the size of the screen (from one of the answers here) and then set the prefferedSize of the JLabel with those values in addition of scaling the image.
To add on to #eitanfar's answer, the best way of enabling fullscreen in Java is using the FSEM (FullScreen Exclusive Mode) API.
As he stated, this is achieved by setting the windows as fullscreen on the GraphicsDevice you want the window to appear fullscreen on, usually the default one. Even if your device does not support FSEM (id est isFullscreenSupported() returns false), setting the window as fullscreen will still partially work as the API will emulate fullscreen. The only safety check is to verify whether the GraphicsEnvironment is headless (isHeadless()). If it is, then there are no devices to display to.
The advantage FSEM gives you is that all graphics processing is run on the GPU (the GraphicsDevice is the GPU, not the monitor), therefore making it faster on most systems. In your program's options, you can allow the user to choose to enable or not FSEM so that they can run at optimal performance.
However, the system's repaint events are undefined when in FSEM, you're better off using active rendering, therefore you're better off ignoring repaint (setIgnoreRepaint(true)) and then using a custom thread for drawing.
I am having a similar problem with my application. the nearest I have come is to set all components that reside on top to either component.setOpaque(false), or component.setBackground(new Color(255,255,255,0)). you could also try panel.setVisible(false) for the unused panels.
its hard to offer up code with out the entire program but give this a whirl:
Menu.setBackground(new Color(255,255,255,0);
I'm having a problem, creating a fixed-size overall panel for a touchscreen GUI application that has to take up the entire screen. In a nutshell, the touchscreen is 800 x 600 pixels, and therefore I want the main GUI panel to be that size.
When I start a new GUI project in NetBeans, I set the properties of the main panel for min/max/preferred size to 800 x 600, and the panel within the 'Design' view changes size. However, when I launch the app, it is resized to the original default size.
Adding this code after initComponents() does not help:
this.mainPanel.setSize(new Dimension(800,600));
this.mainPanel.setMaximumSize(new Dimension(800,600));
this.mainPanel.setMinimumSize(new Dimension(800,600));
this.mainPanel.repaint();
I've peeked into all of the resource files and cannot seem to find values that would override these (which seems somewhat impossible anyway, given that I'm setting them after initComponents() does its work). I'm using the FreeDesign layout, because I wanted complete control over where I put things.
I suspect the layout manager is resizing things based upon how many widgets I have on the screen, because different prototyped screens come in at differing sizes.
Help is appreciated!
Have you tried java full screen mode?
I use this method to complete the task, not sure if its the best and you need to wait calling it until the frame is actually on the screen.
protected void growBig()
{
int screenWidth = java.awt.Toolkit.getDefaultToolkit().getScreenSize().width;
int screenHeight = java.awt.Toolkit.getDefaultToolkit().getScreenSize().height;
Rectangle rectangle = getFrame().getBounds();
rectangle.setSize(screenWidth, screenHeight);
getFrame().setBounds(0, 0, screenWidth, screenHeight);
getFrame().setSize(screenWidth, screenHeight);
getFrame().doLayout();
getFrame().validate();
updateUI();
}
I'm not sure how your touchscreen device works. But if you use Netbeans preview your panel is put in some outer container like JFrame/JWindow. And just maybe you set the frame to 800x600.
If so, then the problem might be that the frame eats a few pixels for its own border, leaving your panel size < 800x600. And in that case your panel will be unable to use your min/max settings and revert to default sizes.