java swing how to restrict JScrollPane to only vertical - java

Check out if you can help on this.
I need to restrict the scrolling to only vertical when using JScrollPane.
REMEMBER: not disabling the hortizontal scroll bar by using HORIZONTAL_SCROLLBAR_NEVER, which just disable horizontal. And i need is the components should not go beyond the window horizontally.

Add this to the container within the JScrollPane:
#Override
public java.awt.Dimension getPreferredSize() {
int h = super.getPreferredSize().height;
int w = getParent().getSize().width;
return new java.awt.Dimension(w, h);
}

At first I suggest you to check this out.
http://www.java-tips.org/java-se-tips/javax.swing/how-to-use-a-scrollbar-in-both-vertical-and-horizontal-dire.html
and you can actually try these lines of codes as well:
public class AddScroll
{
public static void main(String[] args)
{
JPanel panel = new JPanel();
JScrollPane scrollBar = new JScrollPane(panel,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JFrame frame = new JFrame("AddScrollBarToJFrame");
frame.add(scrollBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
}

Related

JScrollPane doesn't work while inside a JPanel

JScrollPane works perfectly when I give it a JPanel and then add the JScrollPane directly on to a JFrame with frame.getContentPane.add(). However, it doesn't work when I add the JScrollPane to a JPanel and then add the JPanel to the JFrame. I need to use the second method because I'm going to add multiple things inside the JPanel and JFrame and I need to keep it organized. Here is my code.
import java.awt.*;
import javax.swing.*;
public class Main {
/**
* #param inpanel asks if the JScrollPane should
* be inside of a JPanel (so other things can also be added)
*/
public static void testScroll(boolean inpanel) {
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setResizable(true);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.red));
//panel.setLayout(new BoxLayout(panel, 1));
panel.setLayout(new GridLayout(0,1));
for (int i = 0; i < 100; i++) {
JLabel l = new JLabel("hey"+i,SwingConstants.CENTER);
l.setBorder(BorderFactory.createLineBorder(Color.green));
l.setPreferredSize(new Dimension(200,200));
panel.add(l);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.blue));
//**********THIS DOES NOT WORK HOW I WANT IT TO************
if(inpanel){
JPanel holder = new JPanel();
holder.add(scrollPane);
f.getContentPane().add(holder);
}
//************THIS DOES WORK HOW I WANT IT TO****************
else{
f.getContentPane().add(scrollPane);
}
f.pack();
f.setSize(500, 500);
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.setVisible(true);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue(bar.getMaximum());
bar.setUnitIncrement(50);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
testScroll(false); //OR TRUE
}
};
SwingUtilities.invokeLater(r);
}
}
In the main method, if I pass false, it works like I mentioned before, but when I pass true it shows up without a scroll bar.
Picture when passing false
Picture when passing true
I need a way to add the JScrollPane to a JPanel and still have it work.
Thanks in advance!
Your problem is the holder JPanel's layout. By default it is FlowLayout which will not re-size its child components when need be. Make it a BorderLayout instead, and your scrollpane will resize when needed. If you need something more complex, check out the layout manager tutorials.

Java - How to change components height using BoxLayout?

