BorderLayout problem with JSplitPane after adding JToolbar (Java) - java

Problem:
My program layout is fine, as below before I add JToolbar to BorderLayout.PAGE_START
Here's a screenshot before JToolbar is added:
Here's how it looked like after adding JToolbar:
May I know what did I do wrong?
Here's the code I used:
//Create the text pane and configure it.
textPane = new JTextPane();
-snipped code-
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(new Dimension(300, 300));
//Create the text area for the status log and configure it.
changeLog = new JTextArea(5, 30);
changeLog.setEditable(false);
JScrollPane scrollPaneForLog = new JScrollPane(changeLog);
//Create a split pane for the change log and the text area.
JSplitPane splitPane = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
scrollPane, scrollPaneForLog);
splitPane.setOneTouchExpandable(true);
//Create the status area.
JPanel statusPane = new JPanel(new GridLayout(1, 1));
CaretListenerLabel caretListenerLabel =
new CaretListenerLabel("Caret Status");
statusPane.add(caretListenerLabel);
//Create the toolbar
JToolBar toolBar = new JToolBar();
-snipped code-
//Add the components.
getContentPane().add(toolBar, BorderLayout.PAGE_START);
getContentPane().add(splitPane, BorderLayout.CENTER);
getContentPane().add(statusPane, BorderLayout.PAGE_END);
//Set up the menu bar.
actions = createActionTable(textPane);
JMenu editMenu = createEditMenu();
JMenu styleMenu = createStyleMenu();
JMenuBar mb = new JMenuBar();
mb.add(editMenu);
mb.add(styleMenu);
setJMenuBar(mb);
Please help, I'm new to GUI Building, and I don't feel like using Netbeans to drag and drop the UI for me... Thank you in advance.

Instead of using setSize() on the JFrame, set the preferred size of your center component as you do now and invoke pack(), which "Causes this Window to be sized to fit the preferred size and layouts of its subcomponents." Expanding on #Bragaadeesh's example,
public static void main(String[] args) {
TestFrame frame = new TestFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.build();
frame.pack();
frame.setVisible(true);
}
Then, change to scrollPane.setPreferredSize(new Dimension(500, 300)) or JTextArea changeLog = new JTextArea(10, 30) to see the difference.

I don't know what is the issue. I tried to run it on my system by fixing the compilation issues. Here is the code and screenshot.
import java.awt.*;
import javax.swing.*;
public class TestFrame extends JFrame{
public static void main(String[] args) {
TestFrame frame = new TestFrame();
frame.build();
frame.setVisible(true);
}
public void build(){
setSize(600,600);
//Create the text pane and configure it.
JTextPane textPane = new JTextPane();
JScrollPane scrollPane = new JScrollPane(textPane);
scrollPane.setPreferredSize(new Dimension(300, 300));
//Create the text area for the status log and configure it.
JTextArea changeLog = new JTextArea(5, 30);
changeLog.setEditable(false);
JScrollPane scrollPaneForLog = new JScrollPane(changeLog);
//Create a split pane for the change log and the text area.
JSplitPane splitPane = new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
scrollPane, scrollPaneForLog);
splitPane.setOneTouchExpandable(true);
//Create the status area.
JPanel statusPane = new JPanel(new GridLayout(1, 1));
JLabel caretListenerLabel =
new JLabel("Caret Status");
statusPane.add(caretListenerLabel);
//Create the toolbar
JToolBar toolBar = new JToolBar();
toolBar.add(new JButton("Btn1"));
toolBar.add(new JButton("Btn2"));
toolBar.add(new JButton("Btn3"));
toolBar.add(new JButton("Btn4"));
//Add the components.
getContentPane().add(toolBar, BorderLayout.PAGE_START);
getContentPane().add(splitPane, BorderLayout.CENTER);
getContentPane().add(statusPane, BorderLayout.PAGE_END);
//Set up the menu bar.
JMenu editMenu = new JMenu("test");
JMenu styleMenu = new JMenu("test");
JMenuBar mb = new JMenuBar();
mb.add(editMenu);
mb.add(styleMenu);
setJMenuBar(mb);
}
}

EDIT: I understand why now.
I used Paint to give me a rough estimation of the pixels, and previously I did not know that the height from the start of the top frame title bar is counted! So that adds up to ~= 504. I get it now.
So next time when I have to set the height roughly, I think I'll use Paint.
Hmmm weird. I have to change from:
//Display the window.
frame.setSize(640, 480);
to
//Display the window.
frame.setSize(640, 504);
Then only it works.
Can somebody teach me how to estimate or set the width/height for the components? Because initially I wanted it to be 640,480 but apparently now it needs 640,504.

