Set resolution manually in Java Swing - java

I need a way to manually control/stretch the size of my whole GUI.
I have a 1400 x 1050 Desktop (native resolution) and I want to scale the resolution manually to 1024 x 1050 inside the code, because my application was written on/for a 1024 x 768 Desktop. So in general the whole frame and all buttons etc should be stretched / bigger as a whole and the relation should stay the same.
I can´t do it via Windows properties because the resolution in general needs to be 1400 x 1050 because of another application.
My approach was something like:
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
screenHeight = screenSize.height;
screenWidth = screenSize.width;
..and then change the screen size via setSize()? But I don´t understand how.
Java Tookit Screen Resolution - How can I use it?
..unfortunately the link in the answer here does not work anymore.
How to set resolution manually in Java Swing?

As mentioned in the comments, the best approach here is to fix the underlying code to not mandate a 1024 x 768 display. This is usually a very distinct code smell of front-end Java code. Proper use of Layout Managers can almost always get your display to function in a more flexible manner.
However, in industry, sometimes refactoring to get legacy components functioning properly is not a feasible effort. In such a case, I would propose that you treat the inflexible GUI you can't refactor as a component of a larger GUI that you can control.
Consider the following example code:
public static void main(String[] args) {
// Initialize the frame
JFrame myApp = new JFrame("App");
myApp.setSize(1400, 1050);
// Create container for the GUI
JPanel container = new JPanel(new BorderLayout());
container.setPreferredSize(new Dimension(1024, 768));
// Load the GUI into the container
JComponent myGui = new JPanel(); // Replace this with actual GUI.
myGui.setBackground(Color.RED); // Remove this once using actual GUI.
container.add(myGui, BorderLayout.CENTER);
// Create the frame's content pane
JPanel content = new JPanel(new FlowLayout(FlowLayout.CENTER));
content.setBackground(Color.BLUE); // Also remove this in production.
// Add GUI to content pane
content.add(container);
// Add content pane to frame, show frame
myApp.setContentPane(content);
myApp.setVisible(true);
}
This works because we've added the GUI to the CENTER of a BorderLayout panel (which will stretch the GUI to occupy the entire size of the panel in the absence of any components on the NORTH/SOUTH/EAST/WEST). We set the preferred size of that BorderLayout panel to be 1024 x 768 (IE: the size that the GUI is specified to work for), and then feed that panel into a FlowLayout panel (which will preserve the preferred size).
The result is that our 1400 x 1050 application contains a 1024 x 768 rendering of our GUI component (you can easily change this to 1024 x 1050 by modifying the preferred size of the panel containing the BorderLayout).
As an exercise to the user, you'll notice that the GUI code isn't centered vertically if you run this. This can be tackled by modifying the layout of the content panel.

Related

Obtain a JPanel's display area dimensions, Windows vs Mac

I have code that generates a JPanel that needs to run on both Mac OSX and Windows environments. I would like to draw a series of rectangles that frame the JPanel's display area. However the display area of the JPanels differs in the two environments. In the diagram below, the Mac JPanel is on the left and a Windows JPanel is on the right.
Is there a property that makes reference to the display area of a JPanel as opposed to its size?
The two JPanels in the diagram were made with the same code. In both cases I have the following command:
setSize(400, 400);
And in the override of paintComponent, the outermost rectangle (cut off in both in the vertical but only for Windows in the horizontal) is drawn as follows:
g2.drawRect(0, 0, 399, 399);
(The inner rectangles are displaced by an increment of 4 pixels and alternate in color. This isn't exactly what I hope to draw, but it illustrates the problem.)
I could manually determing the adjustments needed, and create separate constants for the two environments, but I'm wondering if there is something I've missed in Swing where it is possible to obtain the display size of a given JPanel. If such a function or property exists, making use of it would be cleaner and more flexible, as well as hedging against JPanels being given different title-bar sizes or padding settings.
In the paintComponent() method of your panel you use:
int width = getWidth();
int height = getHeight();
This will give you the current size of the panel whenever the component is repainted.

How to automatically resize JFrame if elements are too large?

I have been researching for 30 minutes on how to automatically resize a JFrame when the elements are too large. I am trying to fit line segments inside the JFrame but it always exceeds the space but does not automatically generate more space.
What should I do?
DrivePanel panel = new DrivePanel(aCar, coordinates);
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(600,600);
application.setVisible(true);
Example of output:
Some things to consider :
if you are doing custom painting on your panel, remember that the panel's size it's not changed by what you are drawing.
For example, if the "last" point (i mean the point with the biggest values of x and y) is drawn at (1000,1000) coordinates, you should set the preferred size of your panel in order to contain it.
To let your application using the preferred size of your components, you should call application.pack() (where application is your JFrame object) instead of setting size manually.
If your panel is too big to be displayed enterily on your screen, you might add it to a JScrollPane, and then add the scrollpane to your jframe (not the panel itself).
The scrollpane will automatically use scroll bars if your panel can't be fully displayed on your screen.
So consider this small example, based on your code :
DrivePanel panel = new DrivePanel(aCar, coordinates);
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(1000,1000)); // change 1000,1000 with the coordinates you need ...
JScrollPane scrollPane = new JScrollPane(panel);
application.add(scrollPane);
application.pack();
application.setVisible(true);
Hope this helps :)

