I am using Java, and trying to make my JFrame's size as the size of the window, not to overlap the taskbar. Off-course, I want it to be the exact same size at every screen resolution. Moreover, to make the frame.GetContentPane() size as the size of the frame. Later I will want to create JPanels within the frmae at a constant size.
I have seen many solution, but unfortunately, non of them work for me.
Please help! Thank you very very much.
JFrame frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
Here is an example, how to set window size to maximum (may be incorrect when computer has more than one display).
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class TestWindow {
/**
*
* #param args
*/
public static void main(String[] args) {
JFrame frm = new JFrame("Test max size");
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setSize(
GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().getSize());
frm.setVisible(true);
}
}
Another possibilities are: make frame maximized or use fullscreen mode. Content pane gets the maximum size automatically.
Related
I often use:
setLocationRelativeTo(null);
In my JFrame Constructor to make the Frame appear right in the middle, but now it doesnt works. It just puts the JFrame in one corner.
If you have any idea of what this happens or if you now another way to always making the Jframe appear at the middle in any computer please tell me.
I said this because I could use
setLocation(x,y);
and just put the coordinates that will put the Jframe in the center of my screen but, for example if my PC is 1920 x 1080 the Jframe wont appear in the center in a 1280 x 720 PC.
If Im wrong in this please correct me, Im new to Java so I can miss a lot of things Bill Gates wont miss. (I now windows is not coded in Java)
For reference, here's an example that works correctly; you might compare it to your current approach. In particular,
Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
Be sure to pack() the enclosing top-level container.
Invoke setVisible(true) as the last step in creating the GUI.
MCVE:
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
/** #see https://stackoverflow.com/a/29643591/230513 */
public class Test {
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JLabel("Test", JLabel.CENTER));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new Test().display();
});
}
}
When I create my GUI I use a cardlayout to hold my different panels as I'm sure many know. This sets my screen to the width and height of my largest panel. This causes problems with the aesthetics of my first to screens, which are much smaller than SudokuPanel and CalkuroPanel.
I have tried setting the preferred size when I change to the larger screens, but to no avail.
Any help with links to good info or anything that will just generally help would be greatly appreciated :).
Please find my main class (where I draw the GUI) below:
import java.awt.*; import javax.swing.*; import java.util.*;
public class puzzleGUI{
private static JPanel screens;
public static String username;
static public void main (String[] args){
JFrame puzzle = new JFrame ("Sudoku/Calkuro Pro");
...
PuzzleStartPanel startPanel = new PuzzleStartPanel();
PuzzleChoosePanel choosePanel = new PuzzleChoosePanel();
PuzzleSudokuPanel sudokuPanel = new PuzzleSudokuPanel();
PuzzleCalkuroPanel calkuroPanel = new PuzzleCalkuroPanel();
screens = new JPanel(new CardLayout());
screens.add(startPanel, "start");
screens.add(choosePanel, "choosePuzzle");
screens.add(sudokuPanel, "sudoku");
screens.add(calkuroPanel, "calkuro");
screens.setPreferredSize (new Dimension(250, 80));
puzzle.setJMenuBar(menuBar);
puzzle.getContentPane().add(screens);
puzzle.pack();
puzzle.setVisible(true);
puzzle.setResizable(false);
puzzle.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
}
static public void getUsername(String str){
username = str;
}
static public void openWindow(String newFrame){
CardLayout cl = (CardLayout)(screens.getLayout());
cl.show(screens, newFrame);
}
}
Edit
brainblast tried to pack the frame after resetting the preferred size when openWindow is called, and wolah, new frame size :D
static public void openWindow(String newFrame, int a, int b){
CardLayout cl = (CardLayout)(screens.getLayout());
cl.show(screens, newFrame);
screens.setPreferredSize (new Dimension(a, b));
puzzle.pack();
}
can i set the size of individual panels in a cardlayout
Certainly. But the layout will ignore them and make every card the same size. The best you can hope for is to add the smaller panels to another panel (with a layout) that allows the content to shrink.
This answer shows this technique using a single label. Swap the label for the 'small panels' and using the layouts on the right, it will be centered.
I had a similar problem and I resolved it by a little cheat ("dirty code").
I had two panels: SmallOne and HugeOne. I set visibility of HugeOne to false. In this case the SmallOne sets the size of whole CardPanel. You can make a method that is called when user selects HugeOne panel and in this method you put HugeOne visibility on true. And CardPanel will resize.
Works like a charm :)
I'm having a problem that when my frame is shown (after a login dialog) the buttons are not on correct position, then in some miliseconds they go to the right position (the center of the panel with border layout).
-- update
In my machine, this SSCCE shows the layout problem in 2 of 10 times I run it:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TEST {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.out.println("Debug test...");
JPanel btnPnl = new JPanel();
btnPnl.add(new JButton("TEST"));
JFrame f = new JFrame("TEST");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(btnPnl);
f.setPreferredSize(new Dimension(800, 600));
f.pack();
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.setVisible(true);
System.out.println("End debug test!");
}
});
}
}
The button first appers in the up-left, and then it goes to the center. Is it a java bug?
--update
Looks like the SSCCE don't show the problem for everyone that is trying.
Maybe it's my computer performance problem. I still think Java Swing is creating new threads for make the layout behind the scenes. But I'm not sure.
--update
The problem only occur with the f.setExtendedState(JFrame.MAXIMIZED_BOTH);
Your problem intrigued me. After some investigation I think I confirmed something that I recall about setting the window state (maximized, restored, etc) which is that setting the state is a request to the operating system and is left to the whim of the OS to process the request. This means it is asynchronous, or at least done later, after you set it. I confirmed using logging and adding resize listeners where you can see that the frame is resized after your block of code exits. Because of this, the pack() will layout components to their preferred size. So imagine the frame being sized to 800x600 and components positioned as such (button centered horizontally around 400). Then later, the OS changes the size of the frame to full screen (e.g. 1024x768) - for a moment, you'll see the button still at 400. Then the frame processes the new size and re-lays out components and centers the button at around 512. So you'll see the flicker as it transitions during this process. Perhaps a solution is to NOT pack() - it will remain at a size of zero and user will see minimum flicker.
Try this change first:
// pack()
If that looks good then you might have the next problem...if the user clicks the restore button, the whole frame shrinks into a black hole. So try calling pack AFTER the frame has been predictably resized due to the maximize. Something like this:
f.addComponentListener( new ComponentAdapter( ComponentEvent e ) {
public void componentResized( Component) {
if( f.getSize().getWidth() > 0 ) {
e.getComponent().removeComponentListener( this );
((JFrame)e.getComponent()).pack();
}
}
}
So if the user later clicks restore button the frame will have a nicely packed size ready to go.
--Update
OK, one last attempt. While I think my description of the problem has some truth, my solutions offered did nothing. Here's one last attempt. Remove pack() and setPreferredSize() and replace with setting the size to the screen size. This seems to reduce the flicker greatly on my system. This is because there should be no difference between the initial layout and the maximized layout done later. You can see this if you switch between restore and maximized. Although I still see a very slight flicker when switching the two, at least it seems to look better when first displayed.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TEST {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
System.out.println("Debug test...");
JPanel btnPnl = new JPanel();
btnPnl.add(new JButton("TEST"));
JFrame f = new JFrame("TEST");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(btnPnl);
// f.setPreferredSize(new Dimension(800, 600));
// f.pack();
f.setSize( Toolkit.getDefaultToolkit().getScreenSize() );
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.setVisible(true);
System.out.println("End debug test!");
}
});
-Mike
Maybe you are missing a frameThatContainsCentralPanel.pack()?
Well, if it works with a SSCCE, then you've proven the problem isn't with the basic logic. There must be something different between the SSCCE and your real code. Since we don't have access to your real code you need to do the debugging yourself to see what the difference is.
However, in this case a better solution is to use a CardLayout, which is designed to let you swap panels easily. Read the Swing tutorial for a working example.
Or anther approach is to use a "login dialog". Once the login is successfull, you display your main frame with the panel for your application.
I would guess that you need to call pack() before making your frame visible.
If you are calling the above code not on the event thread then you have a race condition and all bets are off - you can only manipulate the GUI from the EDT (event dispatch thread).
EDIT: I tried your SSCCE on my system and it is not exhibiting the behavior you are seeing. I tried it about 50 times, and also tried creating 10 windows by looping your code. I am running 1.6.0_18 on Windows XP SP3.
The "then in some milliseconds" part sounds to me like you need to call validate() on your frame. Also, if you use f.pack(), your panel needs a preferred size, because pack() gives the parent's components their preferred sizes and resizes based on them.
If I copied your code, I had the same problem, but not so heavy.
I solved it by setting a preferred size for your frame before packing. So:
import java.awt.Dimension;
System.out.println("Debug test...");
JPanel btnPnl = new JPanel();
btnPnl.add(new JButton("TEST"));
JFrame f = new JFrame("TEST");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(btnPnl);
f.setPreferredSize(new Dimension(800, 600));
f.pack();
f.setVisible(true);
System.out.println("End debug test!");
I'm running on Linux.
It is indeed strange... I'm sure it is something about the size of all the containers in the swing tree.
I would expect the frame to be maximised both before it is shown, but after checking this I'm sure that on linux frame is maximised after it has been displayed. You can make the frame size equal to a Screen size before calling setVisible, or you can make the components invisible until you know that the it's got preferred initial size. Here is modified sample which shows the elements after the frame has been activated (on linux activated event comes late enough to not show the "jumping button"):
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TEST {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
final JPanel btnPnl = new JPanel();
btnPnl.add(new JButton("TEST"));
final JFrame f = new JFrame("TEST");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(btnPnl);
// calculate preferred size for TEST frame
// f.isDisplayable() will become true
f.pack();
// extended state, if can be applied, needs to be called after f.isDisplayable()
WindowListener maxBoth = new WindowAdapter() {
#Override
public void windowOpened(WindowEvent e) {
f.setExtendedState(Frame.MAXIMIZED_BOTH);
}
};
// after windows has been opened - maximize both
f.addWindowListener(maxBoth);
// initially hide the elements
// after maximized state has been applied show them
f.getContentPane().setVisible(false);
f.addWindowListener(new WindowAdapter() {
#Override
public void windowActivated(WindowEvent e) {
f.getContentPane().setVisible(true);
// remove this listener
f.removeWindowStateListener(this);
}
});
// set the frame visible
f.setVisible(true);
}
});
}
}
Looks like a java bug. I've reported it (but for some reason it still not show on the bugs reports).
This code, when run, will make a window but not at the specified dimensions. What is wrong with it?
import javax.swing.*;
import java.awt.*;
public class Windowing {
void JFrame(){
JFrame frames = new JFrame("Total recall");
frames.setSize(1000,8000);
frames.setVisible(true);
frames.pack();
//Buttons push = new Buttons();
//((Buttons) push).buttons();
JTextField wager = new JTextField(1);
wager.setSize(100,200);
wager.setVisible(true);
wager.setLocation(100, 200);
frames.add(wager);
//frames.add(push);
}
}
You could remove the call to frames.pack(); it overrides the previously set frame size.
However, what you really want to do is remove the frames.setSize(1000,8000) and move frames.pack() down to the bottom of the method; that will ensure that the frame is big enough to display its contents but not too big to fit on the screen.
If you call pack before adding anything to the frame (like you are doing now), it will make the window extremely small; it's probably appearing near the upper left of your screen, but you won't notice it unless you know where to look.
It looks like you have a number of "opportunity areas" here.
To start, it seems like you set frame size to 1000x8000 because you didn't see any change right?
Secondly you call setVisible on the textField because you didn't see that either.
And finally you're setting the size of the textfield ( I guess because you're seeing it take the whole frame )
The problem here is that you have to invoke pack and setVisible at the end of the construction. Also, you have to learn how to use layout managers and frames.
Swing, is very powerful, but it is a bit hard to grasp at the beginning.
These two links will be helpful:
How to make frames
Using Layout Managers
I've changed your code and the result looks like this:
Here's the modified source code.
import javax.swing.*;
import java.awt.*;
public class Windowing {
public static void main( String [] args ) {
Windowing windowing = new Windowing();
windowing.showFrame();
}
void showFrame(){
JFrame frame = new JFrame("Total recall");
JButton push = new JButton("Push");
JTextField wager = new JTextField(15);
// Panels do have "FlowLayout"
JPanel panel = new JPanel();
panel.add(wager);
panel.add(push);
frame.add( panel );
frame.pack();
frame.setVisible(true);
}
}
Try to use setPreferredSize(Dimension) instead.
I need to change the direction of the growth of JTextField object when more characters are added to it. Currently when I add more stuff to it, it grows from left to right but I need this growth of the bounds of the JTextField from right to left.
For e.g. when I add "StackOverflow" to this JTextField the o/p is,
<empty space>StackOverflow
but I want,
StackOverflow<empty space>
Can you guys help me with this? I tried setHorizontalAlignment. But it doesnt work.
Thanks for any help.
EDIT : Added SSCCE for better explanation.
import java.awt.Container;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class JTextFieldExample {
public static void addComponentsToPane(Container pane) {
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
JTextField transitionEditorJTextField = new JTextField("StackOverFlow");
pane.add(transitionEditorJTextField);
System.out.println("If I add text to JTextFiled notice that it grows towards Right - which is normal. "
+ "But I want it to grow towards left.");
JButton button = new JButton("Button.I.Am");
pane.add(button);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("BoxLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
textField.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
I'm not sure I understand your question. Normally you create a JTextField with code like:
JTextField textField = new JTextField(10);
This gives the text field a fixed preferred size which is respected depending on the layout manager being used.
It sounds like you are doing something like:
JTextField textField = new JTextField();
In which case I don't think the text field has a size. Can you even add character to it? Well maybe the solution in this case is to add a ComponentListener to the text field and keep track of the original size. Every time the size changes you change the location of the text field by the difference in the size. Again this may or may not work depending on the layout manager.
If you need more help post your SSCCE showing the problem.