.class after an Interface with Custom Events in Java Swing - java

I'm learning about Java Swing and I have found an advanced code (in my opinion) about Swing using MVC and Observer patterns. It is very difficult for me and I try to understand it. And I have 2 questions:
What exactly does DetailListener.class? It is the first time when I use .class after an interface. I have tried to search on stackoverflow about ".class syntax" and I see it can be used after a class, but I still don't understand what it does in this situation.
What exactly does the method fireDetailEvent()?
Thanks in advance!
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new MainFrame("Hello world Swing");
frame.setSize(500, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
MainFrame
import java.awt.BorderLayout;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class MainFrame extends JFrame {
private JTextArea textArea;
public MainFrame(String title) {
super(title);
Container c = getContentPane();
c.setLayout(new BorderLayout());
textArea = new JTextArea();
DetailsPanel detailsPanel = new DetailsPanel();
detailsPanel.addDetailListener(new DetailListener() {
public void detailEventOccurred(DetailEvent event) {
String text = event.getText();
textArea.append(text);
}
});
c.add(textArea, BorderLayout.CENTER);
c.add(detailsPanel, BorderLayout.WEST);
}
}
DetailsPanel
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;
public class DetailsPanel extends JPanel {
private static final long serialVersionUID = -5115286206114930420L;
private EventListenerList listenerList = new EventListenerList();
public DetailsPanel() {
Dimension size = getPreferredSize();
size.width = 250;
setPreferredSize(size);
setBorder(BorderFactory.createTitledBorder("Personal details"));
JLabel nameLabel = new JLabel("Name:");
JLabel occupationLabel = new JLabel("Occupation:");
JTextField nameField = new JTextField(10);
JTextField occupationField = new JTextField(10);
JButton addBtn = new JButton("Add");
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
////// First column /////
gc.anchor = GridBagConstraints.LINE_END;
gc.weightx = 0.5;
gc.weighty = 0.5;
gc.gridx = 0;
gc.gridy = 0;
add(nameLabel, gc);
gc.gridy = 1;
add(occupationLabel, gc);
////// Second column /////
gc.anchor = GridBagConstraints.LINE_START;
gc.gridx = 1;
gc.gridy = 0;
add(nameField, gc);
gc.gridy = 1;
add(occupationField, gc);
////// Final row /////
gc.anchor = GridBagConstraints.FIRST_LINE_START;
gc.weightx = 10;
gc.weighty = 10;
gc.gridy = 2;
add(addBtn, gc);
addBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
String occupation = occupationField.getText();
String text = name + ": " + occupation + "\n";
System.out.println(text);
fireDetailEvent(new DetailEvent(this, text));
}
});
}
public void fireDetailEvent(DetailEvent event) {
Object[] listeners = listenerList.getListenerList();
for (int i = 0; i < listeners.length; i += 2) {
if (listeners[i] == DetailListener.class) {
((DetailListener)listeners[i+1]).detailEventOccurred(event);
}
}
}
public void addDetailListener(DetailListener listener) {
listenerList.add(DetailListener.class, listener);
}
public void removeDetailListener(DetailListener listener) {
listenerList.remove(DetailListener.class, listener);
}
}
DetailListener
import java.util.EventListener;
public interface DetailListener extends EventListener {
public void detailEventOccurred(DetailEvent event);
}
DetailEvent
import java.util.EventObject;
public class DetailEvent extends EventObject {
private String text;
public DetailEvent(Object source, String text) {
super(source);
this.text = text;
}
public String getText() {
return text;
}
}

