Okay I want to place my button in a certain place on the screen. Is there any way to place it at an exact pixel location? Right now it places it to the far right of my screen. I have an image that I would want it to go over too.
import java.awt.AWTException;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.WritableRaster;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class UnfollowGUI extends JFrame{
private JLabel label;
private JButton button;
private ImageIcon bgi;
private JLabel bgl;
public static Rectangle gameSquare;
public static boolean rock = true;
public static boolean runningMine = true;
public static int stray = 0;
public static int strayCount = 0;
public static void main(String[] args) {
UnfollowGUI gui = new UnfollowGUI ();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when click x close program
//gui.setSize(886, 266);
gui.pack();
gui.setVisible(true);
gui.setTitle("Solid Cloud Inc - Twitter Unfolower");
}
public UnfollowGUI(){
setLayout(new FlowLayout());
bgi = new ImageIcon(getClass().getResource("tu.png"));
bgl = new JLabel (bgi);
add(bgl);
ImageIcon start = new ImageIcon(getClass().getResource("start.png"));
button = new JButton (start);
button.setBorder(BorderFactory.createEmptyBorder());
button.setContentAreaFilled(false);
add(button);
label = new JLabel ("");
add(label);
Events e = new Events();
button.addActionListener(e);
}
public class Events implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
label.setText("Searching");
try {
Unfollow();
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components.
To organize the components for a robust GUI, instead use layout managers (or combinations of them), along with layout padding & borders for white space.
Yet another way to achieve what you describe can be done this way (there are many alternatives, but in the end, it all depends on how you want your components to be relatively positionned to each other and what happens when the size of the parent container changes):
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestLoginGridBagLayout {
protected void initUI() throws MalformedURLException {
JFrame frame = new JFrame("Background image");
frame.getContentPane().setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel background = new JLabel(new ImageIcon(new URL("http://images2.layoutsparks.com/1/161318/city-lights-bridge-decoration.jpg")));
background.setVerticalAlignment(JLabel.BOTTOM);
background.setHorizontalAlignment(JLabel.LEFT);
background.setLayout(new BorderLayout());
frame.add(background);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
buttonPanel.setOpaque(false);
buttonPanel.add(new JButton("Some button in the bottom left"));
background.add(buttonPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
/**
* #param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
new TestLoginGridBagLayout().initUI();
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
});
}
}
You can place things in the exact place you want by not using a Layout Manager. This is called absolute positioning, and you can read a tutorial on it here: http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html
Here's a snippet of code from inside that tutorial:
pane.setLayout(null);
JButton b1 = new JButton("one");
JButton b2 = new JButton("two");
JButton b3 = new JButton("three");
pane.add(b1);
pane.add(b2);
pane.add(b3);
Insets insets = pane.getInsets();
Dimension size = b1.getPreferredSize();
b1.setBounds(25 + insets.left, 5 + insets.top,
size.width, size.height);
size = b2.getPreferredSize();
b2.setBounds(55 + insets.left, 40 + insets.top,
size.width, size.height);
size = b3.getPreferredSize();
b3.setBounds(150 + insets.left, 15 + insets.top,
size.width + 50, size.height + 20);
...//In the main method:
Insets insets = frame.getInsets();
frame.setSize(300 + insets.left + insets.right,
125 + insets.top + insets.bottom);
That ends up looking like this:
Related
Can't figure out why this wont work, I get a blank panel added to my gridbag panel.
I added a JLabel("test") between the frames I'm trying to add just to see that something IS getting added, it just isn't visible?
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
public class Workspace extends JTabbedPane {
static JFrame frame = new JFrame();
private JPanel grid;
private String text = new String("testing.");
Workspace() {
this.addTab("title", growPanel());
}
public static void main(String[] args) throws IOException {
createAndShowGUI();
}
private JPanel growPanel() {
JPanel gp = new JPanel(false);
gp.setPreferredSize(new Dimension(800,600));
//Add a button that adds my frame
JButton addComponentBtn = new JButton("Add Component");
addComponentBtn.addActionListener(e-> {
try {
addComponent();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
});
gp.add(addComponentBtn, BorderLayout.PAGE_START);
grid = new JPanel(new GridLayout(0, 2, 10, 10)); //any number of rows, 2 columns, H and V gap
JScrollPane sp = new JScrollPane(grid);
sp.setPreferredSize(new Dimension(800,600));
gp.add(sp, BorderLayout.CENTER);
this.setVisible(true);
return gp;
}
void addComponent() throws IOException {
System.out.println("adding");
grid.add(new JLabel("test"));
grid.add(new intf());
this.repaint();
frame.pack();
}
private static void createAndShowGUI() throws IOException {
//Create and set up the window.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add content to the window.
frame.add(new Workspace(), BorderLayout.CENTER);
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
And the intf.java class for the JInternalFrame:
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class intf extends JInternalFrame {
public intf () {
super("Document",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
JPanel jp = new JPanel();
JLabel jl = new JLabel("Hi I'm a label");
jp.add(jl);
this.add(jp);
this.pack();
this.repaint();
}
}
Edit:
The JPanel is used to hold the Layout, I don't think I can assign one to the TabbedPane?
Users will load in images which will appear on the left side of the GridLayout (I will upgrade this to a GridBag). After selecting regions on said images, graphs will appear on the right side. This is also why we use a scrollPane so that there is no limit to the number of images loaded. The TabbedPane will be used to split the load if a user loads in too many images (this is all not in the demo code shown here and not relevant to the problem).
The code I posted is for testing why the JInternalFrame doesn't show, so it only shows what is relevant to getting that to work.
Thank you all for your input.
It turned out to be a simple mistake of not having a necessary .setVisible(true)
Under the addComponent() method, the problem is solved when I replace
grid.add(new intf());
with
intf a = new intf();
a.setVisible(true);
grid.add(a);
package imgscoring;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import static java.lang.System.exit;
public class IMGSCORING
{
private JButton button1;
private JPanel main;
private JButton button2;
private JLabel lblLed;
private JButton button3;
private JLabel label;
private JLabel logo;
private static Image i;
public IMGSCORING() {
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
try {
runProgam();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
exit(1);
}
});
Image i = Toolkit.getDefaultToolkit().createImage("C:\\Users\\djuwo\\Desktop\\icon.jpg");
}
public static void paint(Graphics g)
{
g.drawImage(i, 0, 0, null);
}
public void runProgam() throws IOException, InterruptedException {
QrScanner run = new QrScanner();
run.runProgram();
}
public JPanel getMain() {
return main;
}
public void setMain(JPanel main) {
this.main = main;
}
public static void main(String[] args) {
JFrame frame = new JFrame(" IMG FORMING Label Generator");
frame.setContentPane(new IMGSCORING().main);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
ImageIcon img = new ImageIcon("C:\\Users\\djuwo\\Desktop\\icon.jpg");
frame.setIconImage(img.getImage());
}
private void createUIComponents() {
// TODO: place custom component creation code here
logo = new JLabel(new ImageIcon("icon.jpg"));
}
}
I am very new to using the gui for Java and based on looking around and seeing others code I can definitely tell mine is way off from how it should look.. Would appreciate feedback on how to properly format my code as well as how to add a background. The program works and buttons respond, icon are changed, etc. But I am unable to change the background. At first I tried the following but that obviously didn't work.
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:\\Users\\djuwo\\Desktop\\icon.jpg")))));
In the following solutions, you can see the following steps:
Override paintComponent of JPanel, in order to draw the image in its background.
Add any elements you want in the subclassed JPanel.
Add the subclassed JPanel to the content pane of the JFrame.
setOpaque(false) in the subclassed JPanel in order to show the background (where we paint the image).
In the first solution, I just paint the image once and not care about filling the frame when it is resized:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class RegularMain extends JPanel {
private final BufferedImage bimg;
public RegularMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
g.drawImage(bimg, 0, 0, this);
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RegularMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
But, another approach is to resize the image to correspond to the panel's size:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TransformMain extends JPanel {
private final BufferedImage bimg;
public TransformMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
this.bimg = Objects.requireNonNull(bimg);
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.scale(getWidth() / (double) bimg.getWidth(), getHeight() / (double) bimg.getHeight());
g2d.drawImage(bimg, 0, 0, this);
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TransformMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
And finally another approach is to make the image a TexturePaint, if you want the image to be repeated:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TextureMain extends JPanel {
private final TexturePaint paint;
public TextureMain(final BufferedImage bimg) {
//super(); //FlowLayout already.
paint = new TexturePaint(bimg, new Rectangle2D.Double(0, 0, bimg.getWidth(), bimg.getHeight()));
//Add your components here:
for (int i = 1; i <= 3; ++i)
super.add(prepare(new JButton("Button " + i)));
//Allow pixels to show through (ie the backgroung image to be shown):
super.setOpaque(false);
//Preparing the preferred size:
final Dimension prefsz = super.getPreferredSize(); //Gets the preferred size, after adding the components to this panel.
super.setPreferredSize(new Dimension(Math.max(prefsz.width, bimg.getWidth()), Math.max(prefsz.height, bimg.getHeight())));
}
#Override
protected void paintComponent(final Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(paint);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
super.paintComponent(g);
}
public static JButton prepare(final JButton button) {
button.addActionListener(e -> JOptionPane.showMessageDialog(button, "You clicked \"" + button.getText() + "\"!"));
return button;
}
public static void main(final String[] args) throws IOException {
final JFrame frame = new JFrame("Main frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new TextureMain(ImageIO.read(new File("your_image.png"))));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
The difference in the solutions above is visible when the frame/panel is resized. In the first case, the frame is not supposed to be resized so we only draw the image once, without changing it in size. In the second case the image size follows the panel's size. And in the final case we repeat the image vertically and horizontally up to the panel's size (by using TexturePaint).
All the cases have in common that we paint the image in paintComponent before everything else and that we setOpaque to false.
I am actually a beginner in Java Programming (on eclipse and without netbeans), and want to clear a JLabel presents in a JFrame by clicking a JButton without removing the JButton present at the top of this frame.
import java.awt.Color;
import java.awt.Container;
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.JFrame;
import javax.swing.JPanel;
import javax.swing.JOptionPane;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import javax.swing.BoundedRangeModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class ButtonTest extends JPanel implements ActionListener {
private JButton ouvrirButton = new JButton("Ouvrir");
private JButton retirerButton = new JButton("Retirer");
private JButton ajouterButton = new JButton("Ajouter");
public ButtonTest() {
add(ouvrirButton);
add(retirerButton);
add(ajouterButton);
ouvrirButton.addActionListener(this);
retirerButton.addActionListener(this);
ajouterButton.addActionListener(this);}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
Color color = getBackground();
// ACTION Button "OUVRIR"
// I WANT TO REMOVE THIS JLABEL TEXT WHEN I CLICK FOR EXEMPLE ON
// OR "RETIRER"
if (source == ouvrirButton)
{
color = Color.yellow;
JLabel lab1 = new JLabel("Text", JLabel.LEFT);
setLayout(new FlowLayout());
add(lab1 = new JLabel("INVENTAIRE : "));
lab1.setBounds(20, 15, 500, 100);
}
else if (source == retirerButton)
color = Color.red;
else if (source == ajouterButton)
color = Color.red;
setBackground(color);
repaint();
}
// The main
public static void main(String[] args) {
// NOM DE LA FENETRE
JFrame frame = new JFrame("Programme ");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container contentPane = frame.getContentPane();
contentPane.add(new ButtonTest());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1300, 700);
frame.setVisible(true);
}
}
I tried .setText("") but it doesn't work... Please help me !
I tried .setText("") but it doesn't work...
Yes it does. The problem is you create the label in the ActionListener so that label reference is only valid in the block of code that created it.
You need to create the label as an instance variable (the way you did for all you buttons) and add the label to the fame at the same time you add the buttons to the panel.
Then you will be able to access the label in the ActionListener and change the text.
The below code is not my actual code but a concise, runnable remake of what I am trying to achieve. I want the JPanel CP, an instance of clickPanel, to appear when the user clicks on the image in JPanel hasAnImage. I can see in the Netbeans console that the is executing because of the Sys.out.print, but nothing appears on the screen. I have tried setting visible to false then true again and revalidate() in the mousePressed event; the image moves to the left, but nothing appears on the screen. The goal is for CP to appear. What am I missing? Hope my question is clear.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Testo extends JFrame{
public Testo(){
BufferedImage image = null;
try {
image = ImageIO.read(new File("C:\\Users\\someimage.jpg"));
} catch (IOException ex) {
ex.printStackTrace();
}
;
final JLabel label = new JLabel(new ImageIcon(image));
JPanel hasAnImage = new JPanel();
hasAnImage.addMouseListener(new MouseAdapter(){
#Override //I override only one method for presentation
public void mousePressed(MouseEvent e) {
clickPanel CP = new clickPanel();
hasAnImage.add(CP);
revalidate();
//setVisible(false);
//setVisible(true);
}
});
hasAnImage.add(label);
add(hasAnImage);
setVisible(true);
}
public static void main(String[] args) {
Testo frame = new Testo();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.getContentPane().setBackground(Color.WHITE);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class clickPanel extends JPanel{
public clickPanel() {
setPreferredSize(new Dimension(100,60));
setMaximumSize(new Dimension(100,60));
setBackground(new Color(1.0f,1.0f,1.0f,0.1f));
setBorder(BorderFactory.createMatteBorder(2,2,2,2,Color.GREEN));
System.out.println("This is being executed...");
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setFont(new Font("Arial", Font.PLAIN, 12));
g.setColor(Color.GREEN);
g.drawString("CLICK", 2, 2);
}
}
}
Beyond revalidate();ing the pane, you also need to repaint(); it. Thus your mousePressed method should become:
public void mousePressed(MouseEvent e) {
clickPanel CP = new clickPanel();
hasAnImage.add(CP);
revalidate();
repaint();
}
For further reading: http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#repaint()
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).