I'm using a simple ComponentAdapter to do something when the main JFrame window it's added to is resized. It's picking up the events without issue however I only want to act once a user has finished the resize. The componentResized() method fires multiple events for every pixel change of the resize and I don't want that as I need to scale an image when the window is resized and when it's done for every pixel it creates a huge lag.
I tried using a MouseListener on the frame to detect mouse up and down events to set a boolean as to whether it was being currently resized or not, but the events were never being triggered.
This is the simple ComponentAdapter:
private class ResizeListener extends ComponentAdapter {
public void componentResized(ComponentEvent e) {
onResize();
}
}
And it is added to the frame in the constructor using this.addComponentListener(new ResizeListener()); The class is extending JFrame so it should be added to the frame. I tried using getContentPane().addComponentListener(new ResizeListener()); but that didn't make any difference.
Any advice on a simple or effective way of only running the componentResized() method when the window is actually finished resizing would be appreciated.
Goal
I'm implementing a PDF reader which at the moment converts the page being viewed into a BufferedImage. When the user resizes the window I need to appropriately scale the image which means I can't let layout managers look after that for me. The number of componentResized events creates a huge lag as the image is being resized for every position along the user's resize path so I need to do it once the resize is finished.
Toolkit.getDefaultToolkit().setDynamicLayout(false);
This will affect all windows in the application, so if you only need this feature for a specific frame you may also want to add a WindowListener to the frame and then handle the windowActivated/windowDeactivated events to set this property.
Related
I am maintaining a system which requires me to make components in the dialog resizable, the dialog box calls out a java class Panel.
What is supposed to happen:
What is currently happening:
Note: The image on the bottom layer represents the resized one. While the image at the top layer is the dialog box which is not yet resized.
As you can see, the component JPanel(the one with the black border) is not resized. I am trying to achieve what happend to the bottom layer image of the first attachment.
I tried to apply the answer in How to dynamically control auto-resize components in Java Swing and pattern it in current code but since my panel is only called in a dialog box so there are limitations. The problem is that the components and its hierarchy have been already implemented, I just have to make it auto-resize.
Here is my current outline:
If you want a simple solution you can use a layout manager as described here.
Or, if you wish to avoid a layout manager(like me) then you can have your program resize your elements every time there is a resize event.
Here is some sudo-code
frameOrPanel.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent componentEvent) {
element.setLocation(frameOrPanel.getWidth()*1/4, frameOrPanel.getHeight*1/4);
element.setSize(frameOrPanel.getWidth()*1/2, frameOrPanel.getHeight()*1/2);
}
});
You will have to add unimplemented methods.
Note: the 1/4 and 1/2 is merely a ratio you can change those to fit your application.
My desktop Java application has a JMenubar with several JMenuitems, and underneath it is a JPanel which I re-render when an item in the dropdown menu is clicked.
It all works okay, but my JPanel is re-rendering (my overridden paintComponent is being called) when I hover or click on my JMenuitems.
That is a problem, because on the JPanel are programmatically constructed images (randomly seeded), and the construction takes a while, so my program hangs if i hover over the menu too much..
Why is this and how do I fix it?
Edit: Even if I seed the random values and get the same image, the program does too many unecessary calculations and it becomes slow.
… (my overridden paintComponent is being called) when I hover or click on my JMenuitems. That is a problem, … Why is this …
It is expected behavior. The toolkit will repaint a panel whenever it determines it is necessary to do so: E.G.s
A menu appearing or disappearing over it
Another window or dialog dis/appearing over it
The user resizing the window …
… on the JPanel are programmatically constructed images (randomly seeded), and the construction takes a while, …
To avoid having to recreate a complex paint, draw the details to a BufferedImage then either paint the image in the paint method, or (simpler) display it in a label.
I have some code to resize a chatpanel dynamically, but it does not move according to the mouse. What happens is the mouse moves at a faster rate than the panel gets resized. For example, how I want it to be, is in any application, when you click on the border between two windows, and drag it, the mouse stays along with the piece you are clicking on, and currently this is not happening. here is my code. please let me know if you need more
public void mouseDragged(MouseEvent e) {
if(getCursor().getType() == Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR).getType()) {
owner.adjust((int)MouseInfo.getPointerInfo().getLocation().getY());
System.out.println("vertpanel: "+(int)MouseInfo.getPointerInfo().getLocation().getY());
}
}
public void adjust(int adjustment) {
int height = this.getHeight();
System.out.println((((double)(adjustment))/height)+":"+(((double)(height-adjustment))/height));
output.setHeightPercent((((double)(adjustment))/height));
output.componentResized(new ComponentEvent(this, 1));
input.setHeightPercent((((double)(height-adjustment))/height));
input.componentResized(new ComponentEvent(this, 2));
}
there is one main panel, a chatpanel, and within it, there are two smaller panels, a chat input and a chat output
Can't tell exactly what you are doing based on your code.
I would suggest that you should NOT be manually setting the dimensions of the output and input coponents. You should let the layout manager determine how to resize each component as the parent container is resized.
So in your resize code you would need to invoke revalidate() on the parent container as it is resized.
Check out Resizing Components. You should be able to use the ComponentResizer class as long as you use setAutoLayout(true).
Easy Java question here. I have made a custom JSlider which paints squares at the last location the user has moved the slider to. We override paintcomponent and draw the squares relative to the size of the slider. Everything works good when you use the slider properly. Problems happen though when you resize the frame. The slider grows bigger, and the slider adjuster moves with it, but our squares that we placed don't move relative to the slider. Which function should we use from JSlider to repaint when we resize the frame?
I am trying to keep the JSlider code separate from the frame code, so we want the user to be able to use our custom JSlider and not be trying to handle this resizing feature themselves. Any help on which method we should use for this?
Thanks.
You can add a ComponentListener to your slider that repaints it on componentResized.
slider.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
e.getComponent().repaint();
}
}
A mouse listener calls repaint() and I can see that it does actually go past the drawing part because I see globalcounter incremented in the output of System.out.println(). On the screen, however, I don't see any change until I minimize the window and maximize again, resize it, or move it out of the visible screen area and back in. Obviously I'd like it to update without my intervention.
class GUI extends javax.swing.JFrame {
int globalcounter=0;
class MyCanvas extends Canvas {
#Override
public void paint(Graphics g) {
globalcounter++;
g.drawString(globalcounter,100,100);
System.out.println(globalcounter);
}
}
}
(Originally I was loading an image from a file that got constantly updated (webcam) and painting it on the canvas. When I dragged it partly out of the visible screen area and back in, the part that has been 'outside' was refreshed, the rest not.)
revalidate() instead of repaint() didn't change anything.
I know this post is a duplicate to Java repaint not working correctly but when I posted it there it was deleted.
Why are you adding an AWT component, Canvas, to a Swing component, JFrame? You should stick with Swing components only. And also do you know the size of your MyCanvas, and how have you added it to the JFrame as you don't show this code.
Consider
using a JPanel instead of a Canvas object,
drawing in its paintComponent method,
showing us an sscce if you're still stuck.
And also, if all you're doing is drawing text, use a JLabel rather than drawing in paint/paintComponent, and change its text with its setText(...) method.