1) What exactly does DetailListener.class?
From the API:
Instances of the class Class represent classes and interfaces in a running Java application.
This is somewhat confusing so let's look at a an example. Calling DetailListener.class provides its Class representation. In this specific case DetailListener.class provides a Class<DetailListener> so it's possible to do this:
Class<DetailListener> cdl = DetailListener.class;
cdl is just another variable similar to how frame is just another variable.
frame happens to be a JFrame which provides some methods, while cdl is a Class<DetailListener> which provides a different set of methods.
cdl's type is a Class<DetailListener> which represents the DetailListener class.
but I still don't understand what it does in this situation
Consider this code:
listenerList.add(DetailListener.class, listener);
listenerList is of type EventListenerList. According to its API, the add(...) method parameters require a Class and a T instance. In this case, the generic T is DetailListener. So far the listener has been registered but it leads into your next question.
#2 What exactly does the method fireDetailEvent()?
When the listener was registered the listenerList keeps an internal array which can be referenced later. The array holds both the Class and the actual listener instance. So invoking
Object[] listeners = listenerList.getListenerList();
provides access to the array. In this case:
listeners[0] = DetailListener.class
listeners[1] = reference to the anonymous inner class instance created from detailsPanel.addDetailListener(...)
So the loop in fireDetailEvent(...) is guaranteed to be a multiple of 2 (0 also works if there are no registered listeners). But listenerList could hold any type of listener, so
if (listeners[i] == DetailListener.class) {
uses the Class to check for equality to make sure it's safe to caste to be able to pass the DetailEvent to the listener (which is the next element in the array). Using == (instead of .equals()) is okay in this context since DetailListener.class always provides the same Class.

What exactly does DetailListener.class?
DetailListener.class is a so-called class literal.
Basically, it is a constant of type Class referring to the
DetailListener type.
You can find more and better explanations about this at
What is a class literal in Java?
and its answers.
What exactly does the method fireDetailEvent()?
Your DetailsPanel class uses an EventListenerList for handling event
listeners and sending events to them.
The comment given in class EventListenerList
gives a detailed description how to use it.
Read this description and you will recognize, that the methods
addDetailListener, removeDetailListener and fireDetailEvent
of your class DetailsPanel are written exactly following this description.
The method fireDetailEvent fires a DetailEvent to all those listeners
which have registered themselves earlier by addDetailListener.

Related

JApplet will not initialize when Listener is added to jcheckBox

Alright, since it didn't work out last time. I'm going to post my full code here and i hope i can get some replies as to why it's not working. I'm not getting any compiling errors, the applet runs and then nothing shows up and at the bottom it says "applet not initialized." I'm using blueJ. I apologize for the length of this post, I could not figure out how to make this same error with a shorter code.
I have a JApplet program with multiple classes. RegPanel,WorkshopPanel, ConferenceGUI, ConferenceHandler and ConferenceClient. Basically RegPanel and WorkShop panel are added to the ConferenceGUI, which also creates and adds a couple small panels. The ConferenceClient class is just used to initaite the class to run the applet. The ConferenceHandler is used to handle the action events for the JButtons, JTextArea, JCheckBox, etc... Normally this whole program works fine. Except when i add a listener for the JCheckBox, it stops working. The problem area is in the ConferenceGUI class, it is commented with stars to be clear what's causing the problem.
I've been stuck on this error for about a day now and the frustration i'm feeling is overwhelming. So, to get to the point, here's the complete code:
(please, i don't need tips on any other part of the code, I just need help with that error). You may want to skip over the code and just read the ConferenceGUI class where the error is located. If you could also explain to me why this isn't working, it would be very helpful to me. Thank you in advance!
RegPanel Class:
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class RegPanel extends JPanel
{
protected JTextField regNameTextBox;
protected JCheckBox keynoteCheckBox;
protected final String[] REGTYPES = {"Please select a type","Business","Student","Complimentary"};
protected JPanel registrationPanel, keynotePanel;
protected final double BUSINESSFEE = 895,STUDENTFEE = 495,COMPLIMENTARYFEE = 0;
protected JComboBox regTypeComboBox;
public RegPanel()
{
//Set the layout for the RegPanel to be 2 rows and 1 column.
setLayout(new GridLayout(2, 1));
//initiate the registration panel and add a border
registrationPanel = new JPanel();
registrationPanel.setLayout(new FlowLayout());
registrationPanel.setBorder(BorderFactory.createTitledBorder("Registrant's Name & Type"));
//initiate the comboBox and add the registration types
regTypeComboBox = new JComboBox(REGTYPES);
//Initiate the textfield with a size of 20
regNameTextBox = new JTextField(20);
//Add the registration name textbox and type combobox to the registration panel
registrationPanel.add(regNameTextBox);
registrationPanel.add(regTypeComboBox);
//initiate the second panel for the checkbox
keynotePanel = new JPanel();
keynotePanel.setLayout(new FlowLayout());
//initiate the checkbox and add it to the keynote panel
JCheckBox keynoteCheckBox = new JCheckBox("Dinner and Keynote Speach");
keynotePanel.add(keynoteCheckBox);
//Add the two panels to the main panel
add(registrationPanel);
add(keynotePanel);
}
public double getRegistrationCost()
{
double regFee = 0;
String comboBoxAnswer = (String)regTypeComboBox.getSelectedItem();
switch (comboBoxAnswer)
{
case "Business": regFee = BUSINESSFEE;
break;
case "Student": regFee = STUDENTFEE;
break;
}
return regFee;
}
public double getKeynoteCost()
{
double keynoteCost = 0;
if(keynoteCheckBox.isSelected())
{
keynoteCost = 30;
}
return keynoteCost;
}
public String getRegType()
{
String regType = (String)regTypeComboBox.getSelectedItem();
return regType;
}
}
WorkshopPanel Class:
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class WorkshopPanel extends JPanel
{
protected final double ITFEE = 295, DREAMFEE = 295, JAVAFEE = 395, ETHICSFEE = 395;
protected final String[] WORKSHOPS = {"IT Trends in Manitoba","Creating a Dream Career","Advanced Java Programming","Ethics: The Challenge Continues"};
protected JList workshopList;
public WorkshopPanel()
{
setLayout(new FlowLayout());
workshopList = new JList(WORKSHOPS);
workshopList.setSelectionMode(2);
BorderFactory.createTitledBorder("Workshops");
add(workshopList);
}
public double getWorkshopCost()
{
Object[] workshops = workshopList.getSelectedValues();
double cost = 0;
String workshopString;
for (int i = 0; i < workshops.length; i++)
{
workshopString = (String)workshops[i];
switch(workshopString)
{
case "IT Trends in Manitoba":
cost += ITFEE;
break;
case "Creating a Dream Career":
cost += DREAMFEE;
break;
case "Advanced Java Programming":
cost += JAVAFEE;
break;
case "Ethics: The Challenge Continues":
cost += ETHICSFEE;
break;
}
}
return cost;
}
public Object[] getWorkshopList()
{
Object[] workshopListArray = workshopList.getSelectedValues();
return workshopListArray;
}
}
ConferenceGUI class (THIS CONTAINS THE ERROR):
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class ConferenceGUI extends JPanel
{
protected JPanel titlePanel, buttonPanel;
protected RegPanel regPanel;
protected WorkshopPanel workshopPanel;
protected JLabel titleLabel;
protected JButton calculateButton, clearButton;
protected JTextArea resultArea;
protected JScrollPane textScroll;
public ConferenceGUI()
{
setLayout(new BorderLayout());
titlePanel = new JPanel();
titleLabel = new JLabel("Select Registration Options",JLabel.CENTER);
Font titleFont = new Font("SansSerif", Font.BOLD, 18);
titleLabel.setFont(titleFont);
titlePanel.add(titleLabel);
add(titlePanel, BorderLayout.NORTH);
regPanel = new RegPanel();
add(regPanel, BorderLayout.WEST);
workshopPanel = new WorkshopPanel();
add(workshopPanel, BorderLayout.EAST);
buildButtonPanel();
add(buttonPanel, BorderLayout.SOUTH);
ConferenceHandler handler = new ConferenceHandler(this);
regPanel.regTypeComboBox.addItemListener(handler);
regPanel.regNameTextBox.addFocusListener(handler);
//****************************************************************
//The line below is what causes the error. Without it the code
//Works, with it it doesn't and i get the aforementioned error.
//regPanel.keynoteCheckBox.addItemListener(handler);
}
private void buildButtonPanel()
{
buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
calculateButton = new JButton("Calculate Charges");
buttonPanel.add(calculateButton);
clearButton = new JButton("Clear");
buttonPanel.add(clearButton);
resultArea = new JTextArea(5,30);
textScroll = new JScrollPane(resultArea);
buttonPanel.add(textScroll);
ConferenceHandler handler = new ConferenceHandler(this);
calculateButton.addActionListener(handler);
clearButton.addActionListener(handler);
}
}
ConferenceHandler class( this class is unfinished until i get that error straightened out) :
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class ConferenceHandler implements ActionListener, ItemListener, FocusListener
{
protected ConferenceGUI gui;
public ConferenceHandler(ConferenceGUI gui)
{
this.gui = gui;
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == gui.calculateButton)
{
String regType = gui.regPanel.getRegType();
Object[] workshopList = gui.workshopPanel.getWorkshopList();
String workshopString;
if (regType == "Please select a type")
{
JOptionPane.showMessageDialog(null,"Please select a registration type","Type Error",JOptionPane.ERROR_MESSAGE );
}
else
{
if(gui.regPanel.keynoteCheckBox.isSelected())
{
gui.resultArea.append("Keynote address will be attended/n");
}
else
{
gui.resultArea.append("Keynot address will not be attended/n");
}
}
}
if (e.getSource() == gui.clearButton)
{
gui.resultArea.append("CLEAR");
}
}
private double getTotalCharges()
{
double charges = 0;
return charges;
}
public void itemStateChanged(ItemEvent e)
{
}
public void focusLost(FocusEvent e)
{
}
public void focusGained(FocusEvent e)
{
}
}
ConferenceClient Class:
import java.awt.*; import java.awt.event.*; import javax.swing.*;
public class ConferenceClient extends JApplet
{
private final int WINDOW_HEIGHT = 700, WINDOW_WIDTH = 250;
private ConferenceGUI gui;
private Container c;
public ConferenceClient()
{
gui = new ConferenceGUI();
c = getContentPane();
c.setLayout(new BorderLayout());
c.add(gui, BorderLayout.CENTER);
setSize(WINDOW_HEIGHT, WINDOW_WIDTH);
}
}
You're shadowing your keynoteCheckBox variable. First you create a instance field in RegPanel, but in the constructor, you redeclare it...
public class RegPanel extends JPanel {
protected JCheckBox keynoteCheckBox;
//...
public RegPanel() {
//...
//initiate the checkbox and add it to the keynote panel
JCheckBox keynoteCheckBox = new JCheckBox("Dinner and Keynote Speach");
keynotePanel.add(keynoteCheckBox);
This leaves the instance field as null which will cause a NullPointerException
Also, this: regType == "Please select a type" is not how to compare Strings in Java, you want to use something more like "Please select a type".equals(regType)

How to set Combobox value to one of the choices in the list

I need to change the value of the current JComboBox value.
I got this in my Settings gui class used by Main.class:
package com.tominocz.cookieclicker;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
#SuppressWarnings({ "serial", "rawtypes", "unchecked" })
public class Settings extends JFrame {
private String[] choiceList = { "Default (Arial)", "Comic Sans MS" };
public class ChoiceComboListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
JComboBox cb = (JComboBox) ev.getSource();
String currentComboSelection = (String) cb.getSelectedItem();
if (currentComboSelection.equals(choiceList[0])) {
Main.SelectedFont = "Arial";
Main.refreshGame();
Main.opt.setSize(240, 105);
Save.saveGame(Main.save);
}
if (currentComboSelection.equals(choiceList[1])) {
Main.SelectedFont = "Comic Sans MS";
Main.refreshGame();
Main.opt.setSize(240, 107);
Save.saveGame(Main.save);
}
}
}
public Settings() {
super("Settings");
setLayout(new FlowLayout());
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) (((screen.getWidth()) - this.getWidth()) / 2 - 200);
int y = (int) (((screen.getHeight()) - this.getHeight()) / 2 - 100);
this.setLocation(x, y);
this.setAlwaysOnTop(true);
this.setIconImage(((ImageIcon) Main.SettingsIcon).getImage());
JPanel northPanel = new JPanel();
northPanel.setIgnoreRepaint(true);
northPanel.setBorder(new LineBorder(Color.GRAY));
this.getContentPane().add(northPanel, BorderLayout.NORTH);
JComboBox choiceCombo = new JComboBox(choiceList);
northPanel.add(Main.ChooseFont);
northPanel.add(choiceCombo);
choiceCombo.addActionListener(new ChoiceComboListener());
// LOOK HEREEEEEEEEEEEEEEEEEEEEEEE
if (Main.SelectedFont.equals("Comic Sans MS")) {
[the current JComboBox value(may be the default one - choiceList[0])] = choiceList[1];
}
// LOOK HEREEEEEEEEEEEEEEEEEEEEEEE
Main.OK.setBorder(null);
Main.OK.setBorderPainted(false);
Main.OK.setContentAreaFilled(false);
add(Main.OK);
Main.OK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source instanceof JButton) {
Main.opt.dispose();
}
}
});
}
}
Now how do I change the currentComboSelection value if i'm not available to use it in:
public Settings() {
...
?
Suggestions:
You can set the JComboBox's selected item one of two ways: via setSelectedIndex(int index) or setSelectedItem(Object item) where the first way, you choose the index of the desired selection and the 2nd way you choose the object held by the JComboBox (here they are Strings) that is supposed to be selected.
Other issues:
you look to be getting data from the Main class by directly accessing a field, possibly a static field at that. Don't do this as it will make your code tightly coupled, a set up for hard to find bugs, and difficult to enhance or change. Use tightly controlled getter methods instead. i.e., give Main a public Font getSelectedFont() method so that this class can call the method in a non-static way without directly fiddling with Main's fields, without making Main fields static that shouldn't be static.
The same goes for your directly changing Main's state in this Settings class -- that's not how to do Java safely for the same reasons above. Good OOPs principles don't get thrown out the window just because you're creating an event-driven GUI.
It looks like this is supposed to be a secondary window that is displayed from a main GUI window. If so, this should be displayed as a dialog, such as a JDialog or JOptionPane and not a JFrame. This will prevent the display another icon on the OS's toolbar, will guarantee that this window is on top of the main window, and will allow this window to be displayed in a modal fashion if need be.
You're setting the layout of your contentPane to FlowLayout, and yet you are trying to add a JPanel to its BorderLayout.NORTH position. This obviously won't work.
For example, simple code similar to yours that uses a JOptionPane for the secondary dialog window:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class TestSettingsPanel {
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JFrame frame = new JFrame("Test Settings");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MainPanel extends JPanel {
private static final long serialVersionUID = 1L;
public static final String[] CHOICE_LIST = { "Default (Arial)",
"Comic Sans MS", "Courier", "Times New Roman" };
private static final int PREF_W = 500;
private static final int PREF_H = 400;
private JTextField fontField = new JTextField(10);
private SettingsPanel settingsPanel;
public MainPanel() {
fontField.setFocusable(false);
fontField.setText(CHOICE_LIST[0]);
add(new JLabel("Font: "));
add(fontField);
add(new JButton(new SettingsAction("Change Settings")));
}
#Override // let's make this bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class SettingsAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public SettingsAction(String name) {
// give our button / Action some text
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic); // set alt-key combination short-cut
}
#Override
public void actionPerformed(ActionEvent e) {
// create our settingsPanel in a lazy fashion
if (settingsPanel == null) {
settingsPanel = new SettingsPanel();
}
// set the combo selection by calling the setSetting method:
settingsPanel.setSetting(fontField.getText());
// create a JOptionPane and dsiplay the settingsPanle inside of it
Component parentComponent = MainPanel.this;
String title = "Change Font Settings";
int optionType = JOptionPane.OK_CANCEL_OPTION;
int messageType = JOptionPane.PLAIN_MESSAGE;
// display JOptionPane here
int result = JOptionPane.showConfirmDialog(parentComponent,
settingsPanel, title, optionType, messageType);
// find out what button user pressed
if (result == JOptionPane.OK_OPTION) {
// if OK button pressed, extract information from settingsPanel
String fontType = settingsPanel.getFontType();
fontField.setText(fontType);
}
}
}
}
// note that SettingsPanel is completely ignorant about the GUI that displays it.
class SettingsPanel extends JPanel {
private static final long serialVersionUID = 1L;
private JComboBox<String> choiceListCombo = new JComboBox<>(MainPanel.CHOICE_LIST);
public SettingsPanel() {
add(new JLabel("Select Font:"));
add(choiceListCombo);
}
// to allow outside classes to set the combo's selected item
public void setSetting(String text) {
if (text != null && !text.trim().isEmpty()) {
choiceListCombo.setSelectedItem(text);
}
}
// allow outside classes to extract the selected item from combo
public String getFontType() {
return (String) choiceListCombo.getSelectedItem();
}
}
You can get and set the selected Item (Object) of your Combobox by using the methods:
choiceCombo.getSelectedItem();
and
choiceCombo.setSelectedItem(anObject);

