I'm trying to create an Onscreen telepad where people can press the keypad buttons and itll come up in the text box I haven't made the ActionListner for the keypad yet but I want it to show up in the view... Here's the code for the Keypad Panel and the View there is also a duration timer which I've managed to get working but can't put them into one view
Here's the Keypad Panel
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
public class KeypadPanel extends JPanel {
private JButton noStar;
private JButton noHash;
private JButton[] buttons;
private JButton C;
private JButton add;
private JPanel keypadPanel;
public KeypadPanel(TelepadController controller) {
buttons = new JButton[10];
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton("" + i);
// buttons[i].addActionListener(controller.new NumberButtonListener());
}
//noStar.addActionListener(controller.new noStarActionListener);
//noHash.addActionListener(controller.new noHashActionListener);
//C.addActionListener(controller.new CActionListener);
//add.addActionListener(controller.new addActionListener);
noStar = new JButton("*");
noHash = new JButton("#");
C = new JButton("C");
add = new JButton("+");
JPanel keypadPanel = new JPanel();
keypadPanel.setLayout(new GridLayout(4, 3));
for (int i = 1; i <= 9; i++) {
keypadPanel.add(buttons[i]);
add(noStar);
add(noHash);
add(C);
add(add);
}
}
}
And here's the code for the main View
package londontelepad2;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.FontUIResource;
import org.apache.commons.beanutils.BeanUtils;
public class TelepadView implements Observer {
private StopwatchPanel stopwatchPanel;
private KeypadPanel keypadPanel;
private JFrame frame;
/**
*
* #param controller
*/
public TelepadView(TelepadController controller) {
super();
this.setResources();
frame = new JFrame("London Telepad");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
stopwatchPanel = new StopwatchPanel(controller);
//stopwatchPanel = new StopwatchPanel2(controller);
keypadPanel = new KeypadPanel(controller);
frame.getContentPane().add(stopwatchPanel);
frame.getContentPane().add(keypadPanel);
frame.pack();
}
public void show() {
frame.setVisible(true);
}
#Override
public void update(Observable observable, Object arg) {
if (arg.equals(Properties.TIME)) {
try {
stopwatchPanel.setTime(BeanUtils.getProperty(observable,
Properties.TIME));
} catch (Exception e) {
System.out.println(e);
}
}
}
public void setResetState() {
stopwatchPanel.setButtons(true, false, false);
}
public void setStoppedState() {
stopwatchPanel.setButtons(false, false, true);
}
public void setRunningState() {
stopwatchPanel.setButtons(false, true, false);
}
private void setResources() {
ColorUIResource defaultBackground = new ColorUIResource(Color.white);
ColorUIResource defaultForeground = new ColorUIResource(Color.black);
ColorUIResource disabledColor = new ColorUIResource(Color.lightGray);
FontUIResource smallFont = new FontUIResource(
new Font("Dialog", Font.BOLD, 12));
FontUIResource bigFont = new FontUIResource(
new Font("Dialog", Font.BOLD, 14));
UIManager.put("Button.background",
defaultBackground);
UIManager.put("Button.foreground",
defaultForeground);
UIManager.put("Button.disabledText",
disabledColor);
UIManager.put("Button.font", smallFont);
UIManager.put("Label.background",
defaultBackground);
UIManager.put("Label.foreground",
defaultForeground);
UIManager.put("Label.font", bigFont);
UIManager.put("Panel.background",
defaultBackground);
UIManager.put("Panel.foreground",
defaultForeground);
}
}
If I do the .add seperately I get an error to do with (actual and formal argument lists differ in length)
and if i do it together I get java.lang.IllegalArgumentException: cannot add to layout: constraint must be a string (or null)
And I can't find what it is im doing wrong!!
All the help in the world would be very appreciated seeing as I'm an Uber noob at java!
Thank you
Bilal
UPDATE
Here's a log of the error I reciveve when I put them in the same .add field
Exception in thread "main" java.lang.NullPointerException
at londontelepad2.KeypadPanel.<init>(KeypadPanel.java:48)
at londontelepad2.TelepadView.<init>(TelepadView.java:46)
at londontelepad2.TelepadController.<init>(TelepadController.java:33)
at londontelepad2.LondonTelepad2.main(LondonTelepad2.java:19)
Java Result: 1
Wait, KeypadPanel is just a plain object. Why doesn't it extend JPanel?
you are calling the add()-method of a JFrame to add your components to the frame? You need to call
frame.getContentPane().add(comp);
Related
I want to be able to call the Introduction.Intro() method into my main file code, but it tells me I am unable to call a non-static method intro from a static context. Since I am still fairly new to coding I'm not entirely sure what the problem is. I've added my codes down below. I've tried countless online methods but sadly none have seemed to work.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Start extends JFrame implements ActionListener
{
private JFrame Main;
private JPanel PanelA, PanelB, PanelC;
private JLabel Text, ImageL;
private JButton Button;
private ImageIcon Image;
public Start ()
{
//Button
Button = new JButton("Start");
Button.addActionListener(new ButtonListener());
//Text
Text = new JLabel("Welcome To The Game"); //ADD NAME OF THE GAME
//Image
Image = new ImageIcon(getClass().getResource("download.jfif")); //ADD THE IMAGE FOR WELCOME
ImageL = new JLabel(Image);
//Top Panel (PanelA) - Image
PanelA = new JPanel();
PanelA.setBorder(BorderFactory.createEmptyBorder(0,200,150,200));
PanelA.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelA.add(ImageL);
//Middle Panel (PanelB) - Text
PanelB = new JPanel();
PanelB.setBorder(BorderFactory.createEmptyBorder(50,200,10,200));
PanelB.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelB.add(Text);
//Bottom Panel (PanelC) - Buttons
PanelC = new JPanel();
PanelC.setBorder(BorderFactory.createEmptyBorder(0,200,20,200));
PanelC.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelC.add(Button);
//Main Frame
Main = new JFrame ();
Main.add(PanelA, BorderLayout.NORTH);
Main.add(PanelB, BorderLayout.CENTER);
Main.add(PanelC, BorderLayout.SOUTH);
Main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Main.setTitle("GAME TITLE"); //ADD THIS LATER
Main.pack();
Main.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae)
{
}
public class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == Button)
{
Introduction.Intro1(); //THESE LINE RIGHT HERE
return null; //THESE LINE RIGHT HERE
}
}
}
public static void main(String[] args)
{
new Start();
}
}
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Introduction
{
private JFrame Main;
private JPanel PanelD;
private JLabel Text, ImageL;
private JButton Button;
private ImageIcon Image;
public void Intro()
{
Image = new ImageIcon(getClass().getResource("guy.jfif"));
ImageL = new JLabel(Image);
PanelD = new JPanel();
PanelD.setBorder(BorderFactory.createEmptyBorder(0,100,10,100));
PanelD.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelD.add(ImageL);
PanelD.setVisible(true);
Main.add(PanelD, BorderLayout.NORTH);
}
}
EDIT: So I made another method in the Introduction class where I added this line of code, it managed to fix the error, however, the panel isn't being saved and my JFrame is outputting blank.
public static JFrame Intro1()
{
Introduction M = new Introduction();
return M;
}
If you are looking to initialize the Introduction class in main method of Start class, You can add belo code in main method after Start()
Introduction M = new Introduction();
You main method becomes :
public static void main(String[] args)
{
new Start();
Introduction M = new Introduction();
m.Intro
}
Looking at this set of code, It looks like there is incompatible issue, as you have declare JFrame as return type, while you are returning instance of Introduction.
public static JFrame Intro1()
{
Introduction M = new Introduction();
return M;
}
I'm having some trouble with a java project. I've made an empty GUI interface, and now I need to add some functionality to it. I'm stuck, however, on how to go about that. The basic layout has 4 radio buttons, Rectangle, Box, Circle, and Cylinder. I have a group panel that has 4 separate panels that each have text boxes with labels for entering height, length, width, and radius. Here's how it looks: GUI layout. Depending on the radio button that is selected, certain boxes that aren't needed should be hidden. For example, if Rectangle is selected, only the boxes for length and width should be visible.
The main frame that will display everything is here:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JButton;
import java.awt.Font;
public class GUIFrame extends JFrame
{
//private final BorderLayout layout;
private final FlowLayout layout;
private final JLabel lblTitle;
private final JButton btnProc;
public GUIFrame()
{
super("GUI Layout");
Font titleFont = new Font("Verdana", Font.BOLD, 26);
btnProc = new JButton("Click to Process");
lblTitle = new JLabel("Figure Center");
lblTitle.setFont(titleFont);
widthPanel myWidth = new widthPanel();
myWidth.setLocation(0, 400);
lengthPanel myLength = new lengthPanel();
heightPanel myHeight = new heightPanel();
radiusPanel myRadius = new radiusPanel();
radioButtonPanel myButtons = new radioButtonPanel();
//layout = new BorderLayout(3, 2);
layout = new FlowLayout();
JPanel txtGroup = new JPanel();
txtGroup.setLayout(new GridLayout(2, 2));
txtGroup.add(myWidth);
txtGroup.add(myLength);
txtGroup.add(myRadius);
txtGroup.add(myHeight);
setLayout(layout);
add(lblTitle);
add(myButtons);
add(txtGroup);
add(btnProc);
if(myButtons.btnRectangle.isSelected())
{
myHeight.setVisible(false);
myRadius.setVisible(false);
}
}
private class RadioButtonHandler implements ItemListener
{
#Override
public void itemStateChanged(ItemEvent event)
{
}
}
}
I can get this working using if statements, but I'm supposed to be using event handlers and I'm lost on how to code that to get it to work properly.
if it helps, here's the code for the button panel:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import java.awt.GridLayout;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
public class radioButtonPanel extends JPanel
{
private final JRadioButton btnRectangle;
private final JRadioButton btnBox;
private final JRadioButton btnCircle;
private final JRadioButton btnCylinder;
private final ButtonGroup radioButtonGroup;
private final JLabel label;
private final JPanel radioPanel;
public radioButtonPanel()
{
radioPanel = new JPanel();
radioPanel.setLayout(new GridLayout(5,1));
btnRectangle = new JRadioButton("Rectangle", true);
btnBox = new JRadioButton("Box", false);
btnCircle = new JRadioButton("Circle", false);
btnCylinder = new JRadioButton("Cylinder", false);
label = new JLabel("Select A Figure:");
radioPanel.add(label);
radioPanel.add(btnRectangle);
radioPanel.add(btnBox);
radioPanel.add(btnCircle);
radioPanel.add(btnCylinder);
radioButtonGroup = new ButtonGroup();
radioButtonGroup.add(btnRectangle);
radioButtonGroup.add(btnBox);
radioButtonGroup.add(btnCircle);
radioButtonGroup.add(btnCylinder);
add(radioPanel);
}
}
And a sample of one of the panels. They all follow the same setup, just different variable names.
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;
import java.awt.GridLayout;
public class heightPanel extends JPanel
{
private final JLabel lblHeight;
private final JTextField txtHeight;
private final JPanel myHeight;
public heightPanel()
{
myHeight = new JPanel();
myHeight.setLayout(new GridLayout(2,1));
lblHeight = new JLabel("Enter Height:");
txtHeight = new JTextField(10);
myHeight.add(lblHeight);
myHeight.add(txtHeight);
add(myHeight);
}
}
The below code should give you a quick introduction of how to use event listener/handler for your button group (JRadioButtons).
but I'm supposed to be using event handlers and I'm lost on how to
code that to get it to work properly.
//add listener to the rectangle button and should be the same for the other `JRadioButtons` but with different `identifiers`.
btnRectangle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnRectangle){
//TODO
}
}
});
Depending on the radio button that is selected, certain boxes that
aren't needed should be hidden. For example, if Rectangle is selected,
only the boxes for length and width should be visible.
//To hide JTextFields use
void setVisible(boolean visible) method. You should pass false as the argument to the method if you want to hide the JTextField.
Example:
btnRectangle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnRectangle){
TextFieldName.setVisible(false); // set the textfields that you want to be hidden once the Rectangle button is chosen.
}
}
});
I'm stacked!! I am relatively new to java and I have been days searching the web to solve my problem without success, its now time to ask for your help.
I cannot...(actually do not know) how to change the actionlistener (actionPerformed) after the second click in an array of JButtons. Please find the code below so that you can guide me.
This is how the program performs right now.
On the 1st click on the grid, the border of the button clicked will change to 'blue' and another button will change its boarder to 'red'. on the next click the same action is performed.
What I need is to change action when the 'red' bordered button is clicked, lets say change the color of the buttons from the 'red' to the 'blue' buttons.(x 3 buttons).
The logic about how to perform the final result I think I can do on my own but my problem is how to change the action when the red bordered button is clicked.
Your help is much appreciated!
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class ChangeGrid
{
private JButton[][] bu1 = new JButton[10][10];
public ChangeGrid(JFrame frame)
{
super();
JPanel pCenter = new JPanel();
JPanel pTop = new JPanel();
frame.add(pCenter, BorderLayout.CENTER);
frame.add(pTop, BorderLayout.NORTH);
JPanel Grid10x10 = new JPanel(new GridLayout(10,10));
pCenter.add(Grid10x10);
for(int c = 0; c< 10; c++)
{
for (int r = 0; r< 10; r++)
{
bu1[c][r] = new JButton("X");
Grid10x10.add(bu1[c][r]);
final int i = c;
final int j = r;
bu1[i][j].addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
int f = (3-1);
bu1[i][j].setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
if ((j+f)<=9)
{
bu1[i][j+f].setBorder(BorderFactory.createLineBorder(Color.RED, 2));
}
else
{
JOptionPane.showMessageDialog(null,"move your 1st click more to the center");
}
}
});
}
}
}
}
import javax.swing.JFrame;
public class GUIFrame extends JFrame
{
public GUIFrame()
{
super("Grid 10 x 10");
this.setSize(1350, 700);
this.setVisible(true);
this.setResizable(true);
this.setDefaultCloseOperation(GUIFrame.EXIT_ON_CLOSE);
}
}
import javax.swing.JFrame;
public class Main
{
public static void main(String args[])
{
JFrame frame = new GUIFrame();
ChangeGrid pC = new ChangeGrid(frame);
frame.pack();
}
}
You can change your ActionListener like next:
bu1[i][j].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int f = (3 - 1);
Border border = bu1[i][j].getBorder();
if(border instanceof LineBorder){
LineBorder lBorder = (LineBorder) border;
if(lBorder.getLineColor().equals(Color.RED)){
//red border clicked
redBorderAction(bu1[i][j]);
return;
}
}
defaultAction(i,j,f);
}
});
And other methods:
private void defaultAction(int i, int j, int f) {
bu1[i][j].setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
if ((j + f) <= 9) {
bu1[i][j + f].setBorder(BorderFactory.createLineBorder(Color.RED, 2));
} else {
JOptionPane.showMessageDialog(null,"move your 1st click more to the center");
}
}
private void redBorderAction(JButton btn) {
btn.setBorder(BorderFactory.createLineBorder(Color.BLUE, 2));
}
I have a Java program which until now used to get the input from command line and then proceed accordingly.
Now, I want to have a basic GUI for this. It will need a few buttons which will trigger the events. I am experienced in HTML and JavaScript. Is it possible to write in HTML (or similar syntax) to generate the GUI?
I don't want to go in Swing and awt solution, because I would rather concentrate on the main program than on the GUI.
Here's another alternative. See also How to Use HTML in Swing Components.
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
/**
* #see http://stackoverflow.com/a/10067256/230513
* #see http://stackoverflow.com/a/7454691/230513
*/
public class Pathfinder extends JPanel {
private static final int TEXT_SIZE = 32;
private JTextField srcField = new JTextField(TEXT_SIZE);
private JTextField dstField = new JTextField(TEXT_SIZE);
private JTextField valueField1 = new JTextField(TEXT_SIZE);
private JTextField valueField2 = new JTextField(TEXT_SIZE);
private String srcPath, dstPath, value1, value2;
public Pathfinder() {
super(new GridLayout(0, 1));
this.add(createPathPanel("Source Directory", srcField));
this.add(createPathPanel("Target Directory", dstField));
this.add(createFieldPanel("Some Value:", valueField1));
this.add(createFieldPanel("Another Value:", valueField2));
JPanel submitPanel = new JPanel();
submitPanel.add(new JButton(new AbstractAction("Submit") {
#Override
public void actionPerformed(ActionEvent e) {
srcPath = srcField.getText();
dstPath = dstField.getText();
value1 = valueField1.getText();
value2 = valueField2.getText();
process();
}
}));
this.add(submitPanel);
}
private void process() {
// see ProcessBuilder http://stackoverflow.com/questions/5740390
System.out.println(srcPath);
System.out.println(dstPath);
System.out.println(value1);
System.out.println(value2);
}
private JPanel createPathPanel(String name, final JTextField jtf) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
panel.add(new JButton(new AbstractAction(name) {
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser jfc = new JFileChooser(
new File(System.getProperty("user.dir")));
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int result = jfc.showOpenDialog(Pathfinder.this);
if (result == JFileChooser.APPROVE_OPTION) {
jtf.setText(jfc.getSelectedFile().getPath());
}
}
}));
panel.add(jtf);
return panel;
}
private JPanel createFieldPanel(String name, JTextField jtf) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
panel.add(new JLabel(name));
panel.add(jtf);
return panel;
}
private void display() {
JFrame f = new JFrame("Pathfinder");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Pathfinder pf = new Pathfinder();
if (args.length > 0) {
pf.srcPath = args[0];
pf.dstPath = args[1];
pf.process();
} else {
pf.display();
}
}
});
}
}
I want to have a basic GUI for this. It will need a few buttons which will trigger the events.
This 'basic GUI' goes slightly beyond the spec. to add an output area.
import java.awt.*;
import javax.swing.*;
class SimpleEventGUI {
SimpleEventGUI() {
JPanel gui = new JPanel(new BorderLayout());
JToolBar toolBar = new JToolBar();
for (int ii=1; ii<6; ii++) {
toolBar.add(new JButton("Event " + ii));
if (ii%2==0) {
toolBar.addSeparator();
}
}
gui.add(toolBar, BorderLayout.NORTH);
gui.add( new JScrollPane(new JTextArea(5,30)), BorderLayout.CENTER );
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new SimpleEventGUI();
}
});
}
}
You may consider Google Web Toolkit with Window Builder which allow you to build a rich internet interface using Java and interact with the existing logic.
If you want something quick, you can build a Swing GUI using Window Builder
I am trying to get an internal frame to contain tabbed panes. However, my code does not seem to be loading the panes into the internal frame. I have my code in the java files, called InternalFrame.java and TabbedPaneSample.java. The code for both files is included below. Can anyone show me how to fix the code below so that it loads the tabbed panes when I run InternalFrame.java?
Here is my code:
The code for InternalFrame.java is:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
public class InternalFrame extends JFrame {
JButton openButton;
JLayeredPane desktop;
JInternalFrame internalFrame;
TabbedPaneSample myTabbedPaneSample = new TabbedPaneSample();
public InternalFrame() {
super("Click button to open internal frame with two panels.");
setSize(500, 400);
openButton = new JButton("Open");
Panel p = new Panel();
p.add(openButton);
add(p, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
openButton.addActionListener(new OpenListener());
desktop = new JDesktopPane();
desktop.setOpaque(true);
add(desktop, BorderLayout.CENTER);
}
class OpenListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if ((internalFrame == null) || (internalFrame.isClosed())) {
internalFrame = new JInternalFrame("Internal Frame", true, true, true, true);
internalFrame.setBounds(50, 50, 200, 100);
internalFrame.add(myTabbedPaneSample, BorderLayout.CENTER);
internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
internalFrame.pack();
internalFrame.setMinimumSize(new Dimension(300, 300));
desktop.add(internalFrame, new Integer(1));
internalFrame.setVisible(true);
}
}
}
public static void main(String args[]) {
InternalFrame myInternalFrame = new InternalFrame();
myInternalFrame.setVisible(true);
}
}
And the code for TabbedPaneSample.java is:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class TabbedPaneSample extends JTabbedPane {
private JTabbedPane tabbedPane = new JTabbedPane();
private ImageIcon closeImage = new ImageIcon("C:/test/shipIcon.gif");
private Dimension closeButtonSize;
private int tabCounter = 0;
public TabbedPaneSample() {
closeButtonSize = new Dimension(closeImage.getIconWidth() + 2, closeImage.getIconHeight() + 2);
}
public void add() {
final JPanel content = new JPanel();
JPanel tab = new JPanel();
tab.setOpaque(false);
JLabel tabLabel = new JLabel("Tab " + (++tabCounter));
JButton tabCloseButton = new JButton(closeImage);
tabCloseButton.setPreferredSize(closeButtonSize);
tabCloseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int closeTabNumber = tabbedPane.indexOfComponent(content);
tabbedPane.removeTabAt(closeTabNumber);
}
});
tab.add(tabLabel, BorderLayout.WEST);
tab.add(tabCloseButton, BorderLayout.EAST);
this.addTab(null, content);
this.setTabComponentAt(this.getTabCount() - 1, tab);
}
public static void main(String[] args) {
TabbedPaneSample main = new TabbedPaneSample();
main.add();
main.add();
}
}
Here's one approach, shown below. A more flexible approach using Action is referenced here.
Addendum: Reviewing your code, you should let the various layout managers and component preferred sizes do more of the work, as shown. In particular, this.setPreferredSize() is done for demonstration purposes. In a real application, you would restore user size and location preferences.
package overflow;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
/** #see https://stackoverflow.com/posts/6514889 */
public class InternalFrame extends JFrame {
JButton openButton;
JLayeredPane desktop;
JInternalFrame internalFrame;
public InternalFrame() {
super("Click button to open internal frame with two tabs.");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(400, 400));
openButton = new JButton("Open");
JPanel p = new JPanel();
p.add(openButton);
this.add(p, BorderLayout.SOUTH);
openButton.addActionListener(new OpenListener());
desktop = new JDesktopPane();
this.add(desktop, BorderLayout.CENTER);
this.pack();
this.setLocationRelativeTo(null);
}
class OpenListener implements ActionListener {
private static final int DELTA = 40;
private int offset = DELTA;
public void actionPerformed(ActionEvent e) {
internalFrame = new JInternalFrame(
"Internal Frame", true, true, true, true);
internalFrame.setLocation(offset, offset);
offset += DELTA;
internalFrame.add(createTabbedPane());
desktop.add(internalFrame);
internalFrame.pack();
internalFrame.setVisible(true);
}
}
private JTabbedPane createTabbedPane() {
JTabbedPane jtp = new JTabbedPane();
createTab(jtp, "One");
createTab(jtp, "Two");
return jtp;
}
private void createTab(JTabbedPane jtp, String s) {
jtp.add(s, new JLabel("TabbedPane " + s, JLabel.CENTER));
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
InternalFrame myInternalFrame = new InternalFrame();
myInternalFrame.setVisible(true);
}
});
}
}
First of all, I think Finally, I think you shouldn't use desktop.add(internalFrame, new Integer(1)) but rather desktop.add(internalFrame) instead, the reason is that JDesktopPane uses its layers (it is a JLayeredPane subclass) internally, and I don't think you should play with layers yourself.
Then, following this problem I had once with JInternalFrame, I would advise you call pack() after adding the internal frame to the desktop pane.
Hence, you should try with your OpenListener class looking like this:
class OpenListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if ((internalFrame == null) || (internalFrame.isClosed())) {
internalFrame = new JInternalFrame("Internal Frame", true, true, true, true);
internalFrame.setBounds(50, 50, 200, 100);
internalFrame.add(myTabbedPaneSample, BorderLayout.CENTER);
internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// internalFrame.pack();
internalFrame.setMinimumSize(new Dimension(300, 300));
// desktop.add(internalFrame, new Integer(1));
desktop.add(internalFrame);
internalFrame.pack();
internalFrame.setVisible(true);
}
}
}
Besides, I also agree with trashgod comments on Action of course and the simplifying rework he has done on your snippet.
I preferred to create in my Main Frame class (which extends JFrame) the following function:
private void showIntFrame(Class intFrameClass) {
JInternalFrame targetFrame = null;
int xoff = 0, yoff = 0;
for(JInternalFrame jif : jdp.getAllFrames()) {
if(jif.getClass().equals(intFrameClass))
targetFrame = jif;
if(jif.getLocation().x > xoff)
xoff = jif.getLocation().x;
if(jif.getLocation().y > yoff)
yoff = jif.getLocation().y;
}
if(targetFrame == null) {
try {
Constructor<JInternalFrame> c = intFrameClass.getConstructor(MainFrame.class);
targetFrame = c.newInstance(MainFrame.this);
} catch (Exception ex) {
System.err.println("Exception in MainFrame.showIntFrame() while creating new JInternalFrame instance. " + ex.getLocalizedMessage());
ex.printStackTrace();
return;
}
jdp.add(targetFrame);
targetFrame.setLocation(xoff + 30, yoff + 30);
}
targetFrame.setVisible(true);
try {
targetFrame.setSelected(true);
} catch (PropertyVetoException ex) {
System.err.println("PropertyVetoException in MainFrame.showIntFrame() while activating JInternalFrame instance. " + ex.getLocalizedMessage());
}
}
Here jdp is instance of JDesktopPane, which previously was set as ContentPane of my main JFrame.
Because my programs often contain numbers of different classes, inherited from JInternalFrame, it is easier to call this function from event handlers to show new subclass of JInternalFrame.
Every subclass of JInternalFrame in my programs have one constructor with one parameter - MainFrame (main JFrame).