So, I have a tiny GUI program and I decided to use the BoxLayout to display the components from top to bottom. Everything works fine but I'm not able to change the height of my JButtons. I tried many things like setPreferredSize() but then i had the problem that the width isn't correct, as well. Using setMaximumSize() sets the width like i want to but the height still doensn't change. Maybe some of you could help me :) Thanks
public class SimpleSkinViewer extends JPanel implements ActionListener{
private final Dimension boxDimension = new Dimension(320, 320);
private final Dimension buttonDimension = new Dimension(320, 60);
private final Dimension spaceDimension = new Dimension(0, 5);
private JLabel imagebox;
private JButton loadButton;
private JButton changeButton;
private JButton downloadButton;
public SimpleSkinViewer() {
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
imagebox = new JLabel("");
imagebox.setIcon(new ImageIcon(loadImage("http://skins.minecraft.net/MinecraftSkins/AvarionDE.png")));
loadButton = new JButton("Load Skin");
changeButton = new JButton("Change Skin");
downloadButton = new JButton("Download");
//add listeners
loadButton.addActionListener(this);
changeButton.addActionListener(this);
downloadButton.addActionListener(this);
//dimensions
imagebox.setMaximumSize(boxDimension);
loadButton.setMaximumSize(buttonDimension);
changeButton.setMaximumSize(buttonDimension);
downloadButton.setMaximumSize(buttonDimension);
add(imagebox);
add(Box.createRigidArea(spaceDimension));
add(loadButton);
add(Box.createRigidArea(spaceDimension));
add(changeButton);
add(Box.createRigidArea(spaceDimension));
add(downloadButton);
}
#Override
public void actionPerformed(ActionEvent arg0) {
}
//and other stuff.....
public static void main (String[] args) {
JFrame frame = new JFrame("Avarion's Simple Skin Viewer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new SimpleSkinViewer());
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
You need Box.createVerticalGlue()
Change
add(changeButton);
add(Box.createRigidArea(spaceDimension));
with
add(changeButton);
add(Box.createVerticalGlue());
Then you can use .setPreferredSize(new Dimension(x,y)); and buttons will adapt to your layout
From the docs for BoxLayout
When a BoxLayout lays out components from top to bottom, it tries to
size each component at the component's preferred height.
For a top-to-bottom box layout, the preferred width of the container
is that of the maximum preferred width of the children. If the
container is forced to be wider than that, BoxLayout attempts to size
the width of each component to that of the container's width (minus
insets). If the maximum size of a component is smaller than the width
of the container, then X alignment comes into play.
So, you can set both the maximumSize and preferredSize to get the desired size.
loadButton.setMaximumSize(buttonDimension);
loadButton.setPreferredSize(buttonDimension);

Add JPanels dynamically to either a JTable or a JScrollPane

Currently working on a project and I need to add a panel I've made to a scrollpane or a table dynamically. The scrollpane should start out empty and add the panels.
The GuiConstructor is where i make the window.
My problem is that if I don't comment out the setSize in the GuiConstructor, the window starts out very small.
Secondly, when i press the add button, it doesn't add the panels.
public GuiConstructor(){
super(APPLICATION_NAME);
setLayout(new BorderLayout());
LoopControlWindow loopwin = new LoopControlWindow(connect);
add(loopwin , BorderLayout.NORTH);
pack();
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
//this.setSize(500, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class LoopControlWindow extends JPanel {
IConnector connect;
public LoopControlWindow(IConnector connect) {
super(new BorderLayout());
this.connect = connect;
initPane();
}
private void initPane() {
JPanel panel = new JPanel(new GridLayout(3,1));
FolderSearchComp fsc = new FolderSearchComp(connect);
JScrollPane scrollPane = new JScrollPane();
JButton button = new JButton("Add");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panel.add(new FolderSearchComp(connect));
scrollPane.getViewport().setView(panel);
}
});
scrollPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scrollPane.setViewportBorder(new LineBorder(Color.BLACK));
add(scrollPane, BorderLayout.CENTER);
add(button, BorderLayout.SOUTH);
}
This is typical of this style of GUI app. You need to tell the layout manager how big to make the Window initialy without using setSize(). The way to do this is to override getPreferredSize() to return a default size. In your case:
public LoopControlWindow extends JPanel {
private Dimension size;
public LoopControlWindow() {
Preferences prefs = Preferences.userNodeForPackge("your.java.package");
size = new Dimension(prefs.getInt("width", 800), prefs.getInt("height", 600));
}
public Dimension getPreferredSize() {
return size;
}
}
By doing it this way you can store the user preferences for the window dimensions but also provide sensible defaults to start.
You should also make sure that this JPanel is your main panel and is added to the JFrame at BorderLayout.CENTER to ensure that your window gets drawn properly. All other panels should be somewhere inside this one.
Once you have this set up calling pack() will work correctly.
For your first problem, you need to specify a size for the initial JFrame(). One way is to call setSize as you are doing. Another is to override getPreferredSize() to return the default size. And one other option is to find the size of the user's monitor and set the JFrame to be a percentage of that size. That way you can ensure your window always fits on your user's screen.
int height = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice().getDefaultConfiguration().
getBounds().height;
height = (int) (height * .85);
int width = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice().getDefaultConfiguration().
getBounds().width;
width = (int) (width * .85);
frame.setSize(width, height);
Second, you need to call revalidate() and repaint() anytime you add or remove from a layout in order to see the changes.
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panel.add(new FolderSearchComp(connect));
scrollPane.getViewport().setView(panel);
revalidate();
repaint();
}
});
One note on border layout. The components in it will not resize with your JFrame. Whatever component that is placed in BorderLayout.CENTER will, however. That component will grow to fill all extra space as the JFrame grows. It will also be the component that shrinks when the JFrame windows gets smaller.

JLayeredPane not resizing with JFrame