Related

Having Multiple Panels with scroll panes

I created two panels and a main panel. Each panel contains a very large image, and I wanted both of them to be scroll-able to see the rest of the image. But when I add the two panels in the main panel and run it, the first panel is soo big that it covers the second panel. How would I implement ScrollPane for both panels?
import java.awt.BorderLayout;
import javax.swing.*;
public class BoardFrame extends JFrame {
JPanel mainPanel = new JPanel(new BorderLayout());
JLabel jLabel = new JLabel();
JPanel jPanelNorth = new JPanel();
JScrollPane scrollPane = new JScrollPane();
JLabel jLabel2 = new JLabel();
JPanel jPanelSouth = new JPanel();
JScrollPane scrollPane2 = new JScrollPane();
public BoardFrame() {
jLabel.setIcon(new ImageIcon("an image here"));
jPanelNorth.add(jLabel);
jLabel2.setIcon(new ImageIcon("an image here"));
jPanelSouth.add(jLabel2);
mainPanel.add(jPanelNorth, BorderLayout.NORTH);
mainPanel.add(jPanelSouth, BorderLayout.SOUTH);
add(mainPanel);
//where would I use this?
//scrollPane.setViewportView();
}
}
Each panel contains a very large image>
//JPanel mainPanel = new JPanel(new BorderLayout());
JPanel mainPanel = new JPanel(new GridLayout(0, 1));
You may want to use a GridLayout so that each scroll pane takes up half the frame so as much of each image as possible is displayed.
//JScrollPane scrollPane = new JScrollPane();
JScrollPane scrollPane2 = new JScrollPane(jPanelNorth);
The easiest way to use the scroll pane is to create the scrollpane with the component you want displayed and the scrollpane will add the component to the viewport for you.
//mainPanel.add(jPanelNorth, BorderLayout.NORTH);
mainPanel.add(scrollPane); // don't need the constraint when using GridLayout.
Then you add the scrollPane to the main panel, since the scrollpane contains the panel with the image.
it seems to use grid layout is much better than using border layout , in this case :
import java.awt.BorderLayout;
import javax.swing.*;
public class BoardFrame extends JFrame {
//1. use GridLayout with 2 rows and 1 column .
JPanel mainPanel = new JPanel(new GridLayout(2,1));
JLabel jLabel = new JLabel();
JPanel jPanelNorth = new JPanel();
JScrollPane scrollPane = new JScrollPane();
JLabel jLabel2 = new JLabel();
JPanel jPanelSouth = new JPanel();
JScrollPane scrollPane2 = new JScrollPane();
public BoardFrame() {
jLabel.setIcon(new ImageIcon("an image here"));
jPanelNorth.add(jLabel);
jLabel2.setIcon(new ImageIcon("an image here"));
jPanelSouth.add(jLabel2);
//2.you should place .setViewportView() here :
scrollPane.setViewportView(jPanelNorth);
scrollPane2.setViewportView(jPanelSouth);
mainPanel.add(scrollPane);//is in the top ("North")
mainPanel.add(scrollPane2);//next ("South")
//3.use setContentPane instead of add()
setContentPane(mainPanel);
}
}

Swing GUI problems with BorderLayout