JDialog does not appear

The program mostly works correctly, but does not open any window. It should show a little dialog on the bottom right of the desktop. But to another person however, compiling the same code works without problems.We have the same Java Runtime (1.8_u40). How can I fix this?
I have put the code below:
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ProgressDialog {
private JDialog dialogFrame;
private JProgressBar progressBar;
private JLabel headingLabel;
private Uploader callerUploader;
public ProgressDialog() {
dialogFrame = new JDialog();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException ex) {
System.err.println(ex.toString());
}
dialogFrame.setSize(200, 50);
dialogFrame.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.insets = new Insets(5, 5, 5, 5);
headingLabel = new JLabel();
Font f = headingLabel.getFont();
f = new Font(f.getFontName(), Font.BOLD, f.getSize());
headingLabel.setFont(f);
headingLabel.setOpaque(false);
dialogFrame.add(headingLabel, constraints);
dialogFrame.setUndecorated(true);
// Bottone
constraints.gridx = 1;
constraints.gridy = 0;
constraints.weightx = 0;
constraints.weighty = 0;
JButton xButton = new JButton("X");
xButton.setMargin(new Insets(1, 4, 1, 4));
xButton.setFocusable(false);
dialogFrame.add(xButton, constraints);
// Progress bar
constraints.gridx = 0;
constraints.gridy = 1;
constraints.weightx = 1.0;
constraints.weighty = 1.0;
constraints.gridwidth = 2;
progressBar = new JProgressBar();
progressBar.setMaximum(100);
progressBar.setMinimum(0);
Dimension dim = new Dimension();
dim.width = 130;
dim.height = 20;
progressBar.setMinimumSize(dim);
progressBar.setStringPainted(true);
progressBar.setBorderPainted(true);
dialogFrame.add(progressBar, constraints);
xButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialogFrame.dispose();
stoppedUploaderClose();
}
});
}
private void autoPosition() {
// Per il posizionamento in basso a destra
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
// altezza taskbar
Insets toolHeight = Toolkit.getDefaultToolkit().getScreenInsets(dialogFrame.getGraphicsConfiguration());
dialogFrame.setLocation(scrSize.width - 5 - dialogFrame.getWidth(), scrSize.height - 5 - toolHeight.bottom
- dialogFrame.getHeight());
}
public void destroy() {
new Thread() {
#Override
public void run() {
try {
Thread.sleep(500);
for (float i = 1.00f; i >= 0; i -= 0.01f) {
dialogFrame.setOpacity(i);
Thread.sleep(15);
}
dialogFrame.dispose();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}.start();
}
public void setUploader(Uploader callerUploader) {
this.callerUploader = callerUploader;
}
public void set(int n) {
progressBar.setValue(n);
progressBar.setString(n + "");
}
public void setMessage(String headingLabel) {
this.headingLabel.setText(headingLabel);
autoPosition();
dialogFrame.setShape(new RoundRectangle2D.Double(1, 1, 200, 50, 20, 20));
dialogFrame.setVisible(true);
}
public void setWait() {
headingLabel.setText("Waiting link...");
}
public void close() {
dialogFrame.dispose();
}
public void stoppedUploaderClose() {
try {
callerUploader.stopUpload();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You're making Swing calls that change the state of the Swing components of GUI from within a background thread, and this can and will lead to unpredictable errors. Better to use a Swing Timer rather than Thread.sleep(...) since all code within the Timer's ActionListener is called on the Swing event thread.
Also, I have to wonder
Just what the Uploader class does,... Likely it creates long running code, which begs the question, is it being called appropriately within a background thread? This looks like a good spot for a SwingWorker.
How is this dialog code being called?
For more direct help, consider creating and posting an sscce or a minimal example program/mcve where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
Edit: OK, I normally don't do this, but I looked at your code in your GitHub project link, and as I suspected, Uploader does long-running code on the Swing event thread, and makes calls to this class you've posted above. I suggest that you use a SwingWorker for long-running code, that you use its setProgress(...) method to change its progress state from 0 to 100, and that you use a PropertyChangeListener to listen for changes to this state, and then set the JProgressBar's value based on this. It will take a lot of work on your part, but will be well worth it. For the details, look at: Lesson: Concurrency in Swing
I have some example SwingWorker programs that you can find here:
Cant get JProgressBar to update from SwingWorker class
MVC Progress Bar Threading
How do I make my SwingWorker example work properly?
JProgressBar without JButton and PropertyChangeListener
Understanding Java ExecutorService

How would I go about preforming actoins after "Next" button is clicked with a Jbutton setup like this?

I found this nice two button interface using javax.swing which I use for my program which will ask a series of questions. I got the question box all set-up but I need to make it go to a second interface after this one.
So I want the next button to preform a piece of code when pressed. Here is my code:
package test;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class SwingJPanelDemo extends JFrame {
String letter = "apple";
private JLabel LetterTest = new JLabel(Main.text);
private JButton NextButton = new JButton("Next");
private JButton NoButton = new JButton("No");
public SwingJPanelDemo() {
super("Is This Your Letter?");
// create a new panel with GridBagLayout manager
JPanel newPanel = new JPanel(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(10, 10, 10, 10);
// add components to the panel
constraints.gridx = 0;
constraints.gridy = 0;
newPanel.add(LetterTest, constraints);
constraints.gridx = 0;
constraints.gridy = 1;
constraints.gridwidth = 1;
constraints.anchor = GridBagConstraints.CENTER;
newPanel.add(NextButton, constraints);
constraints.gridx = 0;
constraints.gridy = 3;
constraints.gridwidth = 1;
constraints.anchor = GridBagConstraints.CENTER;
newPanel.add(NoButton, constraints);
// set border for the panel
newPanel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), "Is This Your Letter?"));
// add the panel to this frame
add(newPanel);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) {
// set look and feel to the system look and feel
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new SwingJPanelDemo().setVisible(true);
}
});
}
}
How would I go about preforming actions after a button is pressed when using this kind of setup for an interface?
BTW: if there are any things you think are mistaken o that could be done better help is always appreciated but not requested
You need to add an ActionListener to your nextButton. There are at least two common patterns
With an anonymous class
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Your code to do something here
}
});
With a custom ActionListener class:
class MyNextButtonActions implements ActionListener
{
// lots of rich method etc that code the meaning of life
public void actionPerformed(ActionEvent e)
{
//code to trigger on click, using all your lovely methods
}
}
which you then add to your button where you create the GUI i.e.
nextButton.addActionListener(new MyNextButtonActions());
A decent tutorial on all this is available for the Swing framework here. You can get very creative - for instance you could make your SwingJPanelDemo class implement ActionListener and add it as an ActionListener for all its components.
Make sure to import java.awt.event.*;, then you add an actionlistener to you're jbutton by doing
NextButton.addActionListener(new MyFirstActionListener());
Next we have to make the MyFirstActionListener() class. So anywhere inside your class is good.. perhaps in between the main method and your constructor, make it like so: and make sure it implements the ActionListener interface. The ActionListener interface only demands 1 method; the actionPerformed method, which takes an ActionEvent object as a parameter.
private class MyFirstActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String whatIsWrittenOnTheButton = e.getActionCommand();
if(whatIsWrittenOnTheButton.equals("Next")) {
System.out.println("You pressed the \'Next\' JButton.");
}
if(e.getSource() == NextButton) {
System.out.println("Here is a 2nd message upon pressing next");
}
}
}
e.getActionCommand() will return a string that represents what was written on the pressed button, and e.getSource() will return an object. This is particularly handy if you use the same actionlistener for multiple different buttons; it's a means to distinguish between them.