The size of a JTextArea

I have a set of JPanel's within a JFrame. One of the panels contains a JTextArea. At the moment I create this like so:
JTextArea = new JTextArea(5, 40);
And this gives me a text area which is 5 rows by (roughly) 40 columns.
Vertically this works as I'd like it to, the area fills the entire height of the parent container - probably because the parent is the only element positioned in that row.
Horizontally the parent width is determined by elements underneath and it is (usually) wider than the JTextArea is. So I end up with a text area with large margins on either side. What is worse, when I resize the frame smaller to the point where the text area is exactly the width of the parent container, it suddenly 'flicks' and changes into a text area that is 1 row high and is then the width of the parent.
Excuse the crude drawing below which hopefully illustrates the issue.
In short: How to I create a JTextArea that always fills the maximum space available to it? (and if possible with a minimum width after which a scrollbar appears if the user sizes the frame even smaller)
In the parent container of the JTextArea (denoted as Panel 1 in your drawing), call the function:
panel1.setLayout(new BorderLayout());
For reference, see this documentation page:
https://docs.oracle.com/javase/7/docs/api/java/awt/BorderLayout.html
As you only have a single child in panel1, the BorderLayout layout manager of panel1 will by default stretch the text area to use all available space in the parent container.
You may want to take away the constructor parameters specifying the size of your TextArea. The BorderLayout should take care of sizes for you :)
You can request that Swing respects a certain minimum size for the text area by calling:
textArea.setMinimumSize(new Dimension(minimum_width, minimum_height));
You have to use layout manager, for start see oficial Oracle docu about layout managers. For your situation, BorderLayout or GridBagLayout should work fine.
Start with:
panel1.setLayout(new BorderLayout());
or
panel1.setLayout(new GridBagLayout());
With GridBagLayout you can more preciselly do layouting (with BorderLayout you have five areas - no more, no less). With GridBagLayout you can do more complicated layouts.

Center JFrame in combination with pack()

I'm trying to center a JFrame i used to pack(), and I got it, but I think it's not the clean way.
This is how I'm doing it atm:
JFrame window = new JFrame();
//filling
//window
//with
//stuff
window.pack();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int x = (dim.width - window.getPreferredSize().width) / 2, y = (dim.height - window.getPreferredSize().height) / 2;
window.setBounds(x, y, window.getPreferredSize().width, window.getPreferredSize().height);
I pack it after filling it to get the final PreferredSizes, so I can use those values in the setBounds method. But I don't like rebounding it after packing it.
Any better ideas?
To center a window in the screen you need to call window.setLocationRelativeTo(null) right after pack() call and before making your window visible:
JFrame window = new JFrame();
...
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
As per Window#setLocationRelativeTo(Component c) docs:
public void setLocationRelativeTo(Component c)
Sets the location of the window relative to the specified component
according to the following scenarios.
The target screen mentioned below is a screen to which the window
should be placed after the setLocationRelativeTo method is called.
If the component is null, or the GraphicsConfiguration associated with this
component is null, the window is placed in the center of the
screen. The center point can be obtained with the
GraphicsEnvironment.getCenterPoint method.
On the other hand
Some developers might advice you to use Window#setLocationByPlatform(boolean flag) instead of setLocationRelativeTo(...) in order to honor the default location for the native windowing system of the platform where your desktop application is running. This makes sense since your application must be designed to run in different platforms with different windowing systems and PLAFs.

Why will BoxLayout not allow me to change the width of a JButton but let me change the height?

