How to add a JScrollPane onto a JTabbedPane using a null layout? - java

I want to implement a Scrollbar onto my Tab. However nothing is showing and there are no exceptions.
I think I need a:
scrollPane.setViewportView(scrollPanel);
But it didn't work as well.
I am wondering when adding a Jscrollpane onto a JTab how do you set it visible without using an explicit frame. If I use a frame and add it on the frame it creates a new window.
However how I got this program the Frame looks built I assume and this complicates everything.
import java.awt.*;
import javax.swing.*;
public class Test extends JFrame {
private JTabbedPane tabbedPane;
private JPanel panel; // Page where I want JScrollPane intisialized
public Test()
{
setTitle( "Program" );
setSize( 400, 200 ); // I want the JScrollPane to extend to 400 vertically
JPanel topPanel = new JPanel();
topPanel.setLayout( new BorderLayout() );
getContentPane().add( topPanel );
// Create the tab pages
createPage1();
tabbedPane = new JTabbedPane();
tabbedPane.addTab( "Welcome", panel );
topPanel.add( tabbedPane, BorderLayout.CENTER );
}
public void createPage1()
{
panel = new JPanel();
panel.setLayout( null ); // sets layout to null
////////////////////////
JPanel scrollPanel = new JPanel();
scrollPanel.setLayout(null);
scrollPanel.setPreferredSize(new Dimension(400,400));
///////////////////////
panel.add(scrollPanel);
scrollPanel.setVisible (true);
}
public static void main( String args[] )
{
// Create an instance of the test application
Test mainFrame = new Test();
mainFrame.setVisible( true );
}
}
If you have any questions don't hesitate to ask.

What you want is to use a JScrollPane. Change the createPage1() method to something like this:
public void createPage1()
{
panel = new JPanel();
panel.setLayout( new BorderLayout() );
////////////////////////
JScrollPane scrollPanel = new JScrollPane();
scrollPanel.setViewportView(new JLabel("hellossssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"));
scrollPanel.setPreferredSize(new Dimension(400,400));
///////////////////////
panel.add(scrollPanel,BorderLayout.CENTER);
}
And you will see a scrollbar. Note this change encompasses four things:
replace the null layout call with a BorderLayout
make a JScrollPane instead of a JPanel
add something to the pane for demo purposes
remove the unnecessary setVisible(true) call.

Related

Java Swing JTabbedPane layout

