I got an unexpected behavior on my JScrollPane:
My ScrollPanel is filled with different panels
(Transparency is needed because in the end I will have images in background instead of just colors)
I made a quick example of my problem:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.border.Border;
public class ScrollPaneTest extends JPanel{
ScrollPaneTest(){
JPanel Content = new JPanel();
BoxLayout ColumnLayout = new BoxLayout(Content,BoxLayout.Y_AXIS);
Content.setLayout(ColumnLayout);
for(int i = 0 ; i < 10 ; i++){
JPanel pane = new JPanel();
JLabel elem = new JLabel("element "+i);
pane.setBackground(new Color(0,0,0,125));
pane.add(elem);
Content.add(pane);
}
Content.setBackground(Color.ORANGE);
JScrollPane scrollPane = new JScrollPane(Content);
scrollPane.setPreferredSize(new Dimension(100,100));
scrollPane.setBackground(new Color(0,0,0,250));
add(scrollPane);
}
public static void main(String[] args) throws Exception {
JFrame f = new JFrame();
JPanel bck = new JPanel();
bck.setBackground(Color.RED);
bck.add(new ScrollPaneTest());
f.add(bck);
f.setSize(200, 200);
f.setVisible(true);
}
}
With this you can see that when I scroll, the graphics are all messed up :/
Thanks for Helping :p
I have the Following Solution for your Problem
When you scroll through the elements the elements are not repainted so you need to repaint them when you scroll the scroll bar. Add the following code after this line JScrollPane scrollPane = new JScrollPane(Content); it will work!
scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener(){
#Override
public void adjustmentValueChanged(AdjustmentEvent e) {
repaint();
}
});
Related
I'm trying to create a scrollable text area, (much like the one i'm writing in right now as in stack overflow's one). It seems as if the scrollpane and the text area are mutually exclusive and i'd like to create a connection between them
package Notepad;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JFrame;
import java.awt.BorderLayout;
import javax.swing.JTextArea;
import javax.swing.JScrollBar;
public class test {
private JFrame frame;
private Font f = new Font(null);
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
test window = new test();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public test() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout(0, 0));
JTextArea textArea = new JTextArea();
frame.getContentPane().add(textArea, BorderLayout.CENTER);
textArea.setLineWrap(true);
textArea.setFont(f.deriveFont(40f));
JScrollBar scrollBar = new JScrollBar();
frame.getContentPane().add(scrollBar, BorderLayout.EAST);
}
}
use JScrollPane rather than JScrollBar
Wrong:
JScrollBar scrollBar = new JScrollBar();
Right:
JScrollPane scroller = new JScrollPane(textArea);
you can set the size of this ScrollPane like so:
Dimension size = new Dimension (0, 50);
scroller.setPreferredSize(size);
NOTE: When you use JScrollPanes, be sure to put where you want it in parentheses, or it will not show up.
JTextArea textArea = new JTextArea();
textArea.setLineWrap(true);
textArea.setFont(f.deriveFont(40f));
JScrollPane scrollPane = new JScrollPane(textArea);
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
OMG sorry guys. I imported JScrollBar not JScrollPane. Thank you all. I'm going to test this fix and get back to you.
Edit:
It works. Thank you guys!!!
I have a JPanel, that lists a set of Jlabels. I would like to make the width of each label wide as the panel's size. So it will be wide but but text stays in the left. I am using BoxLayout to list labels.
Here is the code:
public class JavaApplication78 {
JFrame frame;
JPanel panel, labelsPanel;
JLabel label;
ArrayList<String> names = new ArrayList<String>();
ArrayList<JLabel> labelsArray = new ArrayList<JLabel>();
Border paddingBorder = BorderFactory.createEmptyBorder(10,10,10,10);
Border border = BorderFactory.createLineBorder(Color.BLUE);
JScrollPane labelsScroll;
public JavaApplication78(){
frame = new JFrame();
panel = new JPanel(new BorderLayout());
names.add(".mp3");names.add(".html");names.add(".jpeg");names.add(".mp4");names.add(".pdf");
labelsPanel = new JPanel();
labelsPanel.setLayout(new BoxLayout(labelsPanel, BoxLayout.PAGE_AXIS));
labelsScroll = new JScrollPane(labelsPanel);
for(String format : names){
label = new JLabel(format);
//icon
labelsArray.add(label);
labelsPanel.add(label);
label.setBorder(BorderFactory.createCompoundBorder(border,paddingBorder));
}
panel.add(labelsScroll, BorderLayout.CENTER);
frame.add(panel);
frame.setSize(200, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new JavaApplication78();
}
}
Currently I could give a border around each JLabel. The height of labels are ok, but width need to be as wide as the parent panel.
Any idea ?
You could use a GridBagLayout...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
public class JavaApplication78 {
JFrame frame;
JPanel panel, labelsPanel;
JLabel label;
ArrayList<String> names = new ArrayList<String>();
ArrayList<JLabel> labelsArray = new ArrayList<JLabel>();
Border paddingBorder = BorderFactory.createEmptyBorder(10, 10, 10, 10);
Border border = BorderFactory.createLineBorder(Color.BLUE);
JScrollPane labelsScroll;
public JavaApplication78() {
frame = new JFrame();
panel = new JPanel(new BorderLayout());
names.add(".mp3");
names.add(".html");
names.add(".jpeg");
names.add(".mp4");
names.add(".pdf");
labelsPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = GridBagConstraints.REMAINDER;
labelsScroll = new JScrollPane(labelsPanel);
for (String format : names) {
label = new JLabel(format);
//icon
labelsArray.add(label);
labelsPanel.add(label, gbc);
label.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder));
}
panel.add(labelsScroll, BorderLayout.CENTER);
frame.add(panel);
frame.setSize(200, 400);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
new JavaApplication78();
}
});
}
}
Or a JList, but in cases like this, I tend to like using the VerticalLayout from the SwingLabs SwingX library
BoxLayout respects the maximum size of the component and for a JLabel the maximum size is equal to the preferred size.
You can override the getMaximumSize() method:
label = new JLabel(format)
{
#Override
public Dimension getMaximumSize()
{
Dimension d = super.getMaximumSize();
d.width = Integer.MAX_VALUE;
return d;
}
};
label.setHorizontalAlignment(JLabel.CENTER);
This will then allow the label to expand horizontally to fill the width of the panel.
Or if you wanted you could use the Relative Layout. It functions much like the BoxLayout but has a few additional features. The basic code would be:
RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
JPanel labelsPanel = new JPanel( rl );
Use PreferredSize to set the dimension of the parent JPanel for your JLabels :
JLabel label = new JLabel() {
public Dimension getPreferredSize() {
return labelsPanel.getSize();
};
};
Unless you are obliged to use BoxLayout, maybe it's better to use GridBagLayout as suggested by #MadProgrammer in his comment.
EDIT :
You could also take a look at MigLayout. Adding components with it is very simple :
labelsPanel.setLayout(new MigLayout());
labelsPanel.add(label, "span") // span to take the whole row width.
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class ScrollJPanelDemo extends JFrame {
public ScrollJPanelDemo(){
setSize(480, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("Select one or more options : ");
JCheckBox jcb1 = new JCheckBox("Chandigarh");
JCheckBox jcb2 = new JCheckBox("Mohali");
JCheckBox jcb3 = new JCheckBox("Delhi");
JCheckBox jcb4 = new JCheckBox("Noida");
JCheckBox jcb5 = new JCheckBox("Mumbai");
JCheckBox jcb6 = new JCheckBox("Kolkata");
//creating JPanel to hold the checkboxes
JPanel jpnl = new JPanel();
jpnl.setLayout(null);
jpnl.setOpaque(true);
jcb1.setBounds(0,0,100,40);
jcb2.setBounds(0,60,100,40);
jcb3.setBounds(0,120,100,40);
jcb4.setBounds(0,180,100,40);
jcb5.setBounds(0,240,100,40);
jcb6.setBounds(0,300,100,40);
//adding check boxes and label to the JPanel
jpnl.add(label);
jpnl.add(jcb1);
jpnl.add(jcb2);
jpnl.add(jcb3);
jpnl.add(jcb4);
jpnl.add(jcb5);
jpnl.add(jcb6);
//creating the scroll pane that will scroll the panel.
JScrollPane jscrlPane = new JScrollPane(jpnl);
jscrlPane.setBounds(0,0,300,300);
jscrlPane.setHorizontalScrollBarPolicy
(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS) ;
jscrlPane.setVerticalScrollBarPolicy
(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
//adding that scroll pane to the frame.
getContentPane().add(jscrlPane);
setVisible(true);
}
public static void main(String args[]){
new ScrollJPanelDemo();
}
}
I'm new in Java Swing and try to use of Scroll pane on my Java code, but it's not working. The Scroll Pane is add on the frame in vertical direction but not worked.
You should create your own panel that extends JPanel containing all checkboxes and in this panel override getPreferredSize() method like:
#Override
public Dimension getPreferredSize()
{
return new Dimension( 300,300 );
}
and use it in your code:
...
// creating the scroll pane that will scroll the panel.
JScrollPane jscrlPane = new JScrollPane( new MyPanelWithCheckboxes() );
jscrlPane.setBounds( 0, 0, 300, 300 );
...
I see OP already set desired/correct answer for him, yet that solution does not work with dynamic content (in my case vertically on Y axis) so I "repaired" or updated - if you will - Mateusz's original answer so that now it actually works even with dynamic JPanel content (like when you adding to it other components on the run which was my case).
Here is my code (works, using it myself):
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JPanel;
public class JPanelForNullLayoutScroll extends JPanel {
int h;
#Override
public Dimension getPreferredSize() {
if (getComponentCount() > 0) {
h = 0;
for (Component c : getComponents()) {
h += c.getHeight();
}
} else {
h = 0;
}
// as I do not need width recount
//I set it to be taken directly from the component itself
Dimension d = new Dimension(getWidth(), h);
return d;
}
}
You can use it then in your code by implementing it like:
int tableW = 300;
int tableH = 300;
// JPANEL WITH NULL LAYOUT
JPanelForNullLayoutScroll container = new JPanelForNullLayoutScroll();
container.setLayout(null);
container.setVisible(true);
container.setEnabled(true);
container.setBounds(0, 0, tableW, tableH);
// SCROLLER
JScrollPane scrollPane = new JScrollPane(container);
scrollPane.setAlignmentX(JLabel.LEFT_ALIGNMENT);
scrollPane.getVerticalScrollBar().setUnitIncrement(8);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setBounds(0, 0, tableW, tableH);
I've made a GUI using swing with a BorderLayout and GridLayout in the center. I want to add a triangle I've made in another class to the JPanel east in my BorderLayout but cant get it to show.
When I set a bgcolor for said JPanel I got a weird little result, if you like you can have a look at the code: gistlink
I have a feeling the issue is in the TriGoButton constructor but I'm not sure how to test further. I've tried different variations of paint() but have never been able to see the green triangle.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
#SuppressWarnings("serial")
public class TestGUI extends JFrame implements ActionListener {
private JPanel content;
private JTextField placeTxtField;
public static void main(String[] args) {
TestGUI frame = new TestGUI();
frame.pack();
frame.setVisible(true);
}
#SuppressWarnings("rawtypes")
public TestGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
content = new JPanel();
content.setLayout(new BorderLayout());
setContentPane(content);
// issue
JPanel rightPanel = new JPanel();
content.add(rightPanel, BorderLayout.EAST);
rightPanel.add(new TriGoButton());
// issue?
JPanel leftPanel = new JPanel();
content.add(leftPanel, BorderLayout.WEST);
JPanel centerPanel = new JPanel();
content.add(centerPanel, BorderLayout.CENTER);
centerPanel.setLayout(new GridLayout(3, 3, 0, 20));
JLabel countyLbl = new JLabel("County");
centerPanel.add(countyLbl);
JComboBox countyDropDown = new JComboBox();
centerPanel.add(countyDropDown);
JLabel muniLbl = new JLabel("Munipalicity");
centerPanel.add(muniLbl);
JComboBox muniDropDown = new JComboBox();
centerPanel.add(muniDropDown);
JLabel placeLbl = new JLabel("City or place");
placeLbl.setToolTipText("search");
centerPanel.add(placeLbl);
placeTxtField = new JTextField();
centerPanel.add(placeTxtField);
placeTxtField.setColumns(15);
placeTxtField.setToolTipText("enter w/e");
JPanel bottomPanel = new JPanel();
content.add(bottomPanel, BorderLayout.SOUTH);
JButton goBtn = new JButton("Clicky");
bottomPanel.add(goBtn);
goBtn.setToolTipText("Please click.");
goBtn.addActionListener(this);
JPanel topPanel = new JPanel();
content.add(topPanel, BorderLayout.NORTH);
JLabel headlineLbl = new JLabel("headline");
topPanel.add(headlineLbl);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class TriGoButton extends JPanel {
public TriGoButton() {
add(new JPanel(), BorderLayout.EAST);
setBackground(new Color(100,100,250)); //blue //wtf
}
public void paint(Graphics g) {
super.paint(g);
int[]x={90,90,300};
int[]y={150,0,90};
g.setColor(new Color(23,201,10)); //green
g.fillPolygon(x,y,3);
}
}
EDIT:
////////////
I don't know why you are adding a JPanel to your TriGoButton class, but this is going to cause you issues.
It's not recommended that you override paint, this can cause no end of issues, as the parent container isn't always included in updates when it's children are painted. See Painting in AWT and Swing and Performing Custom Painting for more details.
BorderLayout will use the component's preferredSize tomake decisions about how it should sized. Your TriGoButton class should override the getPreferredSize method and return an appropriate default size..
I've added your code. I think that your issue is that your TriGoPanel doesn't override getPreferredSize, and so it may be sizing itself quite small. Consider adding to the class something like:
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
where you have int constants, PREF_W, PREF_H, for your width and height dimensions.
__________________________________________________
Edit: and I strongly second everything that MadProgrammer recommended!
I'm tried to add a JPanel to a JScrollPane using:
panel1 Panel1 = new panel1();
jScrollPane1.setViewportView(Panel1);
and it worked. But the problem is scrollPane doesn't show scroll bars even the Panel1 is bigger. (I'm working with NetBeans & panel1 is a jpanel form)
Override, getPreferredSize() method for the said JScrollPane, you might be able to see the Scroll Bar. Or one can simply call setPreferredSize(), though as stated in the API
Sets the preferred size of this component. If preferredSize is null, the UI will be asked for the preferred size
overriding will be beneficial, as it tends to define some appropriate dimensions to the said JComponent.
Something like this:
JScrollPane scroller = new JScrollPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
};
scroller.setViewportView(panelWithScroll);
One example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PanelScroller {
private void displayGUI() {
JFrame frame = new JFrame("Swing Worker Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
JPanel panelWithScroll = new JPanel();
panelWithScroll.setLayout(new GridLayout(0, 1, 5, 5));
JScrollPane scroller = new JScrollPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
};
scroller.setViewportView(panelWithScroll);
//scroller.setPreferredSize(new Dimension(300, 200));
for (int i = 0; i < 20; i++) {
panelWithScroll.add(new JLabel(Integer.toString(i + 1), JLabel.CENTER));
}
contentPane.add(scroller);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new PanelScroller().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
If you only want the scrollbars to show up you can call
JScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
But that don't make them work at all.
if you wont to make them work you can try to set the preferred size of the component inside the Scrollpane to larger then size of Scrollpane and then call repaint(e.g. by make the window fullscreen)