In my code i transfer the JPanel (Bestellpanel) from frame to frame1. After that, everytime i use the frame1 scrollbar it repaints frame1and my JPanel (Bestellpanel) is gone. That means I need a way to stop my JPanel getting overpainted. I read something about super.paint(); and other methods but I have major problems understanding them.
Here is a code example of my problem:
import java.awt.Color;
import javax.swing.JPanel;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
public class weqe {
private static JFrame frame = new JFrame("First Frame");
private static JFrame frame1 = new JFrame("Second Frame");
private static JPanel Bestellpanel = new JPanel();
private static int kunde = 1;
public static void addComponentsToPane(final Container pane) {
pane.setLayout(null);
final Insets insets1 = pane.getInsets();
// Mitn Button
JButton MitnIcon = new JButton("Mitnehmen");
MitnIcon.setFocusPainted(false);
MitnIcon.setVisible(true);
Dimension size2 = MitnIcon.getPreferredSize();
MitnIcon.setBounds(1010 + insets1.left, 700 + insets1.top,
size2.width + 27, size2.height + 50);
pane.add(MitnIcon);
MitnIcon.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
if (kunde == 1) {
frame.getContentPane().remove(Bestellpanel);
Bestellpanel.setLocation(0, 0);
frame1.getContentPane().add(Bestellpanel);
Bestellpanel.repaint();
frame.repaint();
}
}});
// ScrollPane
JPanel panel1 = new JPanel();
panel1.setPreferredSize(new Dimension(2000,800));
panel1.setVisible(false);
JScrollPane scrollPane = new JScrollPane (panel1,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
frame1.add(scrollPane);
Bestellpanel.setBounds(930 + insets1.left, 50 + insets1.top,size2.width
+ 30, size2.height + 400);
Bestellpanel.setVisible(true);pane.add(Bestellpanel);
Bestellpanel.setBackground(Color.green);
}
private static void createAndShowGUI() {
//Create and set up the window.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addComponentsToPane(frame.getContentPane());
//Size and display the window.
Insets insets = frame.getInsets();
Insets insets1 = frame1.getInsets();
frame.setSize(1200 + insets.left + insets.right,
900 + insets.top + insets.bottom);
frame.setVisible(true);
frame1.setSize(800 + insets1.left + insets1.right,
600 + insets1.top + insets1.bottom);
frame1.setVisible(true);
frame.add(Bestellpanel);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
meinJDialog.setSize(800,800); and panel1.setPreferredSize(new Dimension(2000,800)); most likely are part of your problem, see Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? (The general consensus says yes and to override getPreferred|Maximum|MinimumSize() methods instead)
Instead of removing/adding the JComponents yourself, try out Card Layout
You don't need to manually change component's visibility, again, check the link in point number 2, for this line: Bestellpanel2.setVisible(true);
Please follow the Java naming conventions: FirstWordUpperCaseClass, firstWordLowerCaseVariable, firstWordLowerCaseMethod() and ALL_WORDS_UPPER_CASE_CONSTANT), so, your code is easier to read and understand for you and for us.
If all the above points don't work, then consider posting a valid Minimal, Complete and Verifiable Example (MCVE) or Short, Self Contained, Correct Example (SSCCE) that demonstrates your issue, has no external dependencies or customizations such as background color / image, etc. It should be indented correctly, as said in the comments above.
Related
I have a JScrollPane with a JPanel in it that works perfectly, except for one flaw. When I run the program, the JScrollPane is added and shows up on its parent panel just fine, however the content inside it does not show up.
If I resize the window or if I scroll on the JPanel the content shows up immediately. I have also checked and the dimensions are correct for both the JPanel and the JScrollPane. Repaint is also called so I don't think I'm missing anything there.
I did also look at this question but it didn't help:
JScrollPane doesn't show scroll bars when JPanel is added
Null layouts being used are intentionally, I'm doing my own formatting instead to account for multiple size screens. Thank you ahead of time!
class FilesPanel extends JPanel
{
public JScrollPane scroller;
private FileHolderPanel holder;
public FilesPanel()
{
//setLayout(null);
setBackground(extraLight);
holder = new FileHolderPanel();
System.out.println(holder.getWidth() + " " + holder.getHeight() + " " + holder.getX() + " " + holder.getY() + " " + holder.getBounds());
scroller = new JScrollPane();
JViewport viewport = new JViewport();
viewport.add(holder);
scroller.setViewport(viewport);
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroller.setBorder(BorderFactory.createEmptyBorder());
scroller.setBackground(blue);
add(scroller);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
scroller.setLocation(0, 0);
scroller.setSize(filesWidth, frame.getHeight() - 40);
}
class FileHolderPanel extends JPanel
{
public FileHolderPanel()
{
setBackground(extraLight);
setLayout(null);
setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
}
}
The "main" issue is the fact that FileHolderPanel has not concept of the size it might like to be, so the JScrollPane has no really of how large it needs to be or when it should display its scroll bars. This is a bit of guess work, as you've not provided a fully runnable example.
Something like the below example works fine...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new ContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ContentPane extends JPanel {
public ContentPane() {
setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(new FileHolderPane());
scrollPane.setBorder(BorderFactory.createEmptyBorder());
scrollPane.setBackground(Color.BLUE);
add(scrollPane);
}
}
public class FileHolderPane extends JPanel {
public FileHolderPane() {
setBackground(Color.RED);
setLayout(new GridBagLayout());
add(new JLabel("All your content is belong to us"));
}
#Override
public Dimension getPreferredSize() {
// This will make the panel a fixed size, so beware of that
return new Dimension(400, 400);
}
}
}
If you need more control, then you'll probably need to look at the Scrollable interface, but that's another level of complexity
I am writing some Java code that allows the user to see a frame with JLabel, JTextField and JButton.
I want the JLabel to be called "Count" and I have a problem with FlowLayout.
I want the interface to look like this:
Instead, I have this:
This is my code:
package modul1_Interfate_Grafice;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Exercitiu04 implements ActionListener {
private JFrame frame;
private JLabel labelCount;
private JTextField tfCount;
private JButton buttonCount;
private int count = 0;
public void go() {
frame = new JFrame("Java Counter");
labelCount = new JLabel("Counter");
labelCount.setLayout(new FlowLayout());
frame.getContentPane().add(BorderLayout.CENTER, labelCount);
tfCount = new JTextField(count + " ", 10);
tfCount.setEditable(false);
labelCount.add(tfCount);
buttonCount = new JButton("Count");
labelCount.add(buttonCount);
buttonCount.addActionListener(this);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(350, 150);
frame.setLocation(400, 200);
}
#Override
public void actionPerformed(ActionEvent event) {
count++;
tfCount.setText(count + "");
}
public static void main(String[] args) {
Exercitiu04 a = new Exercitiu04();
a.go();
}
}
Solve it.
Instead of labelCount.setLayout(new FlowLayout());` i should have had
frame.setLayout(new FlowLayout());
From description of JLabel class,
JLabel is:
A display area for a short text string or an image, or both.
But here: labelCount.add(tfCount) and here labelCount.add(buttonCount) you're trying to put a textfield and a button into a label. In this case, positions of button and textfield are controlled by FlowLayout but position of the text in the label is not.
Instead of this, you should put all of your elements in common JPanel, like this:
...
frame = new JFrame("Java Counter");
frame.setLayout(new BorderLayout());
JPanel wrapper = new JPanel(); // JPanel has FlowLayout by default
labelCount = new JLabel("Counter");
labelCount.setLayout(new FlowLayout());
wrapper.add(labelCount);
tfCount = new JTextField(count + " ", 10);
tfCount.setEditable(false);
wrapper.add(tfCount);
buttonCount = new JButton("Count");
buttonCount.addActionListener(this);
wrapper.add(buttonCount);
frame.add(BorderLayout.CENTER, wrapper);
...
And, like MasterBlaster said, you should put swing methods in EDT.
There are only two things you should know about FlowLayout:
a) It is a default layout manager of the JPanel component
b) It is good for nothing.
This trivial layout cannot be achieved with FlowLayout.
When doing layouts in Swing, you should familiarize yourself
with some powerful layout managers. I recommend MigLayout and
GroupLayout.
package com.zetcode;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
/*
Simple UI with a MigLayout manager.
Author Jan Bodnar
Website zetcode.com
*/
public class MigLayoutCounterEx extends JFrame {
public MigLayoutCounterEx() {
initUI();
}
private void initUI() {
JLabel lbl = new JLabel("Counter");
JTextField field = new JTextField(10);
JButton btn = new JButton("Count");
createLayout(lbl, field, btn);
setTitle("Java Counter");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
setLayout(new MigLayout());
add(arg[0]);
add(arg[1]);
add(arg[2]);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MigLayoutCounterEx ex = new MigLayoutCounterEx();
ex.setVisible(true);
});
}
}
The example is trivial. You just put the three components into the
cells.
Screenshot:
You shouldn't use setSize when dealing with FlowLayout. Instead use pack(). It makes the window just about big enough to fit all your components in. That should tidy things up for you
I have a problem which is most likely "simple" however I can't figure it out. I am trying to reference my current JFrame so that I can dispose of it, and create a new one, thus "resetting" the program, however I and having trouble figuring out how to reference the JFrame, I have tried, super, this and getParent(), but none of the seem to work. Thanks for any / all help. ^^
Here is my code:
Main Class, just sets up the Jframe and calls the class that creates everything:
public static void main(String args[]) {
JFrame window = new JFrame();
Director director = new Director(window, args);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.pack();
window.setVisible(true);
}
}
Class the creates everything:
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class Director extends JFrame implements CollisionListener {
private BrickWall wall;
private JLabel gameTitle, gameScore, gameLives;
private JPanel controlPanel;
private JButton reset, quit;
private JRadioButton hard, normal, easy;
private int score = 6, lives = 5;
private ButtonGroup difficulty;
public Director(JFrame window, String[] args) {
window.getContentPane().add(makeGamePanel(), BorderLayout.CENTER);
window.getContentPane().add(gameControlPanel(), BorderLayout.NORTH);
}
public void collisionDetected(CollisionEvent e) {
wall.setBrick(e.getRow(), e.getColumn(), null);
}
private JComponent makeGamePanel() {
wall = new BrickWall();
wall.addCollisionListener(this);
wall.buildWall(3, 6, 1, wall.getColumns(), Color.GRAY);
return wall;
}
// Reset method I'm trying to dispose of the JFrame in.
private void reset() {
JFrame frame = new JFrame();
frame.getContentPane().add(makeGamePanel(), BorderLayout.CENTER);
frame.getContentPane().add(gameControlPanel(), BorderLayout.NORTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
private JComponent gameControlPanel() {
// CONTROL PANEL PANEL!
controlPanel = new JPanel();
gameTitle = new JLabel("Brickles");
gameScore = new JLabel("Score:" + " " + score);
gameLives = new JLabel("Lives:" + " " + lives);
reset = new JButton("Reset");
quit = new JButton("Quit");
hard = new JRadioButton("Hard", false);
normal = new JRadioButton("Normal", true);
easy = new JRadioButton("Easy", false);
difficulty = new ButtonGroup();
difficulty.add(hard);
difficulty.add(normal);
difficulty.add(easy);
controlPanel.setLayout(new GridLayout(4, 2));
controlPanel.add(gameTitle);
controlPanel.add(gameScore);
controlPanel.add(hard);
controlPanel.add(gameLives);
controlPanel.add(normal);
controlPanel.add(reset);
controlPanel.add(easy);
controlPanel.add(quit);
// Action Listener, where I'm caling the reset method.
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
reset();
}
});
return controlPanel;
}
}
You can refer to the "outer this" from a nested class with the following syntax:
reset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Director.this.reset();
}
});
Yes, you can refer to the outer class by specifying it with the class name as noted in DSquare's good answer (1+ to it), but I urge you not to fling JFrame's at the user as you're program is trying to do. I recommend:
Instead of opening and closing multiple JFrames, use only one JFrame as the main application's window.
If you need helper windows, such as modal windows to get critical information that is absolutely needed, before the program can progress, use modal dialogs such as JDialogs or JOptionPanes.
If you need to swap GUI's, instead of swapping JFrames, swap "views" inside the JFrame via a CardLayout.
Gear your code towards creating these JPanel views and not JFrames as it will make your Swing GUI's much more flexible and portable.
My program writes text in a JProgressBar. The problem is the text is wider than the JProgressBar's width.
I have already changed the JProgressBar's height to be able to write the text on two lines but I don't want to the change the width.
How to change the JProgressBar's overflow to make the text going back to the next line if it is too wide?
I hope this is clear enough :)
Here is what I would like:
Thanks
EDIT
After #mKorbel reply the result looks like this:
The label works quite fine but why those strips?
My code:
// Construct progress bar
JProgressBar progressBar = new JProgressBar(0, 100);
// Set progressBar color
progressBar.setForeground(new Color(0,176,80));
// Edit progress bar height
Dimension prefSize = progressBar.getPreferredSize();
prefSize.height = 50;
progressBar.setPreferredSize(prefSize);
// Set the layout
progressBar.setLayout(new BorderLayout(5, 5));
// Set progress bar value
progressBar.setValue(38);
// Construct the label
JLabel progressLabel = new JLabel("<html>I have already changed the JProgressBar's height to be able to write the text on two lines but I don't want to the change the width.</html>");
// Set alignment
progressLabel.setHorizontalAlignment(JLabel.CENTER);
progressLabel.setVerticalAlignment(JLabel.CENTER);
// Set the borders
progressLabel.setBorder(new EmptyBorder(15, 15, 15, 15));
// Change the font
font = progressLabel.getFont();
font = font.deriveFont(Font.BOLD, 12);
progressLabel.setFont(font);
// Add label to the progress bar
progressBar.add(progressLabel, BorderLayout.CENTER);
// Add progress bar to the frame
frame.add(progressBar);
the program is developed with Java 6. It seems JLayer is not
available. If I'm wrong, could you provide some code on how to do
this?
could you provide some code on how to do this? --- > JLayer & JProgressBar by #aterai, for more ideas see his blog, for Java6 you can to use JXLayer
or with very similair logics by using GlassPane
some notes
should be used GBC instead of NullLayout
can be nicer with added Icon or transparent background
(by add LayoutManager to JLabel) there can be placed bunch of JComponents with the same effect as for JPanel
for example
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.UIManager;
//https://stackoverflow.com/questions/14560680/jprogressbar-low-values-will-not-be-displayed
public class ProgressSample {
private JFrame frame = new JFrame("GlassPane instead of JLayer");
private JLabel label;
private GridBagConstraints gbc = new GridBagConstraints();
private JProgressBar progressSeven;
public ProgressSample() {
frame.setLayout(new FlowLayout());
frame.add(new JButton("test"));
frame.add(new JCheckBox("test"));
frame.add(new JRadioButton("test"));
// Nothing is displayed if value is lover that 6
JProgressBar progressSix = new JProgressBar(0, 100);
progressSix.setValue(2);
frame.add(progressSix);
// but this works value is higher that 6
progressSeven = new JProgressBar(0, 100);
progressSeven.addComponentListener(new ComponentAdapter() {
#Override
public void componentMoved(ComponentEvent e) {
label.setBounds(
(int) progressSeven.getBounds().getX(),
(int) progressSeven.getBounds().getY(),
label.getPreferredSize().width,
label.getPreferredSize().height);
}
});
progressSeven.setValue(7);
frame.add(progressSeven);
label = new JLabel();
label.setText("<html> Concurency Issues in Swing<br>"
+ " never to use Thread.sleep(int) <br>"
+ " durring EDT, simple to freeze GUI </html>");
label.setPreferredSize(new Dimension(label.getPreferredSize().width, label.getPreferredSize().height));
Container glassPane = (Container) frame.getRootPane().getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(null);
glassPane.add(label, gbc);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
ProgressSample dialogTest = new ProgressSample();
}
}
EDIT
comments
my first thought was using html, but astonishingly (for me) the
progressbar doesn't support it ... by #kleopatra
and
I think my question may not be clear enough. I don't want the text to
exceed the JProgressBar borders. Plus, I don't want to insert manually
line returns (ie no ). I added a picture of what I want. by
#Maxbester
result is to use JProgressBar as Container, put there proper LayoutManager, overlay JProgressBar by JLabel
enhancements, to set EmptyBorder for JLabel, e.g. label.setBorder(new EmptyBorder(15, 15, 15, 15));
EDIT2 (Icon is, can be semi_transparent too, can overlay JProgressBar)
code could be something like as
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
public class JProgressBarWithJLabel {
private JFrame frame = new JFrame("JLabel in JProgressBar");
private JLabel label;
private JProgressBar progressSeven;
public JProgressBarWithJLabel() {
progressSeven = new JProgressBar(0, 100){
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 60);
}
};
progressSeven.setValue(38);
progressSeven.setLayout(new BorderLayout(5, 5));
label = new JLabel();
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
label.setBorder(new EmptyBorder(15, 15, 15, 15));
label.setText("<html>I have already changed the JProgressBar's height "
+ "to be able to write the text on two lines but I don't want "
+ "to the change the width.</html>");
progressSeven.add(label, BorderLayout.CENTER);
frame.add(progressSeven);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new JProgressBarWithJLabel();
}
});
}
}
EDIT3:
default stripping for WindowsClassicLookAndFeel (Icon isn't semi_transparent)
The available answers didn't satisfy me. Thus I implemented the following alternative solution for my own needs.
import javax.swing.JProgressBar;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
public class MultilineProgressBar extends JProgressBar
{
private static final String FONT_NAME = "Dialog";
private static final int FONT_SIZE = 12;
private static final int INTERLINE_COEFFICIENT = 2;
private static final int NEWLINE_OFFSET = FONT_SIZE * INTERLINE_COEFFICIENT;
private static final int CENTERING_DIVISOR = 2;
#Override
protected void paintComponent(final Graphics graphics)
{
super.paintComponent(graphics);
final String componentString = getString();
int i = componentString.indexOf('\n');
if (i == -1)
return;
// Draw first line of the component's string
String currentString = componentString.substring(0, i);
Rectangle2D stringBounds = getFontMetrics(getFont()).getStringBounds(currentString, graphics);
graphics.setFont(new Font(FONT_NAME, Font.BOLD, FONT_SIZE));
graphics.setColor(Color.WHITE);
graphics.drawString(currentString,
(int) (getWidth() - stringBounds.getWidth()) / CENTERING_DIVISOR,
(int) (getHeight() - stringBounds.getHeight()) / CENTERING_DIVISOR);
++i;
if (i >= componentString.length())
return;
// Draw second line of the component's string
currentString = componentString.substring(i);
stringBounds = getFontMetrics(getFont()).getStringBounds(currentString, graphics);
graphics.drawString(currentString,
(int) (getWidth() - stringBounds.getWidth()) / CENTERING_DIVISOR,
(int) ((getHeight() - stringBounds.getHeight()) / CENTERING_DIVISOR) + NEWLINE_OFFSET);
}
}
I am trying to create very simple class. The goal is to create a button in the maximum size when scrollbars are not visible yet. My code doesn`t work. The condition pane.getVerticalScrollBar().isVisible() returns true even if the scrollbar is not visible. I wonder why and how can I fix it?
import java.awt.BorderLayout;
import java.io.UnsupportedEncodingException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) throws UnsupportedEncodingException {
JFrame frame = new JFrame();
final JButton button = new JButton("Hello");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
final JPanel buttons = new JPanel();
buttons.add(button);
buttons.revalidate();
final JScrollPane pane = new JScrollPane(buttons);
pane.getViewport().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
System.out.println("*******************************************************************");
System.out.println("Vertical visible? " + pane.getVerticalScrollBar().isVisible());
System.out.println("Horizontal visible? " + pane.getHorizontalScrollBar().isVisible());
if (!pane.getVerticalScrollBar().isVisible() && !pane.getHorizontalScrollBar().isVisible()) {
button.setSize(button.getWidth() + 1, button.getHeight() + 1);
buttons.revalidate();
pane.revalidate();
} else {
button.setSize(button.getWidth() - 1, button.getHeight() - 1);
buttons.revalidate();
pane.revalidate();
pane.getViewport().removeChangeListener(this);
}
}
});
panel.add(pane);
frame.setContentPane(panel);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
Don't play with the set size method.
If you want the button to occupy all the space available then use either:
frame.add(button); // height/width will be max
frame.add(button, BorderLayout.SOUTH); // only width will be max
Let the layout managers do the job for you.
Edit:
I have another class which scale img in the label and I want to find the best value for scale to make it maximalized as possible
Create a custom panel and dynamically draw the image at the size of the panel. Then it will automatically scale based on the space available.
See Background Panel as an example of this approach.