I am new to Swing and cannot find a page that helps me understand JTabbedPane. I cannot find a way to control the layout of components of the tabbed panels. I can layout each of my panels correctly as separate GUIs but not in a tabbed pane like I need to do. I would like to use the BorderLayout not FlowLayout.
Also, you can see I'm trying to use colors to keep track of my panels and their components. I cannot set the background of the JTabbedPane. It is still the default grey. Can someone tell me why this is?
Thank you for any advice you can give.
What I have so far appears to follow a 'flow layout' despite any changes I've tried
(Methods have been removed or nearly removed to keep code shorter)
public class GUIFrame extends JFrame {
public GUIFrame(String title) {
JFrame frame = new JFrame(title);
Container c = frame.getContentPane();
buildGUI(c);
setFrameAttributes(frame);
}
private void buildGUI(Container c) {
c.setLayout(new BorderLayout());
c.setBackground(Color.BLACK);
JTabbedPane tabs = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT);
tabs.setBackground(Color.YELLOW);
c.add("Center", tabs);
tabs.addTab("Specialty", new SpecialtyPanel());
tabs.addTab("Treatment", new TreatmentPanel());
tabs.addTab("Doctor", new DoctorPanel());
tabs.addTab("Patient", new PatientPanel());
}
private void setFrameAttributes(JFrame f) {
f.setSize(500, 500);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
MedicalSystemIO test = new MedicalSystemIO();
new GUIFrame("Tabbed Title");
}
public class SpecialtyPanel extends JPanel implements ActionListener {
JTextField jteInput = null;
DefaultListModel<String> model = new DefaultListModel<String>();
JList<String> list = new JList(model);
JScrollPane pane = new JScrollPane(list);
public SpecialtyPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.black));
buildGUI(panel);
}
private void buildGUI(JPanel panel) {
JPanel jpaInput = createInputPanel();
JPanel jpaProcess = createProcessPanel();
JPanel jpaOutput = createOutputPanel();
//panel.setLayout(new BorderLayout());
add("North", jpaInput);
add("Center", jpaProcess);
add("South", jpaOutput);
}
private JPanel createInputPanel() {
JPanel jpaInput = new JPanel();
jpaInput.setBackground(Color.RED);
return jpaInput;
}
private JPanel createProcessPanel() {
JPanel jpaProcess = new JPanel();
jpaProcess.setBackground(Color.BLUE);
return jpaProcess;
}
private JPanel createOutputPanel() {
JPanel jpaOutput = new JPanel();
jpaOutput.add(pane);
return jpaOutput;
}
The SpecialtyPanel is shown that way (flow layout) as you are putting the components on it in the wrong way:
No need for passing a new panel into the buildGUI method as you want to put them directly on the SpecialtyPanel which already is a JPanel,
you commented out the setting of the BorderLayout and
you used the wrong notation of passing the layout constraints in the add methods.
Your constructor and build method should look like this:
public SpecialtyPanel() {
buildGUI();
}
private void buildGUI() {
setBorder(BorderFactory.createLineBorder(Color.black));
JPanel jpaInput = createInputPanel();
JPanel jpaProcess = createProcessPanel();
JPanel jpaOutput = createOutputPanel();
setLayout(new BorderLayout());
add(jpaInput, BorderLayout.NORTH);
add(jpaProcess, BorderLayout.CENTER);
add(jpaOutput, BorderLayout.SOUTH);
}
To have the panel another color than gray you have to color the component that is put on the tabbed pane as it covers the whole space. Add the desired color to the buildGUI method, e.g.:
private void buildGUI(JPanel panel) {
// ...
setBackground(Color.YELLOW);
}
As a JPanel is opaque by default (that means not transparent), you need to set panels on top (except those which you colored explicitly) to be transparent. In case of SpecialtyPanel:
private JPanel createOutputPanel() {
JPanel jpaOutput = new JPanel();
jpaOutput.add(pane);
jpaOutput.setOpaque(false); // panel transparent
return jpaOutput;
}

IllegalArgumentException error

So I am attempting to use MVC(model, view, controller) to format my code and when attempting to add the view to the actual application I get an error that says that "java.lang.IllegalArgumentException: adding a window to a container
at java.awt.Container.checkNotAWindow
at java.awt.Container.addImpl
at java.awt.Container.add"
While I know what the error is I have no idea what I should do(not use MVC or find some sort of work-around) and would appreciate any help. Below I will have the code of the two classes.
Here is where the application is run from:
import javax.swing.*;
import java.awt.*;
/**
* Write a description of class FencingApplication here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class Application
{
public static void main(String[] args){
InputView view = new InputView();
InputModel model = new InputModel();
InputController ctrl = new InputController(view, model);
JFrame window = new JFrame("");
window.setSize(500, 600);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = new Container();
c.setLayout(new BorderLayout());
c.add( view, BorderLayout.CENTER );
JButton btList = new JButton( "List" );
JButton btPools = new JButton("Pools");
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 2));
buttonPanel.add(btList);
buttonPanel.add(btPools);
c.add( buttonPanel, BorderLayout.NORTH );
btList.addActionListener( ctrl );//where is the action performed method defined
btPools.addActionListener( ctrl );
window.setVisible( true );
}
}
And here is the view class:
import javax.swing.*; //Jframe/JButton/JLabel/etc
import java.awt.*; //container
import java.util.*;
/**
* Write a description of class InputView here.
*
* #author (your name)
* #version (a version number or a date)
*/
public class InputView extends JFrame implements Observer
{
JLabel lbPaste = new JLabel("Please paste the seeding here.");
JTextArea taPaste = new JTextArea();
JButton btPools = new JButton("Pools");
JLabel lbNum = new JLabel("Please input the number of pools you want to have.");
JTextField tfNum = new JTextField();
public InputView()
{
JPanel numPanel = new JPanel();
numPanel.setLayout(new BorderLayout());
numPanel.add(lbNum, BorderLayout.NORTH);
numPanel.add(tfNum, BorderLayout.CENTER);
JPanel pastePanel = new JPanel();
pastePanel.setLayout(new BorderLayout());
pastePanel.add(lbPaste, BorderLayout.NORTH);
pastePanel.add(new JScrollPane(taPaste), BorderLayout.CENTER);
Container c = getContentPane();
c.setLayout(new GridLayout(2, 1));
c.add(numPanel);
c.add(pastePanel);
setTitle( "Pools" );
setSize( 350, 500 );//width then height
setVisible(true);
setResizable(false);
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
}
public void update( Observable obs, Object obj )
{
}
}
Thanks in advance for any help!
Container is the superclass of e.g. Panel, JPanel, Window, JFrame, etc.
JFrame is a window, so you shouldn't (and in fact can't, as you found out here) add it to another component. JFrame is a top-level container.
Actually, it's probably the case that you shouldn't be using new Container() directly at all. For example, if you want a panel, you should use JPanel. It's kind of hard for me to tell exactly what you intended, since adding a JFrame to another component is an error. I see you adding stuff to c but I don't see you doing anything else with it.
So:
JFrame is a window.
JFrame has a content pane, which is the panel inside the window. (The default content pane is actually a JPanel, even though getContentPane() returns it as a Container.)
If you want to put stuff in a JFrame, you add the stuff to the content pane.
You don't need to add a JFrame to anything, just create it with new and call setVisible(true).
Those are the basics of how to use a JFrame correctly.
I also highly recommend the Swing tutorials if you haven't read them. They are really pretty good.