I have a JLayeredPane within a JFrame, with two JPanels in it. It all works fine, except since the JLayeredPane requires me to have a null Layout, it doesn't resize the two JPanels correctly when the JFrame resizes.
public class CreatorUI extends JFrame{
private static final long serialVersionUID = 1L;
private JPanel moveablePane = new JPanel();
private Container backgroundPane;
private JLayeredPane layers = new JLayeredPane();
private ComponentMover componentMover = new ComponentMover();
private ComponentResizer componentResizer = new ComponentResizer();
public CreatorUI(){
backgroundPane = new BackgroundUI().initComponents();
layers.add(backgroundPane, 1);
moveablePane.setLayout(null);
componentMover.setAutoLayout(true);
moveablePane.setOpaque(false);
layers.add(moveablePane, 2);
moveablePane.setSize(backgroundPane.getSize());
add(layers, BorderLayout.CENTER);
layers.setPreferredSize(backgroundPane.getPreferredSize());
pack();
}
public void addWindow(WindowComponent window){
this.componentMover.registerComponent(window);
this.componentResizer.registerComponent(window);
this.componentMover.setDragInsets(this.componentResizer.getDragInsets());
this.moveablePane.add(window);
}
public static void main(String[] args){
CreatorUI frame = new CreatorUI();
frame.addWindow(new MapComponent());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
This is what it looks like normally (looks perfect for the normal size):
This is what it looks like once I've tried to resize the JFrame:
I figured out that I can make the top layer resizable if I change my code to this:
public CreatorUI(){
componentMover.setAutoLayout(true);
backgroundPane = new BackgroundUI().initComponents();
moveablePane.setLayout(null);
moveablePane.setOpaque(false);
moveablePane.setSize(backgroundPane.getSize());
layers.setLayout(new BorderLayout());
layers.add(backgroundPane, BorderLayout.CENTER);
layers.setLayer(backgroundPane, new Integer(1));
layers.add(moveablePane, BorderLayout.CENTER);
layers.setLayer(moveablePane, new Integer(2));
add(layers, BorderLayout.CENTER);
layers.setPreferredSize(backgroundPane.getPreferredSize());
pack();
}
This is what it look like now (only the pink layer resizes):
I have the same problem with a more complex container with a shadow Layer above. I was searching for an answer but only found this (which was not helping me). What i did was this:
layers.addComponentListener(new ComponentAdapter() {
#Override public void componentResized(ComponentEvent e) {
Dimension size = layers.getSize(); // get size
backgroundPane.setSize(size); // push size through
moveablePane.setSize(size); // push size trhough
// otherChildOfLayers.setSize(size); // push size trhough
layers.revalidate(); // revalidate to see updates
layers.repaint(); // "Always invoke repaint after revalidate"
}
});
some more information about repaint/revalidate
Answering my own question
There is a very hack-y fix, which (for your purposes) is to keep the overlay at max size at all times.
public CreatorUI(){
componentMover.setAutoLayout(true);
backgroundPane = new BackgroundUI().initComponents();
moveablePane.setLayout(null);
moveablePane.setOpaque(false);
moveablePane.setSize(Toolkit.getDefaultToolkit().getScreenSize());
layers.setLayout(new BorderLayout());
layers.setLayer(moveablePane, JLayeredPane.DRAG_LAYER);
layers.add(moveablePane, BorderLayout.CENTER);
layers.setLayer(backgroundPane, JLayeredPane.DEFAULT_LAYER);
layers.add(backgroundPane, BorderLayout.CENTER);
add(layers, BorderLayout.CENTER);
layers.setPreferredSize(backgroundPane.getPreferredSize());
pack();
}

Java applet scrollbar

[Thanks for the answers. This comes for you http://www.youtube.com/watch?v=Vo0Cazxj_yc ]
This might and should be a very easy question, but i could not find a solution.
I have a java applet, and i want a vertical scrollbar so that i can load thousands of buttons into the applet and use the scrollbar to see buttons down on the applet.
Buttons are used to select items. if button is pressed, the item is selected.
When i load buttons, all of them are shown on one screen, squeezed together to fit the screen in width and height (~1000px,~1000px). Below code is a portion of my program. Please comment.
JFrame frame = new JFrame();
NameClassifier nameClassifier = new NameClassifier();
JScrollPane scrollPane = new JScrollPane(nameClassifier);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(scrollPane);
frame.getContentPane().add(nameClassifier);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
System.out.println("exiting");
import java.awt.*;
import javax.swing.*;
class ManyButtons {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
NameClassifier nameClassifier = new NameClassifier();
JScrollPane scrollPane = new JScrollPane(nameClassifier);
scrollPane.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
frame.add(scrollPane);
// nameClassifier has already been added to the scroll pane.
//frame.getContentPane().add(nameClassifier);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
System.out.println("exiting");
}
});
}
}
class NameClassifier extends JPanel {
NameClassifier() {
super(new GridLayout(0,10,2,2));
for (int ii=1; ii<=1000; ii++) {
add(new JButton("Button " + ii));
}
}
}
I think you want to use a Wrap Layout.
Don't add anything directly to the frame, so
frame.add(scrollPane);
is wrong.
Add things to the content pane. probably
scrollPane.add(nameClassifier);
frame.getContentPane().add(scrollPane);
btw, that is one pretty gui design. :)

Categories

Resources