Scroll Bars For Multiple JTextPanes (Java) - java

Attached is my window code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import java.awt.BorderLayout;
import javax.swing.JTextPane;
public class Window extends JFrame{
private JPanel panel;
private JTextPane textPane;
private JTextPane textPane_1;
public Window() {
super("Window");
this.init();
this.setSize(800, 600);
this.setVisible(true);
}
void init(){
panel = new JPanel();
getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(null);
textPane = new JTextPane();
textPane.setBounds(6, 48, 788, 185);
panel.add(textPane);
textPane.setFocusable(true);
textPane_1 = new JTextPane();
textPane_1.setBounds(6, 346, 788, 185);
panel.add(textPane_1);
JScrollPane scroll1 = new JScrollPane(textPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll1.setViewportView(textPane);
panel.add(scroll1);
this.add(scroll1);
JScrollPane scroll2 = new JScrollPane(textPane_1, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll2.setViewportView(textPane);
panel.add(scroll2);
this.add(scroll2);
this.add(panel);
}
}
My objective is for both JTextPanes to have their own scroll bars. All that appears on the screen though is a single JTextPane (not sure which one), and it has only a vertical scroll bar (I think this is because JTextPanes have word wrap). The second JTextPane isn't showing up. Can anyone help me?
Thanks in advance to all who reply.

You can use GridLayout in this case. See Swing Tutorial on How to Use GridLayout
Here is the code with GridLayout along with inline comments.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class MyWindow extends JFrame {
private JPanel panel;
private JTextPane textPane;
private JTextPane textPane_1;
public MyWindow() {
super("Window");
this.init();
}
void init() {
// panel with GridLayout having 2 rows and 1 column
panel = new JPanel(new GridLayout(2,1));
textPane = new JTextPane();
// enclose the text pane inside the scroll pane
// scroll pane shows scrollbars when needed
JScrollPane scroll1 = new JScrollPane(textPane);
// add scroll pane at first column of the first row
// never add text pane again in the panel because
// it's already added in scroll pane
panel.add(scroll1);
textPane_1 = new JTextPane();
JScrollPane scroll2 = new JScrollPane(textPane_1);
// add scroll pane at first column of the second row
panel.add(scroll2);
// finally add the panel in the JFrame's content pane in the center
getContentPane().add(panel, BorderLayout.CENTER);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
MyWindow window=new MyWindow();
window.setVisible(true);
}
});
}
}
snapshot:
Please have a look at Swing Tutorial on How to Use Various Layout Managers

Two points to start with, first, JFrame uses a BorderLayout by default, a BorderLayout only allows a single component to occupy any one of its five available positions. Second a component can only belong to a single parent
Taking a look at your code...
scroll1.setViewportView(textPane);
panel.add(scroll1);
this.add(scroll1);
//...
scroll2.setViewportView(textPane);
panel.add(scroll2);
this.add(scroll2);
this.add(panel);
You set textPane as the viewport view for scroll1
You add scroll1 to panel
You add scroll to this, effectively removing it from panel...
You set textPane as the viewport view of scroll2, removing it from the viewport for scroll1
You add scroll2 to the panel
You add scroll2 to this, effectively removing it from panel...
You add panel to this, overriding everything that was added to the frame previously...
This effectively means that panel is the only visible component the BorderLayout will try to layout on the frame, but it contains nothing
Instead, you could specify a position for each scroll pane when adding it to the frame, for example..
scroll1.setViewportView(textPane);
this.add(scroll1, BorderLayout.NORTH);
//...
scroll2.setViewportView(textPane_1);
this.add(scroll2, BorderLayout.SOUTH);
Updated with working example
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Window extends JFrame {
private JTextPane textPane;
private JTextPane textPane_1;
public Window() {
super("Window");
this.init();
this.setSize(800, 600);
this.setVisible(true);
}
void init() {
textPane = new JTextPane();
textPane_1 = new JTextPane();
JScrollPane scroll1 = new JScrollPane(textPane);
scroll1.setViewportView(textPane);
JScrollPane scroll2 = new JScrollPane(textPane_1);
add(scroll1, BorderLayout.NORTH);
add(scroll2, BorderLayout.SOUTH);
}
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();
}
Window frame = new Window();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This is the default behaviour for a JTextPane, it's overall size is determine by the size of it's content...
Now, you can make suggestions to the scrollpane about how much space your component would like to use by using the Scrollable interface and specifying the "initial", PreferredScrollableViewportSize...
Lucky for you, JTextPane already implements this interface, so you only need to override the getPreferredScrollableViewportSize method, for example...
textPane = new JTextPane() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
textPane_1 = new JTextPane() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
Take a look at Laying Out Components Within a Container for more details
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify

