How to accurately get the coordinates of a JFrame's contents? - java

This is my JFrame code:
public static int width = 800;
public static int height = 600;
public static void main(String[]args){
JFrame frame= new JFrame("RETRO");
frame.add(new Screen());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width,height);
frame.setVisible(true);
frame.setResizable(false);
}
Basically when I want something to move to the edge of the screen, I have to add extra pixels for it work (I'm guessing because it includes the frame itself instead of just the display size? However the origins work fine (x=0, y=0)). Example:
public double getX(){
if(x<0)
x=0;
if(x+getImage().getWidth(null)>Game.width-6)
x=Game.width-6-getImage().getWidth(null);
return x;
}
public double getY(){
if(y<0)
y=0;
if(y+getImage().getHeight(null)>Game.height-26)
y=Game.height-26-getImage().getHeight(null);
return y;
}
Is there a way around this? I don't think the JFrame would be the same size on everyone's computer, not to mention the guesswork. Rather have it much neater and flexible by using an exiting variable from the JFrame component. Does there exist something like a frame.getDisplayWidth and Height function?

Don't set the size of the frame, set the preferred size of the contents.
Pack the frame
Get co-ordinates according to the position in the content
How do you set a 'preferred size' for the contents? I'm using a Screen class (extended JPanel) for rendering.
screen.setPreferredSize(new Dimension (600,400));
frame.setContentPane(screen);
frame.pack();
// frame will now be the size it needs to display the contents
// and the frame's own decorations (title bar etc.)
// ..now add a nice tweak.
frame.setMinimumSize(frame.getSize());

It seems you want to do something like a full screen app. JFrame's setDecorated(false) would do away with title and borders. setBounds does the sizing.

Instead of explicitly setting the size of the frame, try to set the preferred size of the content (in your case, the Screen object).
Also, just in case you need to find out the actual size of the frame decorations (title bar and borders), there is no need for guess work -- you can get this information by calling JFrame.getInsets()

Related

JLabel does not fully allign with JFrame

I have a JFrame with a JLabel on top called "coloredLabel", an instance of the class it's in is running on both of them. a random amount of objects move around on the frame and label and don't directly interact with them.
The only problem is that there is a bit of the frame visable above the label, what I want is that the label fully alligns with the frame, without pasting over the objects (which are painted in with an override paint method and mentioned as "game.newBall" and "game.moveBall". "test" is the name of the class.
Here is how my main thread looks, the frame and the label are declared within it:
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("Bounce 2.0");
JLabel coloredLabel = new JLabel("");
test game = new test();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
coloredLabel.setOpaque(true);
coloredLabel.setBackground(game.backgroundColor);
coloredLabel.setPreferredSize(new Dimension(1000000,1000000));
frame.getContentPane().add(coloredLabel,BorderLayout.LINE_START);
game.add(coloredLabel);
for(int a = randInt(0,9); a<10; a++)
game.newBall(randInt(0,300),randInt(0,400));
while (true) {
double height = frame.getContentPane().getSize().getHeight();
double width = frame.getContentPane().getSize().getWidth();
int n = 0;
while(game.exists(n)==true){
game.moveBall(n,width,height);
n++;
}
game.repaint();
Thread.sleep(10);
}
}
So my question is:
How do I allign the JLabel with the JFrame? so there is no space in between the JLabel and the frame.
I searched for this on this site, but couldn't find the same problem or something similar enough so I could fix this.
solved - game.setBackground(...);
The only problem is that there is a bit of the frame visable above the label,
game.add(coloredLabel);
I'm guessing "game" is a JPanel. By default a JPanel uses a FlowLayout and by default the FlowLayout has horizontal and vertical gaps of 5 pixels.
Get rid of the gap in the FlowLayout. Read the API for the constructors/methods of the FlowLayout to customize its behaviour.
But of course the bigger issue is the design of your app. I don't understand your point of using the label and attempting to take up all the space of the frame. Just set the background of the game panel by using:
game.setBackground(...);
Also class names should:
start with an upper case character and
be descriptive.
"test" is neither.

Java JFrame setSize doesn`t work properly

I am making a JFrame with the size of 500x500 pixels.
I make a blue background and add a red square in the right-bottom corner from (490,490) to (500,500).
Image:
I don't see the red square on the screen.
I switched the frame from not resizable to resizable and if I make the window larger the red dot is there.
Is the frame size the same as application's window size?
How can I make the application's window to be the exactly 500x500?
Your content pane should override the getPreferredSize() method, returning a Dimension object with width and height of 500 pixels:
public class MyContentPane extends JPanel {
private Dimension dimension;
public MyContentPane() {
this.dimension = new Dimension(500, 500);
}
#Override
public Dimension getPreferredSize() {
return this.dimension;
}
}
// How to use your new class
SwingUtils.invokeLater(() -> {
JFrame frame = new JFrame("Title");
frame.setContentPane(new MyContentPane());
frame.pack();
frame.setVisible(true);
});
The size of your JFrame will be calculated by Swing by taking in consideration the preferred size of the components inside it.
The frame is the size of the entire window, including the title bar required by the OS. When drawing things in the JPanel in the JFrame, the (0, 0) coordinate is in the top left corner if the JPanel, which begins just below the title bar. It sounds like your title bar is taller than 10 pixels, so 490 as a y component is actually off the window, since the visible height of the JPanel is windowHeight - titleBarHeight.
Should user the following
#Override
PreferedSize()
Remember preferedSize method is method of the super class JFrame.
this may be useful for you?
JPanel aa = new JPanel(new GridBagLayout());
aa.setMaximumSize(new Dimension(500,500));
aa.setMinimumSize(new Dimension(490,490));
aa.setBorder(BorderFactory.createLineBorder(Color.black));

How to change string length (calculating its width in pixel) when changing window size and strange behaviour of JLabel

I have JLabel which I would like to change its size while I resize the window. When JLabel contains String which is too big, the String should be shortened, with right part visible and adds dots on the left hand side of the String.
My JLabel is inside innerPanel which is a header in middlePanel which is added to outerPanel. So when I resize window I use listener on outerPanel in that way:
outerPanel.addComponentListener(new ComponentListener() {
#Override
public void componentResized(ComponentEvent evt) {
int width = ((JPanel) evt.getSource()).getWidth();
windowSize = width;
refresh();
}
// [...] other not used override methods
});
refresh() repaints view and creates new middlePanel where is called class which creates innerPanel where is located my JLabel:
Public class InnerPanel extends JPanel {
private int maxSize;
String string = "<VERY_LONG_STRING>";
private static final int DEFAULT_INDEND_PIXEL = 70;
public InnerPanel(int windowSize) {
maxSize = windowSize - DEFAULT_INDENT_PIXEL;
createPanel();
}
private createPanel() {
// [...] gridbag and GridBagConstraints implementation
String shortString = countString();
JLabel label = new JLabel(shortString);
add(label,gc);
}
private String countString() {
int index = 0;
boolean toBig = true;
StringBuilder sb = new StringBuilder(string);
while(toBig) {
Rectangle2d rect = // [...] code which creates rectangle around text from sb.toString()
// I have no access to repo at home but if it's important I can paste it tomorrow
if(rect.getWidth() > maxSize)
sb.deleteCharAt(0);
else
toBig = false;
}
return sb.toString();
}
}
That's works fine in general, bacause it do resize JLabel in one step when I enlarge window in width. But the problem is appear when I try to reduce the window in width. In this case componentResized() calculate width step by step (and it's called multiple times), gradually decreases width by some amount of pixels till it reach real window size. It's behave in that way even thow I change window size in one step from maximum size to 800. Whole process is so slow, that it takes around a second to fit string to window size. So it looks bit like an animation.
The problem is very rare to me, bacause width in componentResized() method is calculeted step by step only when I assign windowSize variable.
When I give windowSize fixed size like for example 500 - componentResized() is called only onces - with correct width indicated real window size (!!) - and there's no its step by step decrease!
It's look like width variable which is assigned by ((JPanel) evt.getSource()).getWidth() knows that windowSize is used to dynamically change size of JLabel component even before first call of refresh() method.
If anyone have an idea what is going on here - I will be very appreciate for help.
You may be able to adapt one of the approaches shown here to better effect. As shown here, the ellipsis is supplied by the label's UI delegate via a call to SwingUtilities2.clipString(), which appends the clipString. Rather than re-invent the label UI, use TextLayout to determine the required geometry, prepend the ellipsis, and handle the alignment in a table or list renderer, as shown here.

Window Size is smaller than it should be

Alright so I've got this JFrame with a screen on it. I've set the size to 800 by 800. However the window is created smaller than that. It's not a problem with the taskbar because it's not fullsize.
package sharph;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Main extends JFrame {
public static String Title = "Game 1";
public static Dimension screenSize = new Dimension(800,800);
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle(Title);
frame.setSize(screenSize);
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
Screen screen = new Screen();
screen.setSize(screenSize);
frame.add(screen);
frame.setVisible(true);
}
}
In the screen class the paint method draws a box around where the border should be:
//Draw border
g.setColor(Color.RED);
g.drawRect(1, 1, 799, 799);
When I run it, the window is smaller than the box and the bottom and right sides are cut off.
Note the second picture I manually re-sized to show the border difference.
I realize that I have drawn the box 1 pixel smaller on each side, but the difference is much more than 2 pixels.
This happens because the content needs to squeezed into the size of the frame minus its borders.
Checkout this question and this question for a more detailed explanation
The layout manager is also overriding the size property you set on the Screen component. In either case, you should be overriding the getPreferredSize method of the Screen class
Also, you shouldn't be relying on magic numbers or assumptions about the actual size of the component, but should, instead, be using getWidth and getHeight instead (I know, it's just for demonstration purposes)
Instead of "screen.setSize(screenSize);" type "screen.setPreferredSize(screenSize);" and then after you type "frame.setVisible(true);" type "frame.pack()". You can also remove "frame.setSize(screenSize);" if you want to.

drawing boxes in java

I have wrote a program that simulates memory allocation with first fit and best fit algorithms .
Now I want to associate my program with a drawing of set of boxes representing available memory segments
Before Allocation
After Allocation
So it just redraws but resizes one box and colors it ... What is the easiest way to do so ?
I have a set of boxes with different sizes that will be drawn dynamically according to input when the user does some action one of the boxes will be resized and recolored and so on.
I think this is best approached using graphics.
Instantiate a BufferedImage of a size to fit all boxes.
Get a Graphics instance by calling either of getGraphics() or createGraphics().
For each memory block:
Call Graphics.setColor(Color) according to allocation status, then..
Graphics.fillRect(int,int,int,int) or fillPolygon(Polygon) to draw the memory block.
If needed, use an AffineTransform to scale the sizes. This would require a Graphics2D object to draw on.
Use JPanel add JLabels like 0verbose but the layout to go with in my opinion is BoxLayout or GridBagLayout.
With FlowLayout you would have to make sure the size of the container is of a proper width to place one component under another, as by default it places components in a row.
From Java tutorial about FlowLayout "The FlowLayout class puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, the FlowLayout class uses multiple rows."
Use a JPanel as container with vertical FlowLayout BoxLayout, and add to it a JLabel for each memory block.
If the memory blocks can be rendered all the same size, a JComponent (or even easier a JProgressBar) could be used to represent each memory block. Those could then be put into a GridLayout or BoxLayout to organize the placement. E.G.
MemoryAllocation.java
import java.awt.*;
import javax.swing.*;
import java.util.Random;
class MemoryAllocation {
public static JProgressBar getMemoryBlock(int full) {
JProgressBar progressBar = new JProgressBar(
SwingConstants.VERTICAL, 0, 100);
progressBar.setValue(full);
progressBar.setPreferredSize(new Dimension(30,20));
return progressBar;
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
JPanel memoryView = new JPanel(new GridLayout(0,10,1,1));
Random random = new Random();
for (int ii=0; ii<200; ii++) {
int amount = 100;
if (random.nextInt(5)==4) {
amount = 100-random.nextInt(75);
}
memoryView.add( getMemoryBlock(amount) );
}
JOptionPane.showMessageDialog(null, memoryView);
}
});
}
}
Screen Shot

Categories

Resources