JScrollPane doesn't work while inside a JPanel

JScrollPane works perfectly when I give it a JPanel and then add the JScrollPane directly on to a JFrame with frame.getContentPane.add(). However, it doesn't work when I add the JScrollPane to a JPanel and then add the JPanel to the JFrame. I need to use the second method because I'm going to add multiple things inside the JPanel and JFrame and I need to keep it organized. Here is my code.
import java.awt.*;
import javax.swing.*;
public class Main {
/**
* #param inpanel asks if the JScrollPane should
* be inside of a JPanel (so other things can also be added)
*/
public static void testScroll(boolean inpanel) {
JFrame f = new JFrame();
f.setLayout(new BorderLayout());
f.setResizable(true);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createLineBorder(Color.red));
//panel.setLayout(new BoxLayout(panel, 1));
panel.setLayout(new GridLayout(0,1));
for (int i = 0; i < 100; i++) {
JLabel l = new JLabel("hey"+i,SwingConstants.CENTER);
l.setBorder(BorderFactory.createLineBorder(Color.green));
l.setPreferredSize(new Dimension(200,200));
panel.add(l);
}
JScrollPane scrollPane = new JScrollPane(panel);
scrollPane.setBorder(BorderFactory.createLineBorder(Color.blue));
//**********THIS DOES NOT WORK HOW I WANT IT TO************
if(inpanel){
JPanel holder = new JPanel();
holder.add(scrollPane);
f.getContentPane().add(holder);
}
//************THIS DOES WORK HOW I WANT IT TO****************
else{
f.getContentPane().add(scrollPane);
}
f.pack();
f.setSize(500, 500);
f.setExtendedState(JFrame.MAXIMIZED_BOTH);
f.setVisible(true);
JScrollBar bar = scrollPane.getVerticalScrollBar();
bar.setValue(bar.getMaximum());
bar.setUnitIncrement(50);
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
testScroll(false); //OR TRUE
}
};
SwingUtilities.invokeLater(r);
}
}
In the main method, if I pass false, it works like I mentioned before, but when I pass true it shows up without a scroll bar.
Picture when passing false
Picture when passing true
I need a way to add the JScrollPane to a JPanel and still have it work.
Thanks in advance!
Your problem is the holder JPanel's layout. By default it is FlowLayout which will not re-size its child components when need be. Make it a BorderLayout instead, and your scrollpane will resize when needed. If you need something more complex, check out the layout manager tutorials.