I'm trying to get the Layout of a JDialog of mine to fit a particular look that a program in which I'm porting to Java has, I've used several LayoutManagers before with great success yet for some reason I cannot seem to get this working at all. My goal is to have the Right (East) side of the JDialog contain a "Find Next" and "Cancel" button in a top-down order and then any extra space below so that the two buttons are always at the top of the JDialog, yet for some reason BoxLayout is continously ignoring any attempts at changing (this is where I'm lost) the width of a JButton. Code follows.
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
cancel.setPreferredSize(new Dimension((int)findNext.getPreferredSize().getWidth(),
(int)cancel.getPreferredSize().getHeight()));
JPanel example = new JPanel();
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
example.add(cancel);
example.add(Box.createGlue());
No matter what I try, cancel always retains it's normal size. I've tried setMinimumSize() and setMaximumSize() with the same parameters as setPreferredSize with no luck. I've even tried cancel.setPreferredSize(new Dimension(500, 500)); and the buttons height was the only thing adjusted, it STILL retained the default width it was given.
To clear up any questions, here is what it looks like (now that I've finished it) and you'll see that the "Find Next" and "Cancel" buttons are not the same size.
I know this is an old question but I don't really see a good explanation. So for the sake of searchers that stumble upon this I will add my two cents.
There are three methods associated with sizing components in Swing: setPreferredSize(), setMinimumSize(), and setMaximumSize(). However, the important point is that it is up to the particular layout manager being used as to whether or not it honors any of these methods.
For BoxLayout (the layout the original poster is using):
setMinimumSize() -- BoxLayout honors this
setMaximumSize() -- BoxLayout honors this
setPreferredSize() -- if X_AXIS is being used width is honored, if Y_AXIS is being used height is honored
The OP is using a Y_AXIS BoxLayout which is why only his height was being changed.
Update: I put together a page with this same information for all of the layout managers. Hopefully it can help some searchers out: http://thebadprogrammer.com/swing-layout-manager-sizing/
You may not want Box.createGlue(), which "grows as necessary to absorb any extra space in its container." Instead, use Box.createVerticalStrut() between the buttons, as shown below and in the ControlPanel of this simulation.
example.setLayout(new BoxLayout(example, BoxLayout.Y_AXIS));
example.add(findNext);
Box.createVerticalStrut(10);
example.add(cancel);
Addendum:
adding in setMaximumSize() made it work.
This is the expected behavior for components having identical maximum widths in a vertical BoxLayout, as described in Box Layout Features. The preferred width of the container becomes that of the (equally wide) children, and the X alignment becomes irrelevant.
example.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JButton findNext = new JButton("Find Next");
JButton cancel = new JButton("Cancel");
Dimension d = findNext.getMaximumSize();
cancel.setMaximumSize(new Dimension(d));
example.add(findNext);
example.add(cancel);
As mentioned in the comments on the question, you were able to fix it by switching to setMaximumSize(). However, as you noted, setPreferredSize() doesn't work. So, what's up with that?
With many things Swing, the properties used to determine the actual component size when using the BoxLayout are somewhat random (in my opinion). When determining how to render the components, Swing calls layoutComponent() on the layout manager, which is figures out where to position everything.
BoxLayout's implementation of layoutComponent() involves a call to a method that creates SizeRequirements objects for the width and height of each of the components you add to the JPanel, based on their getMinimum/Preferred/MaximumSize() methods.
Later, it calls SizeRequirements.calculateAlignedPositions() for determining the correct width values for each component, because your orientation is BoxLayout.Y_AXIS (The heights are calculated using a different method). Taking snippets from the source, the relevant implementation of this method is as follows:
for (int i = 0; i < children.length; i++) {
SizeRequirements req = children[i];
//...
int maxAscent = (int)(req.maximum * alignment);
int maxDescent = req.maximum - maxAscent;
//...
int descent = Math.min(totalDescent, maxDescent);
//...
spans[i] = (int)Math.min((long) ascent + (long)descent, Integer.MAX_VALUE);
}
Note that totalDescent is the available width, so descent is always set to maxDescent, which is based on SizeRequirements.maximum, which was taken from JButton.getMaximumSize(). The value of spans[i] is then used later in a call to JButton.setBounds() as the width. As you'll note, getPreferredSize() was never involved here, which is why setting it has no impact in this case.
Usually if want to ensure a size of the component in Swing you need to call setMinimumSize(), setMaximumSize(), and SetPrefferedSize() with the same value.
button.setMaximumSize(getMaximumSize());
If you put your buttons in a GridLayout panel they will be the same width.

Categories

Resources