I have a JPanel with a JLabel in it, is it possible to have a mouse click on JLabel, following by another mouse click on any location on the JPanel to create an instance of the JLabel. Basically, I can click the JLabel and create new instances of it anywhere on the JPanel.
Here is a simple example of what you are looking for. What you need is deepCopy of the clicked JLabel and then retrieve it back and draw it to the JPanel.
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import java.awt.*;
import javax.swing.border.*;
class CopyLabel extends JFrame
{
JPanel panel ;
JPanel centerPanel;
int clickCount = 0;
ByteArrayOutputStream baos;
ByteArrayInputStream bins;
public void createAndShowGUI()
{
setTitle("Copy JLabel");
JLabel label1 = new JLabel("JLabel1");
JLabel label2 = new JLabel("JLabel2");
panel = new JPanel();
label1.setForeground(Color.blue);
label2.setForeground(Color.red);
panel.add(label1);
panel.add(label2);
class MyMouseAdapter extends MouseAdapter
{
#Override
public void mouseClicked(MouseEvent evt)
{
clickCount = 1;
try
{
deepCopy((JLabel)evt.getSource());
}
catch (Exception ex){}
}
}
label1.addMouseListener(new MyMouseAdapter());
label2.addMouseListener(new MyMouseAdapter());
panel.setBorder(BorderFactory.createTitledBorder("Controllers"));
getContentPane().add(panel,BorderLayout.SOUTH);
centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createRaisedBevelBorder(),"Drawing Pad",TitledBorder.CENTER,TitledBorder.TOP));
centerPanel.setLayout(null);
centerPanel.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent evt)
{
if (clickCount == 1)
{
try
{
pasteLabel(evt.getX(),evt.getY());
}
catch (Exception ex){}
}
}
});
getContentPane().add(centerPanel);
setSize(300,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void deepCopy(JLabel label)throws Exception
{
baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(label);
oos.close();
}
public void pasteLabel(int x, int y)throws Exception
{
if (clickCount == 1)
{
bins = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream oins = new ObjectInputStream(bins);
JLabel obj = (JLabel)oins.readObject();
centerPanel.add(obj);
obj.setBounds(x,y,obj.getWidth(),obj.getHeight());
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
CopyLabel cl = new CopyLabel();
cl.createAndShowGUI();
}
});
}
}
You can attach mouse listener to your JLabel like this
final JLabel jlabel = new JLabel("Test");
jlabel.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Hello : "+ e);
Point location = MouseInfo.getPointerInfo().getLocation();
targetPanel.add(cloneLabelAt(jlabel, location));
}
});
private JLabel cloneLabelAt(JLabel label, Point location)
{
JLabel cloned = new JLabel(label.getText());
cloned.setLocation(location);
return cloned;
}
Inside your mouse click handler you can create another JLabel and add it to your target panel
Related
I want to make the JLabel answer print out the answer when users press the label. But I found line 104 does not use the "input" from HanoisFrames. It keeps using 0 as "input" and prints out "0". I tried to write line 96 as
"private class MouseHandler extends HanoisFrames implements MouseListener, MouseMotionListener" and I used "super (int)" but it does not work. What should I do?
package Hanois;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Hanoi {
private JFrame frame;
JButton[][] buttons= new JButton[3][3];
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Hanoi window = new Hanoi();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Hanoi() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 901, 696);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JMenuBar menubar=new JMenuBar();//Menu
frame.setJMenuBar(menubar);
JMenu file= new JMenu("File");
file.setFont(new Font("Segoe UI", Font.PLAIN, 21));
menubar.add(file);
JMenuItem exit= new JMenuItem("Exit");//provide users a way to exit
exit.setFont(new Font("Segoe UI", Font.PLAIN, 21));
file.add(exit);
class exitaction implements ActionListener{
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
exit.addActionListener(new exitaction());
JPanel panelone = new JPanel();
frame.getContentPane().add(panelone, BorderLayout.CENTER);
panelone.setBackground(Color.WHITE);
panelone.setLayout(new GridLayout(3,4,3,3));
JPanel paneltwo = new JPanel();
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
paneltwo.setBackground(Color.WHITE);
JLabel lblFunHanoiTower = new JLabel("Fun Hanoi Tower");
frame.getContentPane().add(paneltwo, BorderLayout.NORTH);
lblFunHanoiTower.setForeground(Color.BLACK);
lblFunHanoiTower.setBackground(SystemColor.activeCaption);
lblFunHanoiTower.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
paneltwo.add(lblFunHanoiTower);
ActionListener listener =new ActionListener() {
public void actionPerformed(ActionEvent e) {
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
if(e.getSource()==buttons[row][col]){
buttons[row][col].setBackground(Color.lightGray);
HanoisFrames f= new HanoisFrames(((row*3)+(col+3)));
f.setVisible(true);//
}
}
}
}
};
for(int row = 0; row < buttons.length ; row++) {
for(int col= 0; col < buttons[0].length ;col++) {
buttons[row][col] = new JButton("level "+String.valueOf((row*3)+(col+3)-2));
buttons[row][col].setFont(new Font("Tempus Sans ITC", Font.BOLD, 32));
buttons[row][col].setBackground(SystemColor.controlHighlight);
buttons[row][col].setSize(6, 6);
buttons[row][col].addActionListener(listener);
panelone.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
panelone.add(buttons[row][col]);
}
}
}
}
package Hanois;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class HanoisFrames extends JFrame {
private JPanel contentPane;
private JButton ret ;
private JButton next;
private JButton last;
private JLabel answer;
private JMenu menu;
private JButton reset;
private JLabel move;
private JPanel panel;
static int input;
private JLabel lblLevel;
boolean showAnswer=false;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
HanoisFrames frame = new HanoisFrames(input);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public HanoisFrames(int input) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 901, 696);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
MouseHandler handler=new MouseHandler();
panel = new JPanel();
contentPane.add(panel, BorderLayout.SOUTH);
panel.setLayout(new GridLayout(2,3));
move = new JLabel(" Move");
panel.add(move);
reset = new JButton("Reset");
panel.add(reset);
answer = new JLabel();
answer.setHorizontalAlignment(SwingConstants.CENTER);
panel.add(answer);
answer.setText("Answer");
answer.addMouseListener(handler);
answer.addMouseMotionListener(handler);
last = new JButton("Last");
panel.add(last);
ret = new JButton("Return");
panel.add(ret);
next = new JButton("Next");
panel.add(next);
lblLevel = new JLabel("LEVEL "+ String.valueOf(input-2));
lblLevel.setHorizontalAlignment(SwingConstants.CENTER);
lblLevel.setFont(new Font("Viner Hand ITC", Font.PLAIN, 36));
contentPane.add(lblLevel, BorderLayout.NORTH);
}
public int hanoiCalculator(int input) {
if (input==0){
return 0;
}else if (input==1){
return 1;
}else{
return 2*(hanoiCalculator(input-1)+1)-1;
}
}
private class MouseHandler implements MouseListener,MouseMotionListener {
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
answer.setText("Answer: "+String.valueOf(hanoiCalculator(input)).toString());
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent e) {
answer.setText("Answer: ");
}
}
}
Here:
public class HanoisFrames extends JFrame {
private JPanel contentPane;
// ...
private JPanel panel;
static int input;
You never set your input value in your HanoiFrames constructor, and so it remains the default value for an int field, 0. But even if you did set the field because it's a static field, any changes made to it in any HanoiFrames class will change the value in all HanoiFrames classes, and so it cannot be a static field.
So, change input declaration to non-static:
public class HanoisFrames extends JFrame {
private JPanel contentPane;
private JButton ret;
//.....
private JPanel panel;
private int input; // private non-static field now
and set it in the constructor:
public HanoisFrames(int input) {
this.input = input;
This way each HanoisFrames will have a unique and durable input value
Side Recommendation:
I would advise against creating and then swapping a bunch of JFrames. Instead gear your code towards creating JPanels, and then swap them when needed, using a CardLayout.
I need a running order of pages 1-5 pages. I am using the card layout to navigate between each page after entering data on each page. The navigation to the next page works via an Action Listener on each text field.
My question is how do I pass the input from each card/page to the next? I can System.out.println each TextFeilds data. But I can't grab this information in the next card/action listener. The reason I need this to happen is I'd like to compare the strings of each page and also display a label of page 1's input on page/card2.
I apologize in advance for the massive block of code... Most of you will recognise most of this code anyway as it's copied from the CardLayout sample java code. I have just added two cards just now until I get the basics of passing variables back and fourth.
All help is appreciated even a small push the the right direction.
import java.awt.*;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.event.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Scanner;
import javax.swing.*;
public class CardLayoutDemo implements ItemListener {
JPanel cards; //a panel that uses CardLayout
final static String TEXTPANEL = "Card1 with text";
final static String TEXTPANEL2 = "Card with JTextField";
public void addComponentToPane(Container pane) {
//Put the JComboBox in a JPanel to get a nicer look.
JPanel comboBoxPane = new JPanel(); //use FlowLayout
String comboBoxItems[] = { TEXTPANEL, TEXTPANEL2};
JComboBox cb = new JComboBox(comboBoxItems);
cb.setEditable(false);
cb.addItemListener(this);
comboBoxPane.add(cb);
//Create the "cards".
JPanel card1 = new JPanel();
JTextField jtf=new JTextField("", 40);
jtf.setSize(40, 10);
card1.add(jtf);
JLabel lab1 = new JLabel("Page1 Text", JLabel.LEFT);
card1.add(lab1 = new JLabel("Page1"));
JPanel card2 = new JPanel();
JTextField jtf2=new JTextField("", 40);
jtf2.setSize(40, 10);
card2.add(jtf2);
JLabel lab2 = new JLabel("Page2 Text", JLabel.LEFT);
card2.add(lab2 = new JLabel("Page2 "));
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, TEXTPANEL);
cards.add(card2, TEXTPANEL2);
pane.add(cards, BorderLayout.CENTER);
jtf.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
String getText1 = jtf.getText();
System.out.println("PAGE1 ");
System.out.println(getText1);
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, TEXTPANEL2);
jtf2.requestFocus();
jtf2.requestFocusInWindow();
}
//JOptionPane.showMessageDialog(null,"Action Listener is working");
});
//PAGE2
jtf2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
String getText2 = jtf2.getText();
System.out.println("PAGE2 ");
System.out.println(getText2);
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, TEXTPANEL);
jtf.requestFocus();
jtf.requestFocusInWindow();
jtf.setText("");
}
});
}//ADD COMPONENT TO PANE
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
// String getLoginUser1 = jtf.getText();
//System.out.println(getLoginUser1);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CardLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 300));
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the content pane.
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Here is another view on the problem. You could create some kind of cards manager and hold all required info inside of it. Here is an example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class CardLayoutDemo implements ItemListener {
private static class QuizManager {
final java.util.List<String> quizData = new ArrayList<>();
final java.util.List<JPanel> cards = new ArrayList<>();
final JPanel rootView;
public QuizManager(JPanel root){
rootView = root;
}
private JPanel createQuizPanel(String pageText, final int index) {
JPanel card = new JPanel();
JTextField jtf=new JTextField("", 40);
jtf.setSize(40, 10);
JLabel prev = new JLabel("", JLabel.LEFT);
card.add(prev);
card.add(jtf);
card.add(new JLabel(pageText, JLabel.LEFT));
jtf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
QuizManager.this.onCardSubmited(card, index, jtf.getText());
}
});
card.addComponentListener(new ComponentAdapter() {
#Override
public void componentShown(ComponentEvent e) {
super.componentShown(e);
jtf.requestFocus();
jtf.requestFocusInWindow();
String text = QuizManager.this.getPrevStringFor(index);
if (text != null) {
prev.setText(text);
}
}
});
return card;
}
private String getPrevStringFor(int index) {
if (index == 0) return null;
return quizData.get(index-1);
}
private String buildPanelName(int index) {
return String.format("card-%d", index);
}
public QuizManager addCard(String title) {
int index = cards.size();
quizData.add(null);//not set yet, just allocating
JPanel card = createQuizPanel(title, index);
cards.add(card);//this array looks like redundant
rootView.add(card, buildPanelName(index));
return this;
}
private void showCard(int index) {
CardLayout cl = (CardLayout) (rootView.getLayout());
cl.show(rootView, buildPanelName(index));
}
public void show() {
showCard(0);
}
public void onCardSubmited(JPanel card, int cardIndex, String text) {
System.out.println("page " + cardIndex);
System.out.println("text : " + text);
quizData.set(cardIndex, text);
if (cardIndex < cards.size() - 1) {
showCard(cardIndex + 1);
} else {
System.out.println("WE FINISHED");
//add finalazing code here
}
}
}
JPanel cardsRoot;
public void addComponentToPane(Container pane) {
cardsRoot = new JPanel(new CardLayout());
QuizManager manager = new QuizManager(cardsRoot)
.addCard("First page")
.addCard("Second page")
.addCard("Third card")
.addCard("Forth card");
pane.add(cardsRoot, BorderLayout.CENTER);
manager.show();
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cardsRoot.getLayout());
cl.show(cardsRoot, (String)evt.getItem());
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CardLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 300));
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the content pane.
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
/* Use an appropriate Look and Feel */
try {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Take a look how easy would be to create many of cards.
You've got the variable declaration of key components buried within the addComponentToPane(...) method, limiting their scope to this method only, preventing you from getting the information you need. While the canonical solution for this sort of problem is to use an model-view-controller or MVC type pattern so that the model (the underlying program logic and data) is extracted out of the view (the GUI), you can do a quick and dirty solution just by giving your variables private class scope.
For instance, if the JTextField was called textField and was held in a JPanel that acts as a "card", say called cardPanel, you could create a class that looked something like so:
public class CardPanel extends JPanel {
// constants to give the GUI a bigger size
private static final int PREF_W = 300;
private static final int PREF_H = 100;
// our key JTextField declared at class level
private JTextField textField = new JTextField(20);
// a JLabel to display the previous cardpanel's text
private JLabel label = new JLabel(" ");
// create the JPanel
public CardPanel(String name) {
setName(name);
setBorder(BorderFactory.createTitledBorder("Panel " + name));
JPanel labelPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
labelPanel.add(new JLabel("Prior Card's Word: "));
labelPanel.add(label);
setLayout(new BorderLayout());
add(textField, BorderLayout.PAGE_START);
add(labelPanel, BorderLayout.CENTER);
}
// have to jump through this hoop if we want to JTextField to
// have focus when a card is swapped
public void setFocusOnTextField() {
textField.requestFocusInWindow();
textField.selectAll();
}
// to make our GUI larger
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// allow outside classes to add a listener to the JTextField
public void addActionListener(ActionListener listener) {
textField.addActionListener(listener);
}
// allow outside classes to get text from the text field
public String getTextFieldText() {
return textField.getText();
}
// allow outside classes to put text into the JLabel
public void setLabelText(String text) {
label.setText(text);
}
}
And then we could use it like so:
public class MyCardLayoutDemo extends JPanel {
private static final String[] NAMES = {"One", "Two", "Three", "Four"};
private Map<String, CardPanel> namePanelMap = new HashMap<>();
private CardLayout cardLayout = new CardLayout();
private int nameIndex = 0;
public MyCardLayoutDemo() {
setLayout(cardLayout);
MyListener listener = new MyListener();
for (String name : NAMES) {
CardPanel cardPanel = new CardPanel(name);
cardPanel.addActionListener(listener);
add(cardPanel, name);
namePanelMap.put(name, cardPanel);
}
}
private class MyListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// get the current CardPanel
String name = NAMES[nameIndex];
CardPanel currentCard = namePanelMap.get(name);
// advance the name index to get the next CardPanel
nameIndex++;
nameIndex %= NAMES.length;
name = NAMES[nameIndex];
CardPanel nextCard = namePanelMap.get(name);
// get text from current CardPanel
String text = currentCard.getTextFieldText();
nextCard.setLabelText(text); // and put it into next one
// swap cards
cardLayout.show(MyCardLayoutDemo.this, name);
nextCard.setFocusOnTextField();
}
}
private static void createAndShowGui() {
MyCardLayoutDemo mainPanel = new MyCardLayoutDemo();
JFrame frame = new JFrame("My CardLayout Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
I want to create a window(JFrame) and draw a string on it.However, when i run my code the window appears but without the string i want to draw on it. I have made two classes LabelFrame and WebStalker.
Here is my code :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.net.*;
public class LabelFrame extends JFrame {
private final JTextField urlString;
private final JButton backButton;
private final JButton loadButton;
private Stack urlStack = new Stack();
String content;
class GraphicPane extends JComponent {
public GraphicPane() {
super();
}
#Override
public void paint(Graphics g) {
g.setFont(new Font(Font.SANS_SERIF, Font.ITALIC, 14));
g.drawString("Hello, World!", 30, 20);
}
}
public LabelFrame() {
setTitle("WebStalker");
setSize(600, 600);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setLayout(new FlowLayout());
urlString = new JTextField(30);
backButton = new JButton("Load");
loadButton = new JButton("Back");
GraphicPane gp = new GraphicPane();
this.add(new JLabel("URL"));
this.add(urlString);
this.add(loadButton);
this.add(backButton);
this.add(gp);
TextFieldHandler tHandler = new TextFieldHandler();
ButtonHandler bHandler = new ButtonHandler();
urlString.addActionListener(tHandler);
backButton.addActionListener(bHandler);
loadButton.addActionListener(bHandler);
}
private class TextFieldHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent event){
content = URLReaderFinal.Reading(event.getActionCommand());
}
}
private class ButtonHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource() == loadButton) {
try {
//remember url for back button
urlStack.push(urlString.getText());
content = URLReaderFinal.Reading(urlString.getText());
} catch (Exception e) {
System.out.println("Unable to load page");
}
} else if (event.getSource() == backButton) {
if (urlStack.size() <= 1) {
return;
}
try {
urlStack.pop();
String urlString = (String)urlStack.peek();
} catch (Exception e) {
System.out.println("Unable to load page");
}
}
}
}
}
And the other class :
import java.awt.*;
import javax.swing.*;
public class WebStalker extends JFrame {
public static void main(String[] args) {
LabelFrame frame = new LabelFrame();
frame.setVisible(true);
}
}
You panel is using a FlowLayout. A FlowLayout respects the preferred size of a component. The preferred size of your custom component is (0, 0) so there is nothing to paint.
Override the getPreferredSize() method to return a proper size for your component.
Also, custom painting is done by overriding the paintComponent() method.
Since you are extending JComponent you should also do a fillRect(...) on the entire size of the component to make sure the background is cleared. It would be easier to extend JPanel, then you can just invoke super.paintComponent() at the start to clear the background.
Read the section from the Swing tutorial on Custom Painting for working example and more information on both of these suggestions.
I am using a self made toolbar to navigate through my application and the toolbar is present on all pages. Each time a new page is displayed I am closing the current frame and opening a new one, using the following code:
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
I am doing it this way as the ActionListeners are declared in the toolbar class, whilst the frames for each page are declared at runtime and are not static.
This all works fine except for one particular case-the "cancel" button, where the first time the frame is accessed it will close once. The second time it will close and re open 2 times, the third 3 and so on. I have tracked this using the "counter" in the code.
I have minimised the code to recreate the same behaviour, as below:
Toolbar Class
public class Toolbar {
static JButton buttonCancel = new JButton("Cancel");
static int counter;
public static JPanel Toolbar(String panelname){
FlowLayout layout = new FlowLayout();
JPanel Toolbar = new JPanel(new BorderLayout());
Toolbar.setLayout(layout);
GridLayout GLayout = new GridLayout(2,1);
GLayout.setVgap(0);
JPanel container2 = new JPanel();
if(panelname.matches("Customers")){
container2.setLayout(GLayout);
JButton buttonAddCust = new JButton("Add Cust");
container2.add(buttonAddCust, BorderLayout.PAGE_START);
buttonAddCust.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
Customers.AddCustomersGui();
}
});
}
JPanel container21 = new JPanel();
if(panelname.matches("Add Customers")){
container21.setLayout(GLayout);
container21.add(buttonCancel, BorderLayout.PAGE_START);
buttonCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter ++;
java.awt.Window win[] = java.awt.Window.getWindows();
for(int i=0;i<win.length;i++){
win[i].dispose();
}
System.out.println("Coutner " + counter);
Customers.CustomersGui();
}
});
}
Toolbar.add(container2);
Toolbar.add(container21);
return Toolbar;
}
}
GUI class
public class Customers extends Toolbar{
public static void CustomersGui(){
final JFrame frame = new JFrame("Customers");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel customers = new JPanel();
customers.add(Toolbar.Toolbar(frame.getTitle()));
frame.setContentPane(customers);
frame.setSize(1200,500);
frame.setVisible(true);
}
public static void AddCustomersGui(){
final JFrame frame1 = new JFrame("Add Customers");
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel Addcustomers = new JPanel();
Addcustomers.add(Toolbar.Toolbar(frame1.getTitle()));
frame1.setContentPane(Addcustomers);
frame1.setSize(1200,500);
frame1.setVisible(true);
}
}
main class
public static void main(String[] args) {
Customers.CustomersGui();
}
You are adding a new ActionListener to the buttonCancel, with each iteration of your code and this is the reason for your program's behavior.
Also, as per my comment, you state,
Each time a new page is displayed I am closing the current frame and opening a new one.
A better design is probably not to swap windows which can be annoying, but rather to swap JPanel views using a CardLayout. Please read The Use of Multiple JFrames, Good/Bad Practice?.
For example, add this line of code to your program:
if (panelname.matches("Add Customers")) {
container21.setLayout(GLayout);
container21.add(buttonCancel, BorderLayout.PAGE_START);
buttonCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter++;
java.awt.Window win[] = java.awt.Window.getWindows();
for (int i = 0; i < win.length; i++) {
win[i].dispose();
}
System.out.println("Coutner " + counter);
Customers.CustomersGui();
}
});
// ***** add this here **********
System.out.println("buttonCancel ActionListener count: "
+ buttonCancel.getListeners(ActionListener.class).length);
}
and you'll see that the ActionListeners get added multiple times to this button.
An example of swapping views:
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SwapPanels extends JPanel {
public static final String CUSTOMER = "customer";
public static final String ADD_CUSTOMER = "Add Customer";
protected static final int PREF_W = 800;
protected static final int PREF_H = 600;
public static final String CANCEL = "Cancel";
private CardLayout cardLayout = new CardLayout();
public SwapPanels() {
setLayout(cardLayout);
add(createCustomerPanel(CUSTOMER), CUSTOMER);
add(createAddCustomerPanel(ADD_CUSTOMER), ADD_CUSTOMER);
}
public void showCard(String key) {
cardLayout.show(this, key);
}
public JPanel createAddCustomerPanel(String name) {
JPanel addCustPanel = new JPanel() {
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
};
addCustPanel.setName(name);
addCustPanel.setBorder(BorderFactory.createTitledBorder(name));
addCustPanel.add(new JButton(new AbstractAction(CANCEL) {
{
int mnemonic = (int)getValue(NAME).toString().charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
if (CANCEL.equals(e.getActionCommand())) {
SwapPanels.this.showCard(CUSTOMER);
}
}
}));
return addCustPanel;
}
private JPanel createCustomerPanel(String name) {
JPanel custPanel = new JPanel() {
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
};
custPanel.setName(name);
custPanel.setBorder(BorderFactory.createTitledBorder(name));
custPanel.add(new JButton(new AbstractAction(ADD_CUSTOMER) {
{
int mnemonic = (int)getValue(NAME).toString().charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
if (ADD_CUSTOMER.equals(e.getActionCommand())) {
SwapPanels.this.showCard(ADD_CUSTOMER);
}
}
}));
return custPanel;
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SwapPanels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SwapPanels());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Sorry if its an obvious question.I have been trying to switch panels in the same window using cardlayout.But when i run my application nothing happens.
System.out.println(mntmBookingStatus);
the above statement does get printed on console.but not able to make out why cards arent switching when i click on menuitem "booking status" and "invoice entry".
public class StartDemo {
private JFrame frame;
private JPanel cards = new JPanel(new CardLayout());
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
StartDemo window = new StartDemo();
window.initialize();
window.frame.pack();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 772, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setVisible(true);
// main menu
menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
// mainmenuoption-1
mnNewMenu = new JMenu("Entries");
menuBar.add(mnNewMenu);
// option-1 items
mntmBookingStatus = new JMenuItem("Booking Status");
mnNewMenu.add(mntmBookingStatus);
mntmBookingStatus.addActionListener(new MenuListenerAdapter());
mntmInvoiceEntry = new JMenuItem("Invoice Entry");
mnNewMenu.add(mntmInvoiceEntry);
mntmInvoiceEntry.addActionListener(new MenuListenerAdapter());
StartDemo demo = new StartDemo();
demo.addComponentToPane(frame.getContentPane());
}
public void addComponentToPane(Container pane) {
JPanel booking_status = new JPanel();
JPanel invoice_entry = new JPanel();
JPanel customer_ledger = new JPanel();
JPanel create_user = new JPanel();
try {
JPanelWithBackground panelWithBackground = new JPanelWithBackground(
"D:\\Kepler Workspace\\WEDemo\\images\\abc.jpg");
cards.add(panelWithBackground, "name_282751308799");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//the layout code for all the panels is written here.
//its to big to post here
cards.add(booking_status, BOOKINGPANEL);
cards.add(invoice_entry, INVOICEPANEL);
cards.add(customer_ledger, CUSTOMERLEDGER);
cards.add(create_user, CREATEUSER);
pane.add(cards, BorderLayout.CENTER);
}
public class MenuListenerAdapter implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout c = (CardLayout) (cards.getLayout());
if (e.getSource() == mntmBookingStatus) {
c.show(cards, BOOKINGPANEL);
System.out.println(mntmBookingStatus);
} else if (e.getSource() == mntmInvoiceEntry) {
c.show(cards, INVOICEPANEL);
System.out.println(mntmInvoiceEntry);
}
}
This is my JPanelWithBackground class
public class JPanelWithBackground extends JPanel {
private Image backgroungImage;
private Image scaledBackgroundImage;
// Some code to initialize the background image.
// Here, we use the constructor to load the image. This
// can vary depending on the use case of the panel.
public JPanelWithBackground(String fileName) throws IOException {
backgroungImage = ImageIO.read(new File(fileName));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
// Draw the backgroung image
g.drawImage(backgroungImage, 0, 0,getWidth(),getHeight(),null);
}
It's these two lines right here
StartDemo demo = new StartDemo();
demo.addComponentToPane(frame.getContentPane());
Since your initialize() method isn't static I think it's safe to assume that you instantiate youe StartDemo again in the main method. In that case, the above code truly is your problem and would totally explain why it doesn't work. Just do this
//StartDemo demo = new StartDemo(); <-- get rid of this.
addComponentToPane(frame.getContentPane());
Tested with code additions only to get it running. Also please not my comments above. setVisible(true) generally is the last thing you should do after adding all components.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class StartDemo {
private JFrame frame;
private JPanel cards = new JPanel(new CardLayout());
JMenuBar menuBar;
JMenu mnNewMenu;
JMenuItem mntmBookingStatus;
JMenuItem mntmInvoiceEntry;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new StartDemo().initialize();
}
});
}
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 772, 700);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// main menu
menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
// mainmenuoption-1
mnNewMenu = new JMenu("Entries");
menuBar.add(mnNewMenu);
// option-1 items
mntmBookingStatus = new JMenuItem("Booking Status");
mnNewMenu.add(mntmBookingStatus);
mntmBookingStatus.addActionListener(new MenuListenerAdapter());
//StartDemo demo = new StartDemo();
addComponentToPane(frame.getContentPane()); mntmInvoiceEntry = new JMenuItem("Invoice Entry");
mnNewMenu.add(mntmInvoiceEntry);
mntmInvoiceEntry.addActionListener(new MenuListenerAdapter());
frame.setVisible(true);
}
public void addComponentToPane(Container pane) {
JPanel booking_status = new JPanel();
JPanel invoice_entry = new JPanel();
//JPanel customer_ledger = new JPanel();
//JPanel create_user = new JPanel();
try {
JPanelWithBackground panelWithBackground = new JPanelWithBackground(
"/resources/stackoverflow5.png");
cards.add(panelWithBackground, "name_282751308799");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cards.add(booking_status, "booking");
cards.add(invoice_entry, "invoice");
//cards.add(customer_ledger, CUSTOMERLEDGER);
//cards.add(create_user, CREATEUSER);
pane.add(cards, BorderLayout.CENTER);
}
class JPanelWithBackground extends JPanel {
Image img;
public JPanelWithBackground(String path) throws IOException {
img = ImageIO.read(getClass().getResource(path));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
public class MenuListenerAdapter implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
CardLayout c = (CardLayout) (cards.getLayout());
if (e.getSource() == mntmBookingStatus) {
c.show(cards,"booking");
System.out.println(mntmBookingStatus);
} else if (e.getSource() == mntmInvoiceEntry) {
c.show(cards, "invoice");
System.out.println(mntmInvoiceEntry);
}
}
}
}