I want to create a common JPanel template that will be used by all the other panel. The Common JPanel Template would have a common header and footer. Below is the sample code of the common template JPanel.
import javax.swing.*;
public abstract class AbstractPanel extends JPanel {
public AbstractPanel() {
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
init();
addHeader();
addComponentsToScreen();
addFooter();
}
private void addHeader() {
add(new JLabel("Common Header"));
}
private void addFooter() {
add(new JLabel("Common Footer"));
}
protected abstract void init();
protected abstract void addComponentsToScreen();
}
Now I want to create a JPanel using this AbstractPanel with two different layouts based on the input parameter.
import javax.swing.*;
public class MyPanel extends AbstractPanel {
private boolean showDept;
private JTextField jTextEmp;
private JTextField jTextName;
private JTextField jTextDept;
public MyPanel(boolean showDept) {
super();
this.showDept = showDept;
}
protected void init() {
jTextEmp = new JTextField();
jTextName = new JTextField();
jTextDept = new JTextField();
}
protected void addComponentsToScreen() {
add(new JLabel("Employee"));
add(jTextEmp);
add(new JLabel("Name"));
add(jTextName);
if(showDept) {
add(new JLabel("Dept"));
add(jTextDept);
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.add(new MyPanel(true));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 500);
window.setVisible(true);
}
}
The problem with the above code is that the showDept is always false for the method addComponentsToScreen as it is called from the superclass constructor. Is there a better way to do this? Any help is appreciated.
Make your super class constructor a parameterised constructor and pass showDept to super class constructor.
Sample Code:
import javax.swing.*;
public abstract class AbstractPanel extends JPanel {
private boolean showDept; // add public getter for it
public AbstractPanel(boolean showDept) {
super();
this.showDept = showDept;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
init();
addHeader();
addComponentsToScreen();
addFooter();
}
private void addHeader() {
add(new JLabel("Common Header"));
}
private void addFooter() {
add(new JLabel("Common Footer"));
}
protected abstract void init();
protected abstract void addComponentsToScreen();
}
MyPanel class:
import javax.swing.*;
public class MyPanel extends AbstractPanel {
private boolean showDept;
private JTextField jTextEmp;
private JTextField jTextName;
private JTextField jTextDept;
public MyPanel(boolean showDept) {
super(showDept);
}
protected void init() {
jTextEmp = new JTextField();
jTextName = new JTextField();
jTextDept = new JTextField();
}
protected void addComponentsToScreen() {
add(new JLabel("Employee"));
add(jTextEmp);
add(new JLabel("Name"));
add(jTextName);
if(getShowDept()) {
add(new JLabel("Dept"));
add(jTextDept);
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.add(new MyPanel(true));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 500);
window.setVisible(true);
}
}
Other way around, make your panels totally independent from the each other. as this application basic you want to keep same header and footer on very view you can use following.
class MyDynamicPanel extends JPanel {
public MyDynamicPanel() {
super();
setLayout(new BorderLayout());
addAppHeader();
addAppFooter();
}
private void addAppHeader() {
add(new JLabel("Common Header"),BorderLayout.NORTH);
}
public void addAppCenter(JPanel centerPanel){
add(centerPanel,BorderLayout.CENTER);
}
private void addAppFooter() {
add(new JLabel("Common Footer"),BorderLayout.SOUTH);
}
}
This use border layout to adjust itself in every size of screen or frame.
Now your custom panel.
public class MyPanel extends MyDynamicPanel {
private JTextField jTextEmp;
private JTextField jTextName;
private JTextField jTextDept;
private JPanel centerPanel;
public MyPanel() {
super();
init();
addComponentsToScreen();
}
protected void init() {
centerPanel = new JPanel();
jTextEmp = new JTextField("",20);
jTextName = new JTextField("",20);
jTextDept = new JTextField("",10);
}
protected void addComponentsToScreen() {
centerPanel.add(new JLabel("Name"));
centerPanel.add(jTextEmp);
centerPanel.add(new JLabel("Employee"));
centerPanel.add(jTextName);
centerPanel.add(new JLabel("dept"));
centerPanel.add(jTextDept);
addAppCenter(centerPanel);
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.add(new MyPanel());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 500);
window.setVisible(true);
}
}
This Panel can have its own layout and components
Related
So I am trying to learn how to use card layout and in this sample code I would like to change the size of the frame to a certain size but using setSize does not work.
the following also does not work in the when added to createAndShowGui() function
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setPreferredSize(new Dimension(500,200));
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class MainGui2 extends JPanel {
private CardLayout cardLayout = new CardLayout();
private WelcomePanel welcomePanel = new WelcomePanel(this);
private HomePanel homePanel = new HomePanel();
public MainGui2() {
setLayout(cardLayout);
add(welcomePanel, WelcomePanel.NAME);
add(homePanel, HomePanel.NAME);
}
public void showCard(String name) {
cardLayout.show(this, name);
}
private static void createAndShowGui() {
MainGui2 mainPanel = new MainGui2();
JFrame frame = new JFrame("MainGui2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
//frame.pack();
frame.setSize(550, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class WelcomePanel extends JPanel {
public static final String NAME = "welcome panel";
private MainGui2 mainGui2;
public WelcomePanel(final MainGui2 mainGui2) {
this.mainGui2 = mainGui2;
add(new JLabel(NAME));
add(new JButton(new AbstractAction("Logon") {
#Override
public void actionPerformed(ActionEvent e) {
mainGui2.showCard(HomePanel.NAME);
}
}));
}
}
class HomePanel extends JPanel {
public static final String NAME = "home panel";
public HomePanel() {
add(new JLabel(NAME));
}
}
I would like to change the size of the frame to a certain size
Don't try to hard code frame sizes.
If you want extra space around the panels then in the constructor of your MainGui2 class you can add:
setBorder( new EmptyBorder(50, 50, 50, 50) );
This will adjust the preferred size of the panel and this size will now be taken into account when the pack() method is used.
I'm getting an AWT-EventQueue-0 Null Pointer Exception in the below code and I can't get to fix it.
I want to have a main frame, from which by pressing a button
I open a second frame, where I have the option to create new players,
which would show up in the main frame.
I passed the references to the constructors, but I still keep getting the error.
I would be very happy for some help, thanks!
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new App();
}
});
}
}
public class App extends JFrame {
private MainPanel mainPanel;
private SecondPanel secondPanel;
public App() {
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
secondPanel = new SecondPanel(mainPanel);
mainPanel = new MainPanel(secondPanel);
add(mainPanel);
}
}
public class MainPanel extends JPanel {
private JTextArea textArea;
private JScrollPane scrollPane;
private JButton options;
public MainPanel(SecondPanel secondPanel) {
textArea = new JTextArea();
textArea.setColumns(20);
textArea.setRows(5);
textArea.setSize(300, 300);
textArea.setVisible(true);
textArea.setEditable(false);
scrollPane = new JScrollPane(textArea);
scrollPane.setSize(new Dimension(400, 400));
options = new JButton("Options");
options.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
secondPanel.setVisible(true);
}
});
add(scrollPane);
add(options);
}
public JTextArea getTextArea() {
return textArea;
}
public void setTextArea(JTextArea textArea) {
this.textArea = textArea;
}
}
public class SecondPanel extends JFrame {
private JButton create, remove;
private JPanel panel;
public SecondPanel(MainPanel mainPanel) {
setVisible(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
panel = new JPanel();
panel.setLayout(new BorderLayout());
create = new JButton("create");
create.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mainPanel.getTextArea().append("New Player Created");
}
});
remove = new JButton("remove");
remove.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mp.getTextArea().setText("Player removed");
}
});
add(panel);
panel.add(create, BorderLayout.EAST);
panel.add(remove, BorderLayout.WEST);
}
}
Well, it has to be "null", because you don't initialise your MainPanel before you hand it over to the secondPanel.
Instead, make an own method for setting the MainPanel on the secondPanel and to set the secondPanel on the MainPanel.
I see that you need the secondPanel for instance in your constructor to set an ActionListener. Do that in your "setSecondPanel(SecondPanel sPanel)"-Method which, as I mentioned before, you should create.
am trying to add a button to Jframe from other class but it does not work
public class ShowMain {
public static void main(String[] args) throws Throwable {
//My JFrame
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setLayout(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBackground(Color.GRAY);
}
My other Class
public class Commands {
public static void main(String[] args) throws Throwable {
//JButtons
JButton button1 = new JButton();
button1.setText("");
button1.setBounds(120, 350, 400, 20);
button1.setVisible(true);
}
frame.add(button1) is not working
You've got all your code within two static main methods, meaning that the two classes can hardly interact at all. I suggest that you create true OOP-compliant classes, with instance fields ("state"), instance methods ("behavior"), and that you have one class call the method of another if you wish to change its state. For instance, if the Commands class is to add a JButton, then give your ShowMain class a method for this: public void addCommandButton(JButton button).
Having said this, I wouldn't do this at all if this were my code, but rather would follow a more MVC or "Model-View-Controller" program structure, where one set of classes would represent the program logic, another the user interactions (the listeners) and a 3rd set of classes for the GUI or "view".
For example, run this code that shows how to connect classes without them knowing about the other class (loose coupling):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ShowMain {
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JScrollPane scrollPane = new JScrollPane(mainPanel);
CreateActionPanel actionPanel = new CreateActionPanel();
new Controller(actionPanel, mainPanel);
JFrame frame = new JFrame("ShowMain");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(actionPanel, BorderLayout.PAGE_START);
frame.add(scrollPane, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class MainPanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 80;
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefW = Math.max(superSz.width, PREF_W);
int prefH = Math.max(superSz.height, PREF_H);
return new Dimension(prefW, prefH);
}
public MainPanel() {
setBorder(BorderFactory.createTitledBorder("Main Panel"));
}
public void addButtonAction(Action action) {
add(new JButton(action));
// so the button will be displayed properly
revalidate();
repaint();
}
}
class Controller {
public Controller(final CreateActionPanel actionPanel, final MainPanel mainPanel) {
actionPanel.addPropertyChangeListener(CreateActionPanel.ACTION_NAME, pcEvt -> {
mainPanel.addButtonAction(new AbstractAction((String) pcEvt.getNewValue()) {
{
int mnemonic = (int) pcEvt.getNewValue().toString().charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent evt) {
System.out.printf("Button %s pressed!%n", evt.getActionCommand());
}
});
});
}
}
class CreateActionPanel extends JPanel {
public static final String ACTION_NAME = "action name";
private JTextField actionNameField = new JTextField(10);
public CreateActionPanel() {
actionNameField.addActionListener((e -> {
String text = actionNameField.getText();
firePropertyChange(ACTION_NAME, null, text);
actionNameField.selectAll();
}));
add(new JLabel("Button Text to Add:"));
add(actionNameField);
}
}
i want to add panel from "newWork" class on pressing of "drop" button in "menuPan" class.
i cant add panel.
simply how to add Panel from different class on pressing button.
here are the three different classes .
MainClass :-
public class userFrame extends JFrame{
public void Frame()
{
setTitle("TEST CASE");
setSize(900,670);
add(new MenuPan(),BorderLayout.NORTH);
add(new WorkPan(),BorderLayout.CENTER);
setLocationRelativeTo(this);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String [] args){
userFrame u =new userFrame();
u.Frame();
}
}
MenuPan
public class MenuPan extends JPanel implements ActionListener{
WorkPan work=new WorkPan();
JButton view;
public menuPan() {
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
setLayout(new FlowLayout(1, 15, 10));
view=new JButton(" Registered Courses ");
view.addActionListener(this);
add(view);
}
#Override
public void actionPerformed(ActionEvent e) {
work.TaskPannel();
}
}
WorkPAN class :-
class WorkPan extends JPanel{
JPanel work=new JPanel();
public WorkPan() {
setBackground(Color.LIGHT_GRAY);
setLayout(new BorderLayout(40, 50));
}
void TaskPannel() {
System.out.println("here");
add(new NewWork(),BorderLayout.CENTER);// adds NewWork panel
}
}
NewWork Class
class NewWork extends JPanel{
public NewWork(){
setBackground(Color.red);
}
}
One issue -- you create one workPan (which should be renamed WorkPan), change its state in your ActionListener, but never add it to your GUI. So you appear to be changing the state of a non-displayed GUI component, and so it would make sense that nothing will show in the GUI.
Suggestions:
Be sure to create only one WorkPan reference,
Be sure to display this single reference in the GUI
Be sure that your ActionListener calls the appropriate method on the same reference.
Side recommendation:
Learn and follow Java naming conventions so you others can more easily understand and follow your code.
To swap JPanels within a GUI, I strongly advise you to use a CardLayout rather than adding and removing components manually as you're currently doing. Please check out the CardLayout Tutorial.
And my solution does work, but you also must call revalidate and repaint to get the GUI to layout the new component and repaint it. Note additions and changes as marked by the \\ !! comment
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooWork {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
userFrame.main(args);
});
}
}
class NewWork extends JPanel {
public NewWork() {
setBackground(Color.red);
}
}
class WorkPan extends JPanel {
JPanel work = new JPanel();
public WorkPan() {
setBackground(Color.LIGHT_GRAY);
setLayout(new BorderLayout(40, 50));
}
void TaskPannel() {
System.out.println("here");
add(new NewWork(), BorderLayout.CENTER);// adds NewWork panel
// !!
revalidate();
repaint();
// !!
}
}
class MenuPan extends JPanel implements ActionListener {
// !! WorkPan work = new WorkPan();
WorkPan work; // !!
JButton view; // !!
// !!
public MenuPan(WorkPan workPan) { // references are key
// !!
this.work = workPan; // set the reference!
// !!
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
setLayout(new FlowLayout(1, 15, 10));
view = new JButton(" Registered Courses ");
view.addActionListener(this);
add(view);
}
#Override
public void actionPerformed(ActionEvent e) {
work.TaskPannel();
}
}
class userFrame extends JFrame {
public void Frame() {
setTitle("TEST CASE");
setSize(900, 670);
// !!
WorkPan workPan = new WorkPan();
MenuPan menuPan = new MenuPan(workPan);
// !!
// !!
// add(new MenuPan(), BorderLayout.NORTH);
// add(new WorkPan(), BorderLayout.CENTER);
add(menuPan, BorderLayout.NORTH);
add(workPan, BorderLayout.CENTER);
// !!
setLocationRelativeTo(this);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
userFrame u = new userFrame();
u.Frame();
}
}
But again, cleaner is to use a CardLayout to help with the swapping:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class SwapStuff {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwapMainPanel mainPanel = new SwapMainPanel();
JFrame frame = new JFrame("SwapStuff");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
class SwapMainPanel extends JPanel {
private CardLayout cardLayout = new CardLayout();
private JPanel cardPanel = new JPanel(cardLayout);
private ButtonPanel buttonPanel = new ButtonPanel(this); // pass the reference
private WorkPanel workPanel = new WorkPanel();
private ViewPanel viewPanel = new ViewPanel();
public SwapMainPanel() {
cardPanel.add(workPanel, workPanel.getClass().getName());
cardPanel.add(viewPanel, viewPanel.getClass().getName());
setLayout(new BorderLayout());
add(buttonPanel, BorderLayout.PAGE_START);
add(cardPanel, BorderLayout.CENTER);
}
// one possible way to swap "cards"
public void nextCard() {
cardLayout.next(cardPanel);
}
}
class ButtonPanel extends JPanel {
private SwapMainPanel mainPanel;
public ButtonPanel(SwapMainPanel mainPanel) {
this.mainPanel = mainPanel; // set the reference!
add(new JButton(new SwapAction("Swap Panels", KeyEvent.VK_S)));
}
private class SwapAction extends AbstractAction {
public SwapAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
mainPanel.nextCard();
}
}
}
class WorkPanel extends JPanel {
public WorkPanel() {
setBorder(BorderFactory.createTitledBorder("Work Panel"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 400);
}
}
class ViewPanel extends JPanel {
public ViewPanel() {
setBorder(BorderFactory.createTitledBorder("View Panel"));
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 400);
}
}
In this code , I have used 3 classes all of them which extend the JPanel class , whose instances are added to a JFrame in the JForm3 class's constructor.
I am wondering if there's a way to display the text present in the text field(instance of JTextField declared in TextPanel class) in the printTextOnConsole() method in the ButtonPanel class.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JForm3
{
JFrame frame;
ButtonPanel bP;
TextPanel tP;
LabelPanel lP;
public JForm3()
{
frame = new JFrame("Java Window.");
bP = new ButtonPanel();
tP = new TextPanel();
lP = new LabelPanel();
frame.setSize(500,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER,tP);
frame.getContentPane().add(BorderLayout.EAST,bP);
frame.getContentPane().add(BorderLayout.WEST,lP);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
{
new JForm3();
}
}
class ButtonPanel extends JPanel implements ActionListener
{
JButton quitButton;
JButton printButton;
public ButtonPanel()
{
quitButton = new JButton("Quit");
printButton = new JButton("Print");
quitButton.addActionListener(this);
printButton.addActionListener(this);
this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
this.add(quitButton);
this.add(printButton);
}
public void actionPerformed(ActionEvent event)
{
if(event.getSource() == quitButton)
System.exit(0);
else
printTextOnConsole();
}
public void printTextOnConsole()
{
}
}
class LabelPanel extends JPanel
{
JLabel label;
public LabelPanel()
{
this.setLayout(new BorderLayout());
label = new JLabel("Enter Some Text :");
this.add(BorderLayout.CENTER,label);
this.setVisible(true);
}
}
class TextPanel extends JPanel
{
JTextField textField;
public TextPanel()
{
this.setLayout(new BorderLayout());
textField = new JTextField("Enter text here");
this.add(BorderLayout.CENTER,textField);
this.requestFocus();
textField.select(0,textField.getText().length());
this.setVisible(true);
}
}
Use an interface to loose couple the text functionality between JPanels.
interface TextRetriever {
String getText();
}
Then pass the instance of the TextRetriever (TextPanel) to ButtonPanel
class ButtonPanel extends JPanel implements ActionListener {
private TextRetriever textRetriever;
public ButtonPanel(TextRetriever textRetriever) {
this.textRetriever = textRetriever
...
}
public void printTextOnConsole() {
String text = textRetriever.getText();
}
}