Accessing an instance of JTextArea from another class in an array loop. What's the best way?

I'm having problems conceptually getting my head around how to make my application work.
I have 15 JTextField components and 15 JButton components and 1 JTextArea. I want each button to insert the text inside the textarea from each corresponding textfield.
If you wish to see a graphic to explain this setup - [http://i.imgur.com/Vnc3C.png]here1
I've managed to get frame.finaltext to the Curriculum subject class, but it is not seen inside the actionPerformed method.
What is the best way of getting a hold of frame.finaltext.append(textfields[i])
TIA
Adam
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import net.miginfocom.swing.MigLayout;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Dimension;
public class CurriculumSubject extends JPanel implements ActionListener{
/**
* This is an class that will hold details for each subject.
*/
// First we want some variables
String subjectName;
public CurriculumSubject (final JReport frame){
MigLayout layout = new MigLayout("wrap 2");//, debug 4000");
this.setLayout(layout);
final JTextField [] textfields = new JTextField[15];
JButton [] buttons = new JButton[15];
for (int i=0;i<15;i++){
String content = "This is a test. " + i;
textfields[i] = new JTextField(content);
this.add(textfields[i], "width 500:700:1000");
buttons[i] = new JButton(">>>");
buttons[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
//Execute when button is pressed
String text = textfields[i].getText();
frame.finaltext.append(text);
}});
buttons[i].setPreferredSize(new Dimension(10,10));
this.add(buttons[i]);
}
}
}
Ok, I think I understood what you wanted. You should define your JTextArea as class variable, so you have one instance of it in one form object, and then you just append text to that object. Example with method:
public class CurriculumSubject extends JPanel implements ActionListener {
private JTextArea mainArea = new JTextArea();
public CurriculumSubject(final JReport frame) {
MigLayout layout = new MigLayout("wrap 2");//, debug 4000");
this.setLayout(layout);
final JTextField[] textfields = new JTextField[15];
JButton[] buttons = new JButton[15];
for (int i = 0; i < 15; i++) {
String content = "This is a test. " + i;
textfields[i] = new JTextField(content);
this.add(textfields[i], "width 500:700:1000");
buttons[i] = new JButton(">>>");
buttons[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Execute when button is pressed
String text = textfields[i].getText();
addTextToFinalArea(text);
}
});
buttons[i].setPreferredSize(new Dimension(10, 10));
this.add(buttons[i]);
}
}
public void addTextToFinalArea(String text) {
mainArea.append(text);
}
}
I have no idea what JReport is, but why don't you provide a method in it to accept a string (or make a sub class of JReport that provides this method):
class ReportThingy extends JReport {
public void addText(String text) {
finaltext.append(text);
}
}
UPDATE:
You seem to have many widgets to keep track of. I would recommend introducing a Model-View-Controller pattern to make your application more manageable. In the short term, you can try making the finaltext widget available to the CurriculumSubject class through a setter or as a constructor argument.
I'm wondering that the compiler isn't complaining about your code: You are using a non-final local variable i within your anonymous inner ActionListener implementation. Try storing i in a final variable and use that one in the inner class:
for (int i = 0; i < 15; i++) {
...
final int index = i;
buttons[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
//Execute when button is pressed
String text = textfields[index].getText();
frame.finaltext.append(text + "\n");
}});
...
}

Categories

Resources