Related

How can I add a scroll bar to a text area?

Please, anyone, tell me how to add the scrollbar to a JTextArea. I tried out many things. but still not able to get it. I copied some codes related to the text area.
public class main extends JPanel {
private JTextArea jcomp1;
public main() {
jcomp1 = new JTextArea(5, 5);
setPreferredSize(new Dimension(944, 574));
// setPreferredSize (new Dimension (1024, 1080));
setLayout(null);
//add components
add(jcomp1);
jcomp1.setBounds(110, 165, 330, 300);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Paraphrasing Tool");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new main());
frame.pack();
frame.setVisible(true);
}
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Netbeans section.
As Andrew said, you have to place the JTextArea inside of a JScrollPane, then place the JScrollPane inside of a JPanel with a Swing layout. I used a BorderLayout.
Here's the GUI after I typed some lines.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class JTextAreaExample extends JPanel {
private static final long serialVersionUID = 1L;
private JTextArea jcomp1;
public JTextAreaExample() {
this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
this.setLayout(new BorderLayout());
jcomp1 = new JTextArea(5, 30);
jcomp1.setMargin(new Insets(5, 5, 5, 5));
JScrollPane scrollPane = new JScrollPane(jcomp1);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
add(scrollPane);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Paraphrasing Tool");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JTextAreaExample(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
}
Add the text area to (the viewport of) a JScrollPane. The easiest way is to add it in the constructor. Then add the scroll pane to a panel with a layout (in a GUI that uses layouts).

BorderLayout doesn't honor maximumsize

I have a problem using BorderLayout, but first of all, here is my GUI setup:
As you can see, I have 3 different components inside my JFrame. Adding the JMenu and JList works fine. But my JPanel should have a fixed size so I want to prevent my BorderLayout from stretching the panel. I tried everything, setPreferredSize() setMinimumSize() setMaximumSize() setSize() but again the layout stretches my panel to fit to the frame. (The panel is added to the frame using BorderLayout.CENTER).
Is there any way to prevent this or do you have other suggestions to manage the problem?
I'm pretty sure you mean BorderLayout, not BoxLayout, because there is no BoxLayout.CENTER and it looks like you use a BorderLayout to place the components.
I think the problem here is that you only set the preferred size of the panel that you add to BorderLayout.CENTER. This doesn't have any effect. Instead you need nested layouts.
In this example I added the JPanel called centerPanel, which is using a standard GridBagLayout (to center the added component), to BorderLayout.CENTER. Then I added the additional JPanel called panel, which has a custom preferrdSize, to centerPanel. This way panel won't get stretched.
Code:
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.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class Example {
public Example() {
JMenuBar menuBar = new JMenuBar();
menuBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));
DefaultListModel<String> listModel = new DefaultListModel<String>();
JList<String> list = new JList<String>(listModel);
list.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Uncomment the following lines if you also want to prevent the
// 'wrapping' of the panel.
/*
* #Override public Dimension getMinimumSize() { return new
* Dimension(400, 400); }
*/
};
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (int i = 1; i <= 5; i++) {
menuBar.add(new JMenu("Menu " + i));
listModel.addElement("Element " + i);
panel.add(new JLabel("Label " + i));
}
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(panel);
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.add(menuBar, BorderLayout.NORTH);
contentPanel.add(list, BorderLayout.WEST);
contentPanel.add(centerPanel);
JFrame frame = new JFrame();
frame.setContentPane(contentPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
Add your existing JPanel to a JPanel having Flowlayout, the default, or having GridBagLayout with default constraints. Add this panel to the frame's center, BorderLayout.CENTER by default.
Panel centerPane = new Panel(new GridBagLayout())`;
centerPane.add(yourJPanel);
frame.add(centerPane, BorderLayout.CENTER);
Also consider using Box, rather than a JPanel having BoxLayout.
Also consider using the frame's setJMenuBar(), rather than add(BorderLayout.PAGE_START).

Recommended layout for component that always stays in the same place on the x-axis?

My situation is a bit complex, so rather than explain I'll just show a picture of what I currently have:
The idea is that I want to move the instrument selector (the combo box that says "Flute" in each staff) above the staff. However, I always want to keep it in the same place, on the left directly above the staff, even when scrolling horizontally. When scrolling vertically, it should move so that it is always directly above its staff. Kind of like a toolbar. The problem is that it's already inside of a JScrollPane (as there could be multiple staves and you need to scroll both axes and there's one "instrument panel" per staff (though eventually there will be other UI elements to interact with in this pseudo-toolbar local to to staff in which it is attached)). Is this something where using absolute positioning + listening for scroll/resize/window move events is needed? Or is there perhaps a layout I'm not aware of that can do this sort of thing?
Thanks for looking!
Add the components to individual scroll panes, but never show the horizontal scrollbar
Have all the scroll panes share the same BoundRangeModel.
Create a separate JScrollBar component that uses this model. Whenever its scrolls the separate scroll panes will also scroll:
Something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class ScrollSSCCE extends JPanel
{
public ScrollSSCCE()
{
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
BoundedRangeModel model = null;
for (int i = 0; i < 5; i++)
{
JLabel label = new JLabel("Flute " + i);
label.setAlignmentX(JComponent.LEFT_ALIGNMENT);
add( label );
JTextArea textArea = new JTextArea(3, 20);
textArea.setText("Just some text to make a horizontal scroll necessary");
JScrollPane scrollPane = new JScrollPane( textArea );
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setAlignmentX(JComponent.LEFT_ALIGNMENT);
add( scrollPane );
// Share the horizontal scrollbar model
JScrollBar horizontal = scrollPane.getHorizontalScrollBar();
if (i == 0)
model = horizontal.getModel();
else
horizontal.setModel( model );
}
// Create the scrollbar that uses the shared model
JScrollBar shared = new JScrollBar( JScrollBar.HORIZONTAL );
shared.setModel( model );
shared.setAlignmentX(JComponent.LEFT_ALIGNMENT);
add( shared );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Scroll SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new ScrollSSCCE() );
frame.setLocationByPlatform( true );
frame.setSize(200, 400);
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Edit:
You can actually do this without even creating the "shared" scrollbar. Just use the scrollbar of the last scrollpane:
if (i != 4)
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
I need a vertical scroll bar as well.
Don't think you need to create another panel. Just add the current panel directly to a scroll pane:
JScrollPane master = new JScrollPane( new ScrollSSCCE() );
master.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JFrame frame = new JFrame("Scroll SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.add( new ScrollSSCCE() );
frame.add( master );
frame.setLocationByPlatform( true );
frame.setSize(200, 400);
frame.setVisible( true );
That's the last tip I have. I won't be around for a couple of days. Good luck.
I got this working to some extend with the following approach:
Put a JPanel with null Layout over the staff
Add the comboBox to this panel
Make the panel height the same as the comboBox and as width as the staff (as width as you can scroll)
Add an AdjusmentListener to the horizontal bar to update the coordinate X of the comboBoxes.
In other words the comboBoxes slides inside their null layout panels to match the position you are looking at. It is not perfect because this causes the comboBoxes to wiggle a little when you are moving the scrollBar.
The mock interface that I made looking like yours is the following:
Notice how in the screenshot the horizontal bar is moved but the comboBoxes with "Flute" are still visible.
So the most important code is:
Put the comboBox inside a null layout panel:
JComboBox comboBox = new JComboBox(new String[]{"Flute", "Piano", "Cello"});
comboBox.setBounds(0, 0, comboBox.getPreferredSize().width, comboBox.getPreferredSize().height);
_comboBoxes.add(comboBox);
JPanel comboBoxPanel = new JPanel();
comboBoxPanel.setLayout(null);
comboBoxPanel.add(comboBox);
Then you put this panel over the staff, with whatever layout you are using. In my case I had a Panel with a vertical Box Layout containg the comboBoxPanel and the red panel where the staff would be.
Add a listener to the scroll bar and update the comboBoxes position inside their panels:
scrollPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener() {
#Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
for (JComboBox comboBox : _comboBoxes)
{
comboBox.setLocation(e.getValue(), 0);
}
}
});
Full code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ScrollIndependentTest
{
private ArrayList<JComboBox> _comboBoxes = new ArrayList<JComboBox>();
public static final void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
new ScrollIndependentTest().createAndShowGUI();
}
});
}
public void createAndShowGUI()
{
JFrame frame = new JFrame();
frame.setTitle("Fourier Synthesis");
JPanel listPanel = new JPanel();
listPanel.setLayout(new BoxLayout(listPanel, BoxLayout.Y_AXIS));
for (int i = 0; i < 10; ++i)
{
listPanel.add(createStaffPanel());
}
JScrollPane scrollPane = new JScrollPane(listPanel);
scrollPane.getHorizontalScrollBar().addAdjustmentListener(new AdjustmentListener()
{
#Override
public void adjustmentValueChanged(AdjustmentEvent e)
{
for(JComboBox comboBox : _comboBoxes)
{
//if (comboBox.isVisible()) //maybe?
comboBox.setLocation(e.getValue(), 0);
}
}
});
frame.add(scrollPane);
/*
* Cosmetic elements to make it look more similar to your case
*/
JMenuBar menuBar = new JMenuBar();
menuBar.add(new JMenu("File"));
menuBar.add(new JMenu("Synthesis"));
menuBar.add(new JMenu("Help"));
frame.setJMenuBar(menuBar);
JPanel toolBar = new JPanel();
toolBar.setLayout(new BoxLayout(toolBar, BoxLayout.Y_AXIS));
for (int i = 0; i < 10; ++i)
{
toolBar.add(new JButton("Note " + i));
}
frame.add(toolBar, BorderLayout.WEST);
/*
* end
*/
frame.setSize(new Dimension(500, 400));
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JPanel createStaffPanel()
{
JPanel staffPanel = new JPanel();
staffPanel.setLayout(new BoxLayout(staffPanel, BoxLayout.Y_AXIS));
staffPanel.setBorder(BorderFactory.createLineBorder(Color.black));
JComboBox comboBox = new JComboBox(new String[]{"Flute", "Piano", "Cello"});
comboBox.setBounds(0, 0, comboBox.getPreferredSize().width, comboBox.getPreferredSize().height);
_comboBoxes.add(comboBox);
JPanel comboBoxPanel = new JPanel();
comboBoxPanel.setLayout(null);
comboBoxPanel.add(comboBox);
comboBoxPanel.setPreferredSize(new Dimension(600, comboBox.getPreferredSize().height));
staffPanel.add(comboBoxPanel);
JPanel panel = new JPanel();
panel.setBackground(Color.red);
panel.setPreferredSize(new Dimension(600, 100));
panel.setAlignmentX(Component.LEFT_ALIGNMENT);
staffPanel.add(panel);
return staffPanel;
}
}

Border with equal sizes on all 4 sides of JTextpane

I am setting a createLineborder to my JTextPane. But the border lines are little different in right-end and bottom of JTextpane when compared to Left-end and top of TextPane. I searched in net and I found that it is the default behavior of lineborder. So can anyone please tell me that is there any border which gives equal lines sizes in all 4 sides?
Hi I cannot put my code as it is very huge. So just putting a sample code here.
JPanel panel;
JTextPane pane;
public BorderedTextPane() {
// TODO Auto-generated constructor stub
pane = new JTextPane();
panel = new JPanel(null);
JPanel innerPanel = new JPanel(null);
innerPanel.setBounds(50,50,300,400);
pane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
pane.setSize(new Dimension(innerPanel.getWidth(),innerPanel.getHeight()));
innerPanel.add(pane);
panel.add(innerPanel);
add(panel);
setVisible(true);
setSize(new Dimension(500,500));
setLocationRelativeTo(null);
}
This could be clearly seen if you zoom the textpane or when you save it on a file. Below image would explain it in better way. Compare the left and right lines.
I would say it has more to do with using null layouts...
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.JPanel;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
public class TestBorder {
public static void main(String[] args) {
new TestBorder();
}
public TestBorder() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
JTextPane pane = new JTextPane();
JPanel panel = new JPanel(new BorderLayout());
JPanel innerPanel = new JPanel(new BorderLayout());
pane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
innerPanel.add(pane);
panel.add(innerPanel);
add(panel);
}
}
}
From the JComponent#setBorder() API:
Although technically you can set the border on any object that inherits from JComponent, the look and feel implementation of many standard Swing components doesn't work well with user-set borders. In general, when you want to set a border on a standard Swing component other than JPanel or JLabel, we recommend that you put the component in a JPanel and set the border on the JPanel.
Consult API setBorder method (new EmptyBorder ());
As well as using the variable JTextPane varible.setBorder (BorderFactory.createLineBorder (Color.xxx);

Java Swing setting JPanel Size

Could anyone point out where I am going wrong with this java swing gui code. I am trying to add two buttons to a JPanel and then add it into a frame after setting the size but it seems to not be responding to the setSize values passed to it
public Test() {
GridLayout layout = new GridLayout(1, 2);
//this.setLayout(layout);
this.setSize(700, 700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setSize(new Dimension(30, 100));
JButton rectButton = new JButton("Rectangle");
JButton ovalButton = new JButton("Oval");
buttonPanel.add(rectButton);
buttonPanel.add(ovalButton);
this.add(buttonPanel);
this.add(new PaintSurface());
this.setVisible(true);
}
This may not answer your immediate question...but...
GridLayout layout = new GridLayout(1, 2);
this.setLayout(layout);
// You're original code...
// Why are you using `BorderLayout.CENTER` on a `GridLayout`
this.add(new PaintSurface(), BorderLayout.CENTER);
You set the layout as a GridLayout, but you are using BorderLayout constraints to apply one of the components??
Also, make sure that there are not calls to Test#pack else where in your code, as this will override the values of setSize
UPDATED (from changes to question)
Remember, the default layout manager for JFrame is BorderLayout, so even though you're calling buttonPanel.setSize, it's likely that it's begin overridden by the layout manager anyway.
I would take a read through A Visual Guide to Layout Managers and Using Layout Managers to find a layout manager that best meets your requirements.
If you can't find a single one, consider using compound components with different layout managers to bring the layout closer to what you want to achieve.
Ok, I'll just give you a solution:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Cobie extends JFrame{
JButton rectButton = new JButton("Rectangle");
JButton ovalButton = new JButton("Oval");
JPanel buttonPanel = new JPanel();
JPanel paintSurface = new JPanel();
public Cobie(){
setLayout(new GridLayout(2,1));
buttonPanel.setBackground(Color.RED);
paintSurface.setBackground(Color.BLUE);
buttonPanel.add(rectButton);
buttonPanel.add(ovalButton);
add(buttonPanel);
add(paintSurface);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
public void run(){
Cobie c = new Cobie();
c.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
c.setSize(600,400); //Avoid using this method
c.setVisible(true);
}
});
}
}
According to your updated answer, you are not setting your layout on anything.
Anyway, if you use LayoutManager's (which you should), it is pointless to call setSize()/setBounds()/setLocation() since it will be overriden by the LayoutManager (that is actually its job).
And guessing that your Test class extends JFrame, by calling this.add(buttonPanel); this.add(new PaintSurface()); you are adding two components with the same constraint (BorderLayout.CENTER, since BorderLayout is the default LayoutManager of the content pane of the JFrame) to the content pane.
Consider reading the LayoutManager tutorial.
Just for information, although far from perfect, this shows something "working":
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test extends JFrame {
private JPanel buttonPanel;
public class PaintSurface extends JButton {
public PaintSurface() {
super("Paint surface dummy");
}
}
public Test() {
GridLayout layout = new GridLayout(1, 2);
this.setLayout(layout);
this.setSize(700, 700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setSize(new Dimension(30, 100));
JButton rectButton = new JButton("Rectangle");
JButton ovalButton = new JButton("Oval");
buttonPanel.add(rectButton);
buttonPanel.add(ovalButton);
this.add(buttonPanel);
this.add(new PaintSurface());
this.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}

Categories