Change bounds of a JScrollPane in Java [closed] - java

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Helloo!
In the Java Application I have a JScrollPane and in that scroll I have a JTextArea
JTextArea TextArea = new JTextArea("Text");
scroll = new JScrollPane(TextArea);
scroll.setBounds(150,100,250,100);
And I got the scroll.
But If the user clicks a JButton the location of the JScrollPane should change...
I have this code and it works if the scroll doesn't have the TextArea
scroll.setBounds(50,100,250,100);
but if the scroll has the TextArea it doesn't move at all
Any idea what is happening?

Change bounds of a JScrollPane ..
The bounds come down to the position and size of the component.
The best way to change the size of a scroll pane is to change the size of the component it is displaying. A text area can be resized by setting the number of rows & columns (easily specified in the constructor), or by setting a different font size.
The best way to position the scroll pane is to use layouts, along with layout padding and borders for white space.

Use vScrollPane.setValue() hScrollPane.setValue() methods.
Like this
import java.awt.event.*;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
class JScrollPaneToTopAction implements ActionListener {
JScrollPane scrollPane;
public JScrollPaneToTopAction(JScrollPane scrollPane) {
if (scrollPane == null) {
throw new IllegalArgumentException(
"JScrollPaneToTopAction: null JScrollPane");
}
this.scrollPane = scrollPane;
}
public void actionPerformed(ActionEvent actionEvent) {
JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar();
JScrollBar horizontalScrollBar = scrollPane.getHorizontalScrollBar();
verticalScrollBar.setValue(20);
horizontalScrollBar.setValue(100);
}
}
public class JScrollPaneToTopActionDemo {
public static void main(String args[]) {
JFrame frame = new JFrame("Tabbed Pane Sample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("Label");
label.setPreferredSize(new Dimension(1000, 1000));
JScrollPane jScrollPane = new JScrollPane(label);
JButton bn = new JButton("Move");
bn.addActionListener(new JScrollPaneToTopAction(jScrollPane));
frame.add(bn, BorderLayout.SOUTH);
frame.add(jScrollPane, BorderLayout.CENTER);
frame.setSize(400, 150);
frame.setVisible(true);
}
}

Related

Java : JTree and BasicTreeUI reference doesn't show scrollbars

Working with the JTreeWithScrollbar example, but scaled it back significantly to focus on the issue.
The original code would have the vertical scrollbars appear as needed.
Here, there is plenty of space and no scrollbars are needed.
If the panel is moved enough, the scrollbar will appear.
Once the following line of code was added, the scrollbars stopped appearing.
tree.setUI(new MyTreeUI());
Notice no scrollbar.
If the above line of code is commented out, the vertical scrollbar appears.
Checking the documentation for BasicTreeUI and there isn't anything related to showing/hiding scrollbars.
2 Questions
1 - When utilizing the BasicTreeUI object, what is required to ensure the scrollbars still function?
2 - Why is it the Horizontal scrollbar never appears even if the line of code is commented out?
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicTreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.Dimension;
public class JTreeWithScrollbar extends JPanel {
private JEditorPane htmlPane;
private JTree tree;
public JTreeWithScrollbar()
{
//Create the nodes.
DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Java Series");
DefaultMutableTreeNode book1Node = new DefaultMutableTreeNode("Book 1");
DefaultMutableTreeNode book2Node = new DefaultMutableTreeNode("Book 2");
top.add(book1Node);
top.add(book2Node);
tree = new JTree(top);
tree.setUI(new MyTreeUI()); ///Comment out this line of code and the vertical scrollbar appears.
JScrollPane treeView = new JScrollPane(tree);
JScrollPane htmlView = new JScrollPane(htmlPane);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setTopComponent(treeView);
splitPane.setBottomComponent(htmlView);
Dimension minimumSize = new Dimension(100, 50);
htmlView.setMinimumSize(minimumSize);
splitPane.setDividerLocation(100);
splitPane.setPreferredSize(new Dimension(500, 300));
add(splitPane);
}
public static void main(String[] args)
{
//Create and set up the window.
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel();
jp.add(new JTreeWithScrollbar());
frame.add(jp);
//Display the window.
frame.pack();
frame.setVisible(true);
}
private static class MyTreeUI extends BasicTreeUI
{
public MyTreeUI()
{
super();
}
#Override
protected void updateCachedPreferredSize() {
treeState.invalidateSizes();
tree.treeDidChange();
}
}
}
When utilizing the BasicTreeUI object, what is required to ensure the scrollbars still function?
As shown in the minimal example below, BasicTreeUI correctly shows each scroll bar when needed; resize the frame to see the effect.
Why does the horizontal scrollbar never appear even if the line of code is commented out?
After pack() the frame has been resized to adopt the preferred size of it content. Making the frame slightly smaller illustrates the effect. Your example adds the tree to a JPanel having a default FlowLayout which ignores preferred sizes; the example below adds the tree to the center of the frame's default BorderLayout which responds to preferred sizes.
I am assuming the updateCachedPreferredSize() must be doing other stuff behind the scenes…
Exactly. Each invocation of updateCachedPreferredSize() updates the component's preferred size to reflect any change in state (resize, expand, etc.); when the preferred size exceeds the viewport size, the scroll bars appear. As you observed, invoking super.updateCachedPreferredSize() allows normal operation, and any further customization must preserve that functionality.
In addition,
Expand rows as need like this.
Construct and manipulate Swing GUI objects only on the event dispatch thread.
Don't use setSize() when you really mean to override getPreferredSize() or illustrates a resize effect; more here.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.plaf.basic.BasicTreeUI;
public class JTreeWithScrollbar {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
//Create and set up the window.
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTree tree = new JTree(); //default model
for (int i = 0; i < tree.getRowCount(); i++) {
tree.expandRow(i);
}
tree.setUI(new MyTreeUI());
frame.add(new JScrollPane(tree));
//Display the window.
frame.pack();
frame.setSize(frame.getWidth() - 10, frame.getHeight() - 100);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
private static class MyTreeUI extends BasicTreeUI {
}
}

Set minimum width in side panel of Swing BorderLayout

I understand some parts of BorderLayout -- e.g., the EAST/WEST (or BEGINNING_OF_LINE/END_OF_LINE) panel component stays one width and its length is stretched with the length of the window.
I want to put a panel on the WEST side that itself has multiple components - a panel of buttons and a JList of things the buttons control, in this case. I would like to allocate a minimum width for the strings in that JList, but something (probably BorderLayout) prevents me from setting a minimum or preferred width.
When I run the code below, the list in the left panel is wide enough for "LongNameGame 3", but only because I added the string before rendering the list. I would like to set the width of that JList to accommodate strings of the width of my choice. Later I'll put it in a ScrollPane for strings wider than that, but that's a different problem.
My question is not answered by referring me to other layout managers -- I want to know how to do this with BorderLayout, if possible.
package comm;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.Border;
public class BLPlay
{
public static void main(String ... arguments)
{
JFrame frame = buildLoungeFrame();
frame.setVisible(true);
}
private static JFrame buildLoungeFrame()
{
JFrame loungeFrame = new JFrame("BLPlay");
loungeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loungeFrame.setLayout(new BorderLayout(10,10));
// left panel is another BorderLayout panel with buttons and a list of games
JPanel gameListControlPanel = new JPanel(new BorderLayout());
Border innerBorder = BorderFactory.createLineBorder(Color.BLACK, 2);
Border outerBorder = BorderFactory.createEmptyBorder(3,3,3,3);
gameListControlPanel.setBorder(BorderFactory.createCompoundBorder(outerBorder, innerBorder));
String[] gamePanelButtonLabels = { "New", "Join", "Leave", "End" };
JPanel gamePanelButtons = new JPanel(new GridLayout(gamePanelButtonLabels.length,1));
addButtons(gamePanelButtons, gamePanelButtonLabels);
JPanel gamePanelButtonsContainerPanel = new JPanel();
gamePanelButtonsContainerPanel.add(gamePanelButtons);
gameListControlPanel.add(gamePanelButtonsContainerPanel, BorderLayout.WEST);
Vector<String> gameList = new Vector<>();
gameList.add("Game 1");
gameList.add("Game 2");
gameList.add("LongNameGame 3");
JList<String> gameJList = new JList<>(gameList);
JPanel gameListPanel = new JPanel(new FlowLayout());
gameListPanel.setMinimumSize(new Dimension(600,600)); // <-- has no effect
gameListPanel.add(gameJList);
gameListControlPanel.add(gameListPanel, BorderLayout.EAST);
loungeFrame.add(gameListControlPanel, BorderLayout.WEST);
// center panel in the lounge is for chat messages; it has a separate border layout,
// center for accumulated messages, bottom for entering messages
JPanel chatMessagePanel = new JPanel(new BorderLayout());
// Border chatMessagePanelBorder = BorderFactory.createEmptyBorder(7,7,7,7);
// chatMessagePanel.setBorder(chatMessagePanelBorder);
JTextArea chatMessages = new JTextArea();
chatMessagePanel.add(chatMessages, BorderLayout.CENTER);
// debug
chatMessages.append("message one\n");
chatMessages.append("message two\n");
chatMessages.append("message three\n");
// and lower panel is for entering one's own chat messages
JPanel chatMessageEntryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JTextField chatMessageEntryField = new JTextField(35);
JButton chatMessageEntryButton = new JButton("Enter");
chatMessageEntryPanel.add(chatMessageEntryField);
chatMessageEntryPanel.add(chatMessageEntryButton);
chatMessagePanel.add(chatMessageEntryPanel, BorderLayout.SOUTH);
loungeFrame.add(chatMessagePanel, BorderLayout.CENTER);
loungeFrame.pack();
return loungeFrame;
}
private static void addButtons(JPanel panel, String ... labels)
{
for (String label : labels)
{
JButton button = new JButton(label);
panel.add(button);
}
}
}
Give the JList a prototype cell value that is wide enough to display what you need. e.g.,
gameJList.setPrototypeCellValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
The prototype value (here a String because the list has been declared as a JList<String>) is used to set the list's preferred size, but is not displayed in the JList. You can use as large or small a list as you need. Also be sure to set visible row count for the same purpose in the horizontal dimension:
gameJList.setVisibleRowCount(20); // for example

Java dynamically changing components when scrollbar appears

I'm trying to implement a feature that (in my test project) once a button is pressed, it adds a random number to my JPanel. (I use the layouts I have because in my real program, I have more items inside and it displays correctly). But I need my program to recognize when the scrollbar is visible (which I implemented that, but it's a little delay. What I mean by delay is I push the button to add a number, if the scrollbar becomes visible nothing happens. But then the next time I press the button it shifts over like I want). The other problem I have (the one I'm focused on now) is that when I dynamically change the size of the JPanel, if the scrollbar is visible, I have it set to change the width to my width - the width of the scrollbar. But It seems like when the scrollbar is visible, the newly inputted number moves over twice the scrollbar width instead of just once. I've been at this part of my program for over a day and can't figure it out. I'll add my full code and some screenshots.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
JFrame frame;
JPanel topPanel;
JPanel memoryPanel;
JScrollPane sPane;
JButton button;
ArrayList<Integer> list = new ArrayList<>();
boolean isVScrollVisible = false;
int scrollBarSize = 0;
public class MyChangeListener implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
isVScrollVisible = (sPane.getVerticalScrollBar().isVisible());
}
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
Random random = new Random();
int r = random.nextInt(10);
list.add(r);
int n;
if (isVScrollVisible) {
n = scrollBarSize;
} else {
n = 0;
}
JPanel nextPanel = new JPanel();
nextPanel.setName("" + r);
nextPanel.setForeground(Color.BLACK);
nextPanel.setPreferredSize(new Dimension(200 - n, 55));
nextPanel.setMinimumSize(new Dimension(200 - n, 55));
nextPanel.setMaximumSize(new Dimension(200 - n, 55));
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BorderLayout());
JLabel label = new JLabel();
label.setText("" + r);
label.setPreferredSize(new Dimension(200 - n, 55));
label.setMinimumSize(new Dimension(200 - n, 55));
label.setMaximumSize(new Dimension(200 - n, 55));
label.setHorizontalAlignment(JLabel.RIGHT);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 17));
label.setFont(new Font("Sans-Serif", Font.BOLD, 20));
labelPanel.add(label);
nextPanel.add(labelPanel, BorderLayout.LINE_START);
for (int i = 0; i < memoryPanel.getComponents().length; i++) {
memoryPanel.getComponent(i).setPreferredSize(new Dimension(200 - n, 55));
memoryPanel.getComponent(i).revalidate();
memoryPanel.getComponent(i).repaint();
}
memoryPanel.add(nextPanel, 0);
memoryPanel.revalidate();
memoryPanel.repaint();
sPane.revalidate();
sPane.repaint();
}
}
public Main() {
frame = new JFrame();
topPanel = new JPanel();
memoryPanel = new JPanel();
memoryPanel.setLayout(new BoxLayout(memoryPanel, BoxLayout.Y_AXIS));
sPane = new JScrollPane(memoryPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
sPane.setPreferredSize(new Dimension(200, 300));
sPane.getViewport().addChangeListener(new MyChangeListener());
scrollBarSize = ((Integer)UIManager.get("ScrollBar.width")) + 1;
button = new JButton("Add Random Number");
button.addActionListener(new ButtonListener());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
topPanel.add(button);
frame.add(topPanel, BorderLayout.PAGE_START);
frame.add(sPane, BorderLayout.CENTER);
frame.setResizable(false);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
I need them to look exactly the same. Before I had the code I have now, the scrollbar would appear over the numbers which looked ugly. And the reason I have the frame resizable false is because In my real program I hard coded all the sizes, which in the future I will calculate the correct sizes based on the size of the frame, so right now setting resizable to true is out of the question. Any suggestions on what to do?
This is what I'm trying to accompolish.
Get rid of all the logic that sets the preferred/minimum/maximum sizes. Each component knows what its size should be. Each layout manager will in turn know what the preferred size of the panel should be. Let the layout manager use the information to do its job.
The basic logic for dynamically adding components is:
panel.add(...);
panel.revalidate();
panel.repaint();
Then the scrollbars will appear automatically when required. There is no need for listeners or anything.
Edit:
The reason I set all the sizes is because If I take them out then everything appears centered
Learn how to use layout managers properly and effectively.
For example when using a BoxLayout you can control the alignment of components by using:
component.setAlignmentX(JLabel.RIGHT_ALIGNMENT);
and the component will be aligned to the right edge of the space available to the component.
When using a JLabel you may also need to set a property on the JLabel to align the text to the right edge of the label. Read the JLabel API for the appropriate method.

JLayeredPane not showing my custom JPanel

I'm having trouble getting my custom panel to show up using JLayeredPanel. I'm currently trying to create a black rectangle on the first layer, and on the second layer, I have a custom JPanel which is a slideshow of images. The slideshow will not display at all, it only works when I add it to the frame. Any thoughts?
Code:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class GUI extends JFrame {
private Container pane;
private JPanel emptySlideShow;
private JLayeredPane layeredPane;
public GUI(){
this.setVisible(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
this.setBounds(0,0,screenSize.width, screenSize.height);
// //Set up the content pane
// pane = this.getContentPane(); //get the content pane to place components
// pane.setLayout(null); //use absolute positioning (using Insets)
// pane.setBackground(new Color(236, 236, 236)); //color the background
//
// //Set up the main menu bar
this.emptySlideShow = new JPanel();
this.emptySlideShow.setBounds(0,0,(int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(),250);
this.emptySlideShow.setBackground(new Color(0,0,0));
layeredPane = new JLayeredPane();
layeredPane.setLayout(null);
layeredPane.add(this.emptySlideShow,new Integer(0));
ArrayList<Image> slides = new ArrayList<Image>();
Image image1 = new ImageIcon("pictures/slide1.png").getImage();
slides.add(image1);
Image image2 = new ImageIcon("pictures/slide2.png").getImage();
slides.add(image2);
ArrayList<String> transitions = new ArrayList<String>();
transitions.add("PanLR");
transitions.add("FadeOut");
this.add(new SlideShow(slides,transitions));
layeredPane.add(new SlideShow(slides,transitions),new Integer(1));
this.add(layeredPane);
}
}
A guess since we don't have all of the pertinent code -- but you need to specify a component's size and position when adding it to the JLayeredPane, and so perhaps you're not setting the SlideShow's size before adding it (it's position will by default be 0, 0).
Question though: Why are you trying to add a SlideShow JPanel to the GUI twice? Once to the JLayeredPane, and the other to the JFrame itself?
Simple. You are adding the components (including JLayeredPane) to the frame AFTER you invoke
this.setVisible(true);
Move this line to the end of the constructor and you should be fine or if you really want to keep this line at the top, you should call revalidate() to update the JFrame and components.

JTabbedPane image alignment

I made a quick research to solve this problem but until now I found nothing regarding to this. I have one image into one TabbedPane object but when I try to align this image on the center of the label inside the TabbedPane it "Doesn't" work. The center alignment in this case works only for horizontal view but I want to be in the center of both vertical and horizontal. Check out the sample below:
import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import com.sh.st.gui.MainScreen;
public class test {
JTabbedPane tabbedPane = new JTabbedPane();
JFrame mainFrame = new JFrame();
public static void main (String[] args){
test t = new test();
}
public test(){
JPanel entrance = new JPanel();
JLabel lbImage1;
JMenuBar bar;
JMenu file, registerQuery;
ImageIcon Logo= new ImageIcon("rsc/img/imagem.jpg");
lbImage1= new JLabel(Logo, JLabel.CENTER);
entrance.add(lbImage1);
tabbedPane.addTab("Entrance", null, entrance);
mainFrame.getContentPane().add( tabbedPane, BorderLayout.CENTER);
bar= new JMenuBar();
file= new JMenu("File");
registerQuery= new JMenu("Request");
mainFrame.setVisible(true);
}
}
I guess its not so hard to do what I want but until now as I said, I found nothing, anyone could help please? thanks in advance
The JLabel alignment will only center horizontally due to the potitioning characteristics of its parent container. In this case it is the default layout for JPanel which is FlowLayout. This layout manager does not facilitate easy vertical alignment.
Provided that the JLabel lbImage1 will be the only component on the JPanel entrance, then GridLayout can be used to center the JLabel both horizontally and vertically:
entrance.setLayout(new GridLayout());

Categories

Resources