Always start vertical ScrollBar from the top - java

nspQuestionArea = new NScrollPane();
nspQuestionArea.setVerticalScrollBarPolicy
(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
nspQuestionArea.setVerticalScrollBarPolicy
(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
nspQuestionArea.setViewportView(getNpQuestionArea());
//where getNpQuestionArea() return a panel
nspQuestionArea.getVerticalScrollBar().setValue(0);
nspQuestionArea.getVerticalScrollBar().setValue(0);
nspQuestionArea.getVerticalScrollBar().setUnitIncrement(5);
nspQuestionArea.setOpaque(false);
if i open the panel,the vertical scrollbar starts from the middle of the panel,i need to start the scrollbar always from the top.
is there any method to do like that?
thanks in advance

I'm not really sure what an NScrollPane is, or what the component returned from getNpQuestionArea() is, but it looks like they're probably just an extension of JComponents. In that case, you can probably call the following...
getNpQuestionArea().scrollRectToVisible(new Rectangle(0,0,0,0));
Also, assuming that NScrollPane is an extension of JScrollPane, if you pass in the getNpQuestionArea() into the constructor of the NScrollPane, I believe it should automatically be at the top. So, something like this...
nspQuestionArea = new NScrollPane(getNpQuestionArea());
If you parse the JComponent into the NScrollPane constructor, I believe it positions the scrollbar at the top-left of the JComponent. However, if you add the JComponent later by calling setViewportView(), it positions it centrally by default. It has something to do with the way that the JComponents are layed-out when generating the display - if you add it in the constructor, it lays out the NScrollPane to the correct size and location for the JComponent that you pass to it. However, if you create a default NScrollPane and only give it the JComponent later, it just creates a NScrollPane at a default size, rather than fitting it appropriately to the JComponent.
Give both of these a try and see how you go.

setCaretPosition(0) worked for me

Related

Java Swing FlowLayout Alignments

I'm fairly new to Java and I'm trying to create a GUI application with some labels, buttons, and textfields. The program is pretty simple and I just wanted to use a default layout, which is FlowLayout. I managed to place and size everything fine, but the only thing seem to be not working is the alignment. I want to place buttons and textfields with certain alignments, but whenever I set an alignment, it moves the text inside of whatever the object rather than the object itself. For example, I wrote:
button.setHorizontalAlignment(JButton.RIGHT);
but it seems like it aligns the text inside the button instead of the button itself.
Is there any way to align the button itself rather than the text inside of it?
I know the alignment stuff could be easier with some other type of layout (e.g. BoxLayout), but I just want to use the FlowLayout for this one, unless it is impossible to align them using the FlowLayout (which I don't think so).
Thanks in advance.
See the constructor FlowLayout(int align).
Constructs a new FlowLayout with the specified alignment and a default 5-unit horizontal and vertical gap. The value of the alignment argument must be one of FlowLayout.LEFT, FlowLayout.RIGHT, FlowLayout.CENTER, FlowLayout.LEADING, or FlowLayout.TRAILING.
It seems you are after a FlowLayout.RIGHT as seen in this answer (the combo and check box at the top).
I don't think you can do this with a FlowLayout alone.
My suggestions would be:
Consider switching to MigLayout which is a much more powerful layout mechanism. MigLayout basically lets you position you components within a flexible grid, and you can set the specific alignment of a component within each grid cell.
When you want alignment of subcomponents, it also often makes sense to put them inside a nested JPanel. You can then use a separate layout for this JPanel (BorderLayout perhaps?) which will enable you to get the exact alignment that you want.
setHorizontalAlignment of AbstractButton sets the horizontal alignment of the icon and text not the position of the button. AbstractButton's default is SwingConstants.CENTER.
If you want to align the button..set the position while adding it to the panel or frame..something like this....
p.add(button, BorderLayout.SOUTH);//using `BorderLayout`
Flow layouts are typically used to arrange buttons in a panel. It will arrange buttons left to right until no more buttons fit on the same line.

Painting a JComponent without adding it to a container

I've implemented a custom JPanel, whose paint method I've extended to do a lot of manual rendering in full screen mode. Now I would like to integrate another JComponent to this (in my case a JPanel that contains a JScrollpane with a JTextPane as its viewport) that should appear on top of my first panel, but because my custom rendering pipeline is complex, adding the JComponent to my panel and having it painted the traditional way through the AWT system is not an option (I tried and it's quirky at best, not functional at worst), so my question is: is it possible to manually order the JComponent to be painted at one point in my program by calling its regular paint method without tying it to a JContainer and if yes, how do I do this?
Thanks in advance for your answers.
See the LabelRenderTest.java source on this thread. The label is eventually drawn to screen, but it is painted to BufferedImage before ever being displayed.
The important line of the source is..
textLabel.setSize(textLabel.getPreferredSize());
You can take a look at CellRendererPane and see how for example BasicTableUI paints component images with it.
Yes, just call the normal paint method on the object and pass the Graphics you want it to paint on. However, this is just going to paint it and it sounds like you want it to possibly scroll which means you will need to add it to your custom JPanel. In that case just add the panel and you a layout manager that will place the component where you need it.
You should set size for the component. Then to position it use your Graphics' translate(x,y) to position the component in desired Point.
if there is any container higher level in the hierarchy you can use
validate(); repaint();
pair to do that.
if not you can change it's size or bounds ( like +1 , -1 ) at the end to make it repaint itself.

Getting the correct sizes for JComponent after using GroupLayout

I wanted to ask whether it is possible to get the correct sizes of an JPanel after it has been placed in another JPanel that uses GroupLayout as Layout Manager. I have already tried to use:
.getPreferredSize(): this results in the Preferred Size that has been set by me, not the actual size that is drawn on the JPanel in the frame (if frame get's resized, the element will expand horizontally; which is not seen in the values).
.getSize(): it returns 0.
.getHeight(): it returns 0.
.getWidth(): it returns 0.
Maybe the positioning of the code is relevant, but it is executed AFTER shown on screen so it should not matter.
To force it to do that after it is shown on screen, maybe I can use EventQueue, but I'm not sure how.
Thank you for your answers!
You can get the "correct" size of the component only after it has been rendered, either by calling pack or setVisible(true) on the top level container.
Maybe the positioning of the code is relevant, but it is executed AFTER shown on screen so it should not matter.
Then something's not right. Are you sure that you're calling these methods on the visible components and not some variables that shadow them? Without code it's hard to tell where your error lies.

add()ing to a JPanel breaks its size

I have a JPanel identified by myPanel. I create a series of JButtons, and add() them to myPanel. At the end of my generating-and-adding loop, I call myPanel.validate(). The buttons show up.
The problem is the size of the panel is affected. No matter what Layout Manager I choose, the buttons are always added on the same line (even though there is more space beneath them).
I have tried setting myPanel's maximum size and setting its size after every add(). No matter what I do, after that validate(), the panel is blown up and my application's GUI is screwed.
Any ideas?
I create a series of JButtons, and add() them to myPanel... the buttons are always added on the same line (even though there is more space beneath them).
None of the default layout managers provide automatic wrapping. You need to specify how you want wrapping to occur. A GridLayout or a GridBagLayout can be used in these cases.
Or you can try the Wrap Layout which was written for this purpose.
i would firstly set a preferred size on the jpanel:
myPanel.setPreferredSize(new Dimension(X, Y));
this will tell your layout manager how to try to fit the contents within this dimension.
without seeing your source code, i can't add much more than that.

How to find out the preferred size of a JPanel which is not displayed, according to its content?

I am using a JPanel (with several labels inside) to add a dynamic information on a graph. This panel is dynamically created, it is not visible before I use it to draw.
For this, I am using a BufferedImage, and I follow approximately the same steps as described on this other question. It works good, as long as I specify all sizes (the panel, and its components).
Like asked as well in comments of the referred question, how can I determine the optimal size of this panel? The same operation would be done if this panel was displayed in a regular frame/layout setting.
In my case, how can I "pack", in a way, this panel, so that its size, and size of its content are set to the optimal (determined by the size of labels, then)?
Suraj and willcodejavaforfood put me on the good track.
Checking what is actually done in a pack() method, I see that this is mostly setting the current size to the one returned by getPreferredSize().
From this, I managed to make such solution:
// Creating the panel
JPanel lPanel = new JPanel();
//lPanel.setSize(1000, 1000); //default size, not needed anymore
lPanel.setLayout(new BoxLayout(lPanel, BoxLayout.PAGE_AXIS));
//Adding the content
lPanel.add(new JLabel("Blah"));
// etc...
//Adjust the panel to its preferred size
lPanel.setSize(lPanel.getPreferredSize());
//Call the layout method
//(this will adjust the content components to their correct size and position)
lPanel.doLayout();
This method works correctly, and adjusts the panel and its content to the correct size (and answers my question in a simplistic way: "how to find the preferred size? getPreferredSize()").
However, it requires to set the initial size to a large enough size, so that the content fits in, or they won't be put on the layout. This is a bit pity, and not really "clean", but I can't find a way to avoid that, for now.
Edit: Actually, the default size was not necessary, because getPreferredSize() returns the correct value, even before calling doLayout(). As such, the panel can be set to its proper size before calling the layout method.
The direct answer is to call Window#pack(). This method will automatically set the size of all underlying children to thier preferred sizes(ofcourse this depends on layouts of child containers, for e.g. BorderLayout doesent give a damn about preffered sizes).
So as long as you have set preferred sizes(or min/max sizes in case layouts are like BorderLayout) of your child components, pack() method will be all you need.
[UPDATE]One way is to do is add a HierarchyListener to your jpanel and check for HierarchyEvent#DISPLAYABILITY_CHANGED events. This event is called when your panel is realized that is ready to be shown(and a parent is available), at this moment you can do:
SwingUtilities#getWindowAncestor(myPanel).pack();

Categories