I'm currently trying to get along with Layouts, considering that I never really understood them and only did nullLayout instead, absolutely positioning all elements then.
However, I currently have a suitable small project, where I am trying to learn it, which is some small chat service.
Here is a picture right now:
And here is a picture, of how I imagine it to be finished (Please note that this is just some concept, but it should give you the right idea. I'm not a graphic artist):
Here is my current code:
public class Gui {
JFrame frame;
JTextArea textfield;
JTextField enterMessage;
public Gui(){
frame = new JFrame();
frame.setSize(600, 400);
textfield = new JTextArea();
textfield.setText("Textfield");
textfield.setSize(400, 300);
JPanel messagePanel = new JPanel();
JTextField chatMessage = new JTextField();
chatMessage.setText("Send me");
JButton send = new JButton();
send.setText("Send");
messagePanel.add(chatMessage, BorderLayout.WEST);
messagePanel.add(send, BorderLayout.EAST);
frame.add(textfield, BorderLayout.WEST);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
}
My idea, together with the understanding of BorderLayouts so far was to put the Textfield, where the chat dialog ends up in later on, right inside the frame, on the WEST-side.
The button to send and the field to enter some text will be inside a panel, with an own borderlayout, while the button has some smaller part on the right and the rest of the width is being filled with the textfield.
The whole panel then ends on the SOUTH-side of the frame.
However, right now I have the problem, that the elements keep shrinking to the least possible size.
I tried to fix this with setSize(); , but that does not have an impact at all, it is just being completely ignored.
Any help to point me into the right direction?
Initially, you've got one simple problem:
// should be new JPanel(new BorderLayout())
JPanel messagePanel = new JPanel();
Then, after that, generally BorderLayout likes to stretch the component in BorderLayout.CENTER. So you want to put your textfield and chatMessage in the center.
public Gui(){
frame = new JFrame();
frame.setSize(600, 400);
textfield = new JTextArea();
textfield.setText("Textfield");
// textfield.setSize(400, 300);
JPanel messagePanel = new JPanel(new BorderLayout());
JTextField chatMessage = new JTextField("Send me");
JButton send = new JButton("Send");
messagePanel.add(chatMessage, BorderLayout.CENTER);
messagePanel.add(send, BorderLayout.EAST);
frame.add(textfield, BorderLayout.CENTER);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
Once you do that, you should get something like this:
But, as a few words of advice:
Don't rely on setSize of a JFrame. Instead, you should use setPreferredSize on a single component which the entire UI should size itself around. (Probably the main text area.) The size of a JFrame includes, for example, the title bar.
You should consider wrapping your JTextArea in a scroll pane. You can then instead setPreferredSize on the viewport.
After you have a component with a preferred size, call pack() on the JFrame before calling setVisible(true). This will size it automatically.
Something like:
frame = new JFrame();
// frame.setSize(600, 400);
...
JScrollPane pane = new JScrollPane(
textfield,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
// specifying initial size for the
// visible portion of the scroll pane
pane.getViewport().setPreferredSize(new Dimension(320, 200));
frame.add(pane, BorderLayout.CENTER);
frame.add(messagePanel, BorderLayout.SOUTH);
// entire UI sizes around the scroll pane view
frame.pack();
frame.setVisible(true);
Try BoxLayout insted BorderLayout in messagePanel:
messagePanel.setLayout(new BoxLayout(messagePanel,BoxLayout.LINE_AXIS));
messagePanel.add(chatMessage);
messagePanel.add(send);
And for textField:
frame.add(textfield, BorderLayout.CENTER);
Try setting preferred size dimensions of the elements.
textfield.setText("Textfield");
textfield.setPreferredSize(new Dimension(600, 300));
//some other code
JTextField chatMessage = new JTextField();
chatMessage.setPreferredSize(new Dimension(500, 25));
//some other code
As pointed out by Sridhar, BorderLayout does not always respect the dimensions of sub-panels. To fix this, you should initialize your sub-panels (in this case textfield and messagePanel) using setPreferedSize() instead of setSize().
change your constructor to
public Gui() {
frame = new JFrame();
frame.setSize(600, 400);
textfield = new JTextArea();
textfield.setText("Textfield");
textfield.setSize(400, 300);
// set border layout to JPanel
JPanel messagePanel = new JPanel(new BorderLayout());
JTextField chatMessage = new JTextField();
chatMessage.setText("Send me");
JButton send = new JButton();
send.setText("Send");
// add JTextField to CENTER and button to EAST
messagePanel.add(chatMessage, BorderLayout.CENTER);
messagePanel.add(send, BorderLayout.EAST);
// add textArea to CENTER of JFrame
frame.add(textfield, BorderLayout.CENTER);
frame.add(messagePanel, BorderLayout.SOUTH);
frame.setVisible(true);
}
and it will work..

JScrollPane In JFrame with two panels

I want to add a scroll bar to my JTextArea but it just won't show up. I have read a lot of stuff on forums but all in vain. Any suggestions are highly appreciated.
Thanks in advance. Below is my code.
JPanel pan, pan2;
JTextArea text = new JTextArea();
JTextField fname = new JTextField(18);
JLabel filename = new JLabel("Filename");
JButton view = new JButton("View");
public FileReading() {
setLayout(new BorderLayout());
pan = new JPanel();
pan2 = new JPanel();
JScrollPane scroll = new JScrollPane(text);
//scroll.setBounds(400,400,400,400);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
text.setEditable(false);
scroll.setViewportView(text);
pan2.add(scroll);
//scrollpane.setViewportView(text);
pan2.setLayout(new BorderLayout());
//pan2.add(scrollpane);
pan.setLayout(new FlowLayout());
pan.add(filename, FlowLayout.LEFT);
pan.add(fname, FlowLayout.CENTER);
pan.add(view, FlowLayout.RIGHT);
view.addActionListener(this);
fname.addActionListener(this);
pan2.add(text, BorderLayout.CENTER);
pan2.add(pan, BorderLayout.SOUTH);
//BorderLayout.EAST
//add(pan, BorderLayout.SOUTH);
add(pan2);//, BorderLayout.CENTER
setVisible(true);
}
public static void main(String args[]) {
FileReading frame = new FileReading();
frame.setTitle("Enter The Full Path to the File");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(400,400,400,400);
//frame.setSize(400,400);
}
You need to add scroll (JScrollPane) to the pan2 not to the text (JTextArea)
try this
pan2.add(scroll, BorderLayout.CENTER);
in place of pan2.add(text, BorderLayout.CENTER);
EDIT
JTextArea gets added automatically when we add JScrollPane into the panel, as you have added text (JTextArea) inside JScrollPane
here -> JScrollPane scroll = new JScrollPane(text);
Can try this
add(scroll);//, BorderLayout.CENTER
add(pan, BorderLayout.SOUTH);
instead of
add(pan2);//, BorderLayout.CENTER
This way we are directly adding the scrollpane to main frame and putting other things below

Java Swing Layout

I would like the following lay out...
JButtons on top along side eachother.
The JTextArea should be under the buttons.
The JTextArea should also have a scrollbar.
...for the code below.
JPanel jp = new JPanel();
One = new JButton("One");
Two = new JButton("Two");
TestOutput = new JTextArea();
jp.add(One);
jp.add(Two);
jp.add(TestOutput);
Use a nested layout: To a JPanel having BorderLayout,
add a JPanel having FlowLayout for the buttons to the NORTH
and a JScrollPane for the JTextArea to the CENTER.
The keyword is layering - having JPanel on JPanel.
Use a GridBagLayout
See this for more help : How to Use GridBagLayout
Now note that the JTextarea to have a scrollbar have nothing to do with layouts.
See this for more help in that context : How to Use Scroll Panes
The FlowLayout in a JPanel for the JButton instances is one way to go. You might also use a JToolBar for the buttons.
import java.awt.*;
import javax.swing.*;
class ButtonsAndTextAreaLayout {
ButtonsAndTextAreaLayout() {
JPanel gui = new JPanel(new BorderLayout(5,5));
// use a toolbar for the buttons
JToolBar tools = new JToolBar();
// use firstWordLowerCase for attribute/method names.
JButton one = new JButton("One");
JButton two = new JButton("Two");
tools.add(one);
tools.add(two);
// provide hints as to how large the text area should be
JTextArea testOutput = new JTextArea(5,20);
gui.add(tools, BorderLayout.NORTH);
gui.add(new JScrollPane(testOutput), BorderLayout.CENTER);
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonsAndTextAreaLayout();
}
});
}
}
You can either use a GridBagLayout as suggested, or nest multiple layout managers such as:
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
JPanel buttonPanel = new JPanel();
JButton oneButton = new JButton("One");
JButton twoButton = new JButton("Two");
buttonPanel.add(oneButton);
buttonPanel.add(twoButton);
JTextArea output = new JTextArea();
JScrollPane scrollPane = new JScrollPane(output);
frame.add(buttonPanel, BorderLayout.NORTH);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);