How can I size a Java Swing JTextArea

I am trying to put a text area onto a dialog box using Java Swing. I have a problem of setting the size of this JTextArea. The width of the text area is always equal to the whole width of the window and stretches with the window if I resize it.
private void arrangeComponents() {
JTextArea textArea = new JTextArea();
JPanel outerPanel = new JPanel();
outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.PAGE_AXIS));
JScrollPane scrollPane = new JScrollPane(textArea);
outerPanel.add(scrollPane, BorderLayout.CENTER);
Container contentPane = getContentPane();
contentPane.add(outerPanel, BorderLayout.CENTER);
}
I want the JTextArea to be horizontally aligned to the centre of the window and does not change its size.
What did I do wrong?
Use the JTextArea(int rows, int columns) constructor that specifies rows and columns, as shown here, and don't neglect to pack() the enclosing Window.
outerPanel.add(scrollPane, BorderLayout.CENTER);
A BoxLayout doesn't take constraints, so the BorderLayout.CENTER is unnecessary.
The problem is that a BoxLayout respects the maximum size of the component which for a scrollpane is set very large.
Instead of using a BoxLayout, just use a panel with a FlowLayout.
Run the example below to see what you are currently doing. Then comment out the setLayout(...) statement and run again. By default the panel uses a FlowLayout so you will get what you want.
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
setLayout( new BoxLayout(this, BoxLayout.PAGE_AXIS));
JTextArea textArea = new JTextArea(5, 30);
JScrollPane scrollPane = new JScrollPane(textArea);
//scrollPane.setMaximumSize( scrollPane.getPreferredSize() );
add(scrollPane);
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new SSCCE() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Or if you really want to keep the BoxLayout then leave keep the setLayout(...) statement and then set the maximum size equal to the preffered size. Many people will say you should never invoke a "setXXX()" method directly and instead you should override the setMaximumSize() method of the scrollpane to just return the preferred size.
Note, when testing these two solutions make sure you make the window smaller than the scrollpane to see how each layout works differently.
i found this from a simple coding site. This code sample may be useful for you.
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class JTextAreaTest {
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("JTextArea Test");
frame.setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String text = "A JTextArea object represents a multiline area for displaying text. "
+ "You can change the number of lines that can be displayed at a time, "
+ "as well as the number of columns. You can wrap lines and words too. "
+ "You can also put your JTextArea in a JScrollPane to make it scrollable.";
JTextArea textAreal = new JTextArea(text, 5, 10);
textAreal.setPreferredSize(new Dimension(100, 100));
JTextArea textArea2 = new JTextArea(text, 5, 10);
textArea2.setPreferredSize(new Dimension(100, 100));
JScrollPane scrollPane = new JScrollPane(textArea2,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
textAreal.setLineWrap(true);
textArea2.setLineWrap(true);
frame.add(textAreal);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
}
Just call that method for ur text area: setLineWrap(true);
If JTextArea is initializated
JTextArea text = new JTextArea(int rows, int columns)
you just call the method text.setLineWrap(true)
then text'size is fixed.

In swing GUI how to show a JPanel as maximized when the user clicks a button?

I want to maximize a JPanel inside a JFrame when the user clicks a button.What is the best way to achieve this.The view and the data model should be in sync in both the panels,that is the panel which in the JFrame and the maximized one.Please suggest me some solution.
my requirement is: i have a JFrame with 4 JPanels named as
JPanelA,JPanelB,JPanelC,JPanelD
Here the JPanelD contains a JList and
a button below it say "MAXIMIZE
PANEL" button . JList has a JTree
with in it . Sometimes the JList may
have huge set of data and it is not
visible to the user clearly.
So he need to maximize this JPanelD alone to see the contents of the JList clearly.For that he clicks "MAXIMIZE PANEL" button.After the click action ,the JPanelD in the JFrame remains there,also a new JPanel with the same JList data(ie.,the replica of the JPanelD say JPanelDMaximized)should be popped up.This is what i want to do ..
Of course you could do this yourself, but you should really look at JInternalFrame and consider using that for your panel. It will save a bunch of headache.
Edit: Sun's tutorial should get you what you need.
Follow-up to your clarification of the problem:
Take my code, and remove:
maximizedFrame.setUndecorated( true );
and size the frame bigger before you make it visible. That should satisfy the maximize-like behaviour you need.
Your other problem is that you cannot add JPanelD to the two JFrames. The pop-up frame must have its own unique JPanel object (let's call it JPanelE). So you need to:
Initialize and lay out JPanelE like you do JPanelD. That means giving JPanelE its own JList (and JTree, and so on).
Share the ListModel from JPanelD's JList with JPanelE's JList, and so on. The feasibility and details of executing this successfully depends on the specifics of your implementation, and is beyond the scope of your original problem.
Create a JWindow (or an undecorated JFrame) with a JPanel. Leave the JWindow invisible, initially. (The wiring of this new JPanel to the same data model used by the original JPanel is left as an exercise.)
When your maximize-panel button's ActionListener executes, it must:
2.1. Update the (invisible) JWindow's location and size to match the (visible) JFrame's.
2.2. Make your JFrame invisible.
2.3. Make your JWindow visible.
When your unmaximize-panel button's ActionListener executes, it must:
3.1. Update the (invisible) JFrame's location and size to match the (visible) JWindow's.
3.2. Make your JWindow invisible.
3.3. Make your JFrame visible
Example:
package stackoverflow;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MaximizingPanelApp extends JFrame {
private JPanel framePanel;
private JPanel windowPanel;
private JFrame maximizedFrame;
public static void main(String[] args) {
JFrame appFrame = new MaximizingPanelApp();
appFrame.setVisible( true );
}
public MaximizingPanelApp() throws HeadlessException {
super( "Application" );
setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
initialize();
}
private void initialize() {
// JFrame
{
Container container = getContentPane();
container.setLayout( new BorderLayout() );
framePanel = new JPanel();
framePanel.setBackground( Color.ORANGE );
container.add( framePanel, BorderLayout.CENTER );
JButton button = new JButton( new MaximizeAction() );
container.add( button, BorderLayout.SOUTH );
setSize( 400, 300 );
}
// JWindow
{
maximizedFrame = new JFrame();
Container container = maximizedFrame.getContentPane();
container.setLayout( new BorderLayout() );
windowPanel = new JPanel();
windowPanel.setBackground( Color.ORANGE );
container.add( windowPanel, BorderLayout.CENTER );
JButton button = new JButton( new UnMaximizeAction() );
container.add( button, BorderLayout.SOUTH );
maximizedFrame.setSize( getSize() );
maximizedFrame.setUndecorated( true );
}
}
private class MaximizeAction extends AbstractAction {
private MaximizeAction() {
super( "Maximize" );
}
public void actionPerformed(ActionEvent e) {
maximizedFrame.setSize( getSize() );
maximizedFrame.setLocation( getLocation() );
setVisible( false );
maximizedFrame.setVisible( true );
}
}
private class UnMaximizeAction extends AbstractAction {
private UnMaximizeAction() {
super( "Un-Maximize" );
}
public void actionPerformed(ActionEvent e) {
setLocation( maximizedFrame.getLocation() );
setSize( maximizedFrame.getSize() );
maximizedFrame.setVisible( false );
maximizedFrame.dispose();
setVisible( true );
}
}
}
This depends on the layout manager you use. If you add a JPanel to a JFrame using the default layout manager, and the JFrame only contains the JPanel and nothing else, you'll achieve what you describe.
Here's an example. The JPanel is green; notice how it resizes as you resize the JFrame.
import javax.swing.*;
import java.awt.*;
public class ScratchSpace {
public static void main(String[] args) {
JFrame frame = new JFrame("Stretchy panel demo");
final JPanel panel = new JPanel();
panel.setOpaque(true);
panel.setBackground(Color.GREEN);
panel.setPreferredSize(new Dimension(600, 400));
final JComponent contentPane = (JComponent) frame.getContentPane();
contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Categories

Resources