I'm trying to take a window screenshot to use that as background in the application.
This is my code:
try {
Robot robot = new Robot();
Rectangle captureSize = new Rectangle(new MainWindow().getX(), new MainWindow().getY(), MainWindow.getWIDTH(), MainWindow.getHEIGHT());
RenderManager.backgroundGUIs = robot.createScreenCapture(captureSize);
GUIManager.ThisGui = new GUI("inventory", null, false);
} catch(AWTException e) {
System.err.println("Error taking screenshot!");
}
And these are the MainWindow().getY() and MainWindow().getX() methods:
public int getX() {
return (int) frame.getLocationOnScreen().getX();
}
public int getY() {
return frame.getY();
}
Now... it works fine, but there is a problem. frame.getLocationOnScreen().getX() and frame.getX() return the location with the window border, that hasn't to be in the screensot. Ok, i can manually calculate border size to subtract it, but from Windows 7 to Windows 8, from Windows 8 to Mac, etc. window border changes.
So... is there a method to get frame position or window border size to calculate what i need?
Thank you for your time and your answer!
As simple as this:
x = frame.getRootPane().getX();
As well, you can make all other calculations according to the root pane, just dropping the frame's.
As expected, the root pane is the top-level container inside any Frame/Window/Dialog etc. It includes the menubar too.
Use this
frame.getContentPane().getSize();
Check out the Screen Image class. You can create an image of any component displayed on the frame.
So you could use frame.getRootPane() as the component you want the image of.
Or frame.getContentPane() if you don't want the menu bar. I think this method returns a Container object so you will need to cast is to a JComponent.
int mouseX = MouseInfo.getPointerInfo().getLocation().getX() - frame.getX() - frame.getRootPane().getX();
int mouseY = MouseInfo.getPointerInfo().getLocation().getY() - frame.getY() - frame.getRootPane().getY();
This gives the top right point within the border / tab of a frame
Related
There are many questions of the converse, inserting a JTextPane into a JPanel. This is not my question. I need to be able to insert a custom JPanel (with drag and drop, drag, and mouse click listeners) into a JTextPane, which is then put into a JScrollPane, and finally put into a JFrame for displaying. The reason is because I need to have an image with support for resizing by dragging it within a chat client, which is itself primarily text.
Conveniently enough, there is a relevant method in JTextPane: insertComponent(Component c), but whenever I use it, my components end up being squished to exactly one line of text worth of space (even though they report having a larger size). This is perfect for plain buttons, but if I need anything larger, I'm out of luck. I can insert images by themselves just fine, with ImageIcons, but images wrapped inside a JPanel don't work at all (plus I can't add any listeners to ImageIcons, since they're not GUI elements; overriding one isn't an option).
Whenever a user drags an image into the chat client, this bit of code inserts the custom JPanel:
private void sendImage(BufferedImage im, int cl) throws IOException {
if(output == null) return;
//Send the image itself over to your friend
byte[] toSend = toBytes(im, cl);
sendString(nickname.hashCode() + "image"); //Header for image
output.writeInt(toSend.length); //Tells how many bytes to read.
output.write(toSend);
//Let the user know that the image was sent
float linmb = (float)(toSend.length / 1048576.0); //Size of file sent
addText("\n" + nickname + " sent an image! (" + linmb + " MB)\n", Color.RED.darker());
//Show the image itself
DraggerPanel d = new DraggerPanel(im, true);
text.insertComponent(d);
d.repaint();
//Spacer
addText("\n");
}
This is the source for DraggerPanel, the custom JPanel that holds an image:
public class DraggerPanel extends JPanel {
private BufferedImage image; //The image we're drawing
private Point startingPoint = null; //Starting point for resizing
private boolean first = true; //Is this the first drag?
private boolean lockedDrag; //If true, then lock x and y to be proportionally dragged.
public DraggerPanel(BufferedImage image, boolean lockedDrag) {
super();
this.image = image;
this.lockedDrag = lockedDrag;
//The listener for dragging events.
addMouseMotionListener(new MouseMotionListener() {
private int inWidth = 0, inHeight = 0; //Initial height and width values
private double ratio = 0; //Ratio of height to width for locked drag.
public void mouseDragged(MouseEvent m) {
if (first) { //If we're first, record initial position.
startingPoint = m.getPoint();
first = false;
inWidth = getWidth();
inHeight = getHeight();
ratio = (double)inHeight / inWidth;
} else { //Otherwise, change the size of the window.
if (!lockedDrag) {
int w = (int)startingPoint.getX() - m.getX();
int h = (int)startingPoint.getY() - m.getY();
setSize(Math.abs(inWidth - w), Math.abs(inHeight - h));
} else {
int w = (int)startingPoint.getX() - m.getX();
int h = (int)((double)ratio * w);
setSize(Math.abs(inWidth - w), Math.abs(inHeight - h));
}
}
repaint();
}
public void mouseMoved(MouseEvent m){
}
});
//Lets us know when you're not dragging anymore.
addMouseListener(new MouseAdapter(){public void mouseReleased(MouseEvent m){first = true;}});
//Set appropriate size.
if(image != null) setSize(image.getWidth(), image.getHeight());
else setSize(200,200);
//We're live, baby.
setVisible(true);
}
public void paint(Graphics g) {
if (image == null) super.paint(g);
else g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
}
}
Update 1: I followed #camickr 's advice, and updated the DraggerPanel to use setPreferredSize instead of setSize, as well as overrode paintComponent() instead of paint(). Now, the image has the proper height, but is stretched to the width of the JTextPane (which seems like what it was doing before). Furthermore, resizing doesn't seem to matter- the image doesn't change its size at all. Mouse events are definitely going through, but not affecting the size. It seems as though the original problem isn't fully resolved, since the JPanel's size isn't what I need it to be, and the solution to that will also lead to a solution to the resizing issue.
Update 2: I did it! I finally did it. To the future time travelers who have this issue, I basically yelled at the JTextPane by not only using setSize() in my overridden JPanel, but also setPreferredSize() and setMaximumSize(). The preferred one works well with height, and the maximum sets the width (God knows why). Thanks for your tips, #camickr!
my components end up being squished to exactly one line of text worth of space (even though they report having a larger size).
I would guess the size is not important.
I would think you need to override the getPreferredSize() method of your DraggerPanel to return the preferred size of the panel so the text pane can display the panel.
Also, custom painting is done by overriding the paintComponent(...) method NOT the paint() method.
I have created a GUI via Netbeans Java but whenever I maximize the GUI window the text boxes become misaligned. I used the Netbeans drag and drop function to create the GUI. I was wondering why the text boxes become misaligned whenever I maximize the GUI
It's an issue with the layout.
Read up on using layouts: http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
If you are going to use Netbean's GUI builder, run through a tutorial. It'll help you better understand how the builder is to be used. https://netbeans.org/kb/docs/java/quickstart-gui.html
I Understood your problem because I already had the same problem, My advice to you is that you can use the drag and drop of netbeans but before using it first make a panel and in that panel drop all your stuff then using the JFrame Component re sized function just put the panel wherever you want to put it for e.g if you want to center align it.
//if your class is extending JFrame
public static int getWIDTH(){
return WIDTH;
}
public static int getHEIGHT() {
return HEIGHT;
}
private void formComponentResized(java.awt.event.ComponentEvent evt) {
// this is for setting panel in the middle of the JFrame horizontally
int a = getWIDTH();
int b = Panel.getWidth();
a = a/2;
b = b/2;
int centerForX = b - a;
// This is for setting the panel in the middle vertically
int x = getHEIGHT();
int y = Panel.getHeight();
x = x/2;
y = y/2;
int centerForY = x - y;
// Making a 'Point' object and then setting location of the Panel.
Point p = new Point(centerForX , centerForY);
Panel.setLocation(p);
}
Some Keypoints:
1) getWIDTH and getHEIGHT methods will be generated by netbeans write outside all methods but in the class the getwidth and getheight and press ctrl + space and press enter and the getWIDTH and getHEIGHT methods will be generated respectively.
2) the formComponentResized method will be generated by netbeans, just go to design tab and then in the Navigator which is mostly in the bottom left right click on JFrame and then goto events then components and then componentResized.
3) If you have any question don't hesitate to ask, as I have detailed knowledge of this topic.
Is there anything obvious wrong with this line of code? I want rectangle to stay centered regardless the size of the window. But this donĀ“t work for some reason, the rectangle stays the same place.
public void run() {
setSize(800, 800);
createEntireFigure();
}
private void createEntireFigure(){
int centerOfWindowWidth = getWidth() / 2;
int centerOfWindowHeight = getHeight() / 2;
GRectWithGLabel ("A String",centerOfWindowWidth, centerOfWindowHeight);
}
Your rectangle size code is only called on rectangle creation, and so it makes sense that the rectangle's position will not change if the GUI is re-sized. You need to somehow listen for size changes in your GUI and call code to re-position the rectangle then for this to work. What graphics library are you using?
Yes some questions get close :)
There is a Bug in Java ( been around and reported since 2011, seems like there is no effort being made to fix it either - should be handled on the native side of the VM)
That is when you maximize an "undecorated" window, or a window drawn wihth a PLAF look and feel, it will cover the windows taskbar. Fine - desirable when you want it, but when you do want the taskbar maximized windows cover it. setting the "always on top" proerty doesn make any difference.
Yes one can resize a window BUT one has to know where the task bar is, or the size of the screen minus the taskbar - know how to do that?
and one needs to know you are maximizing on a screen without a taskbar if that is being done. and if on a multimonitor virtual desktop ...
Any ideas :)
Yes one can resize a window BUT one has to know where the task bar is,
or the size of the screen minus the taskbar - know how to do that?
Yes:
1.Look up the graphic device you are on (assuming p is a Point of the Screen you are looking for):
GraphicsConfiguration graphicsConfiguration = null;
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
if (gd.getDefaultConfiguration().getBounds().contains(p)) {
graphicsConfiguration = gd.getDefaultConfiguration();
break;
}
}
2.Look at the screen bounds (watch out that some bounds location are negative with multiple screens - for example, if you have a secondary screen which is on the left of your main screen), the screen size and the "Insets" of the screen which are usually the taskbar and/or other graphical artifacts:
Rectangle screenBounds = graphicsConfiguration.getBounds();
Dimension screenSize = screenBounds.getSize();
Insets screenInsets = Toolkit.getDefaultToolkit()
.getScreenInsets(graphicsConfiguration);
Thanks
Here is the code made from above which is calls immediately after the window is maximized by the system. It checks for the taskbars and resizes the window accordinly.
note that the setBounds will "un-maximize" the window as far as Java is concerned so the "getExtendedState()" will return un maximized and I need to maintain my own flag. I also have to cache the last pre-maximized window size so I know where to restore the window to later - all way too messy but it works.
Rectangle bounds;
Rectangle fbounds = frame.getBounds();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
// as system maximized this at this point we test the center of the window
// as it should be on the proper screen.
Point p = new Point(fbounds.x + (fbounds.width/2),fbounds.y + (fbounds.height/2));
GraphicsConfiguration graphicsConfiguration = null;
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices())
{
if (gd.getDefaultConfiguration().getBounds().contains(p)) {
graphicsConfiguration = gd.getDefaultConfiguration();
break;
}
}
if(graphicsConfiguration != null)
{
bounds = graphicsConfiguration.getBounds();
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfiguration);
bounds.x += screenInsets.left;
bounds.y += screenInsets.top;
bounds.height -= screenInsets.bottom;
bounds.width -= screenInsets.right;
} else {
bounds = env.getMaximumWindowBounds();
}
if(fbounds.equals(bounds)) {
bounds.height -= 1;
}
frame.setBounds(bounds);
As in wen you run any output in a frame, every time you run the program it pops on a different position on the screen?
You can use the setLocation(int, int) of JFrame to locate a JFrame in a new location.
So, put this in the frame's constructor and use Random to generate a random location, and your frame will pop up in a random location every time.
Another option would be to override the setVisible(boolean) method of the JFrame.
public void setVisible(boolean visible){
super.setVisible(visible);
if (visible) {
Random r = new Random();
// Find the screen size
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension d = tk.getScreenSize();
// randomize new location taking into account
// the screen size, and current size of the window
int x = r.nextInt(d.x - getWidth());
int y = r.nextInt(d.y - getHeight());
setLocation(x, y);
}
}
The code located inside the if (visible) block could be moved inside the constructor. The getWidth() and getHieght() methods may not return the correct values that you expect though.
Use java.util.Random's nextInt(int) along with JFrame.setLocation(int, int).
For example,
frame.setLocation(random.nextInt(500), random.nextInt(500));
If you receive an error such as Cannot make a static reference to the non-static method nextInt(int) from the type Random
you can use the alternative code, frame.setLocation((int)Math.random(), (int)Math.random());
Hope this helps!