horizontal split pane resize with window

I have a horizontal split pane that contains a vertical split pane. When the window shows up i want the vertical split pane in the top of the horizontal split pane to be split in the middle. I want the horizontal divider to be in the middle.
I have that working, however, i also want to the horizontal split pane to change its size when the window is maximized. (It currently does not.)
I also have a button box below the horizontal pane and would like it to always be visible when the window is resized. Currently when the window launches i can see everything in the horizontal split. I am unable to see the buttons, because they do not fit in the preferred size of the window (800, 600). But i would like everything to show up in the window automatically and stay Glue'd to the border of the window when it is resized...
How can i do this?
Thanks!
Below is the code i am currently using. I call the create methods in a controller. createView is called first then the rest in sequential order.
public void createView() {
dialog = new JFrame();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
dialog.setAlwaysOnTop(true);
dialog.setBounds(0, 0, 800, 600);
dialog.setMinimumSize(new Dimension(800, 600));
dialog.setPreferredSize(new Dimension(800, 600));
dialog.setResizable(true);
dialog.setTitle("MJLA Class Control Panel");
contentPanel = new JPanel();
// contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
contentPanel.setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
dialog.getContentPane().add(contentPanel, BorderLayout.CENTER);
classQuizSRTSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
contentPanel.add(classQuizSRTSplit, BorderLayout.NORTH);
classQuizSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
classQuizSRTSplit.setTopComponent(classQuizSplit);
// classQuizHBox = Box.createHorizontalBox();
// contentPanel.add(classQuizHBox);
sRTHBox = Box.createHorizontalBox();
contentPanel.add(sRTHBox);
buttonBox = Box.createHorizontalBox();
contentPanel.add(buttonBox, BorderLayout.SOUTH);
refreshButton = new JButton("Refresh");
buttonBox.add(refreshButton);
doneButton = new JButton("Done");
buttonBox.add(doneButton);
this.validateView();
}
public void createClassTablePanel() {
this.classTablePanel = new JPanel();
this.classTablePanel.setBorder(BorderFactory.createLineBorder(Color.black, 3));
this.classTablePanel.setPreferredSize(new Dimension(300, 300));
this.classTablePanel.setLayout(new BorderLayout());
// this.classQuizHBox.add(classTablePanel);
this.classQuizSplit.setLeftComponent(classTablePanel);
classTableModel = cPModel.getClassTableModel();
classTable = new JTable(this.classTableModel);
classTable.getSelectionModel().addListSelectionListener(this);
JScrollPane scrollPane = new JScrollPane(classTable);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
classTablePanel.add(scrollPane, BorderLayout.CENTER);
this.validateView();
}
public void createQuizTablePanel() {
this.quizTablePanel = new JPanel();
this.quizTablePanel.setBorder(BorderFactory.createLineBorder(Color.black, 3));
this.quizTablePanel.setPreferredSize(new Dimension(300, 300));
this.quizTablePanel.setLayout(new BorderLayout());
// this.classQuizHBox.add(quizTablePanel);
this.classQuizSplit.setRightComponent(quizTablePanel);
quizTableModel = cPModel.getQuizTableModel();
this.quizSorter = new TableRowSorter<DefaultTableModel>(quizTableModel);
quizTable = new JTable(this.quizTableModel);
quizTable.getSelectionModel().addListSelectionListener(this);
quizTable.setRowSorter(quizSorter);
JScrollPane scrollPane = new JScrollPane(quizTable);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
quizTablePanel.add(scrollPane, BorderLayout.CENTER);
Box buttonHBox = Box.createHorizontalBox();
quizTablePanel.add(buttonHBox, BorderLayout.SOUTH);
addQuizButton = new JButton("Add Quiz");
buttonHBox.add(addQuizButton);
removeQuizButton = new JButton("Remove Quiz");
buttonHBox.add(removeQuizButton);
editQuizButton = new JButton("Edit Quiz");
buttonHBox.add(editQuizButton);
this.validateView();
}
public void createStudentRecordTablePanel() {
this.studentRecordTablePanel = new JPanel();
this.studentRecordTablePanel.setBorder(BorderFactory.createLineBorder(Color.black, 3));
this.studentRecordTablePanel.setLayout(new BorderLayout());
// this.sRTHBox.add(studentRecordTablePanel);
this.classQuizSRTSplit.setBottomComponent(studentRecordTablePanel);
this.studentRecordTableModel = cPModel.getStudentRecordTableModel();
this.sRTSorter = new TableRowSorter<DefaultTableModel>(studentRecordTableModel);
sRTTable = new JTable(this.studentRecordTableModel);
sRTTable.setRowSorter(sRTSorter);
JScrollPane scrollPane = new JScrollPane(sRTTable);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
studentRecordTablePanel.add(scrollPane, BorderLayout.CENTER);
Box buttonHBox = Box.createHorizontalBox();
studentRecordTablePanel.add(buttonHBox, BorderLayout.SOUTH);
editGradeButton = new JButton("Edit Grade");
buttonHBox.add(editGradeButton);
generateReportButton = new JButton("Generate Report");
buttonHBox.add(generateReportButton);
this.validateView();
}
Another issue.
That fixed one of the problems #TrashGod. However, how can i make the horizontal split pane resize its component to fit the new size of the window, instead of their being that big gap between the done and refresh button and the bottom of the horizontal split pane?
I was thinking that i would have to listen for an event for when the window size changes and then call the pack() method when that happens, is that the only way or would that even work? (Just tested this, it did not work... just puts everything back to preferred sizes. duh)
Initial look.
After window maximized.
You might look at setResizeWeight(); a value of 0.5 should distribute the space evenly.
The pack() method "Causes this Window to be sized to fit the preferred size and layouts of its subcomponents." BorderLayout.NORTH and BorderLayout.SOUTH seem like suitable layouts for staying with the divider.
For additional help, please provide an sscce that exhibits the problem.

Categories