Swing Component communication - java

i am building an algorithm simulation tool and I am struggling to get my mainframe class which instantiates and adds all the subcomponents to the JFrame to get the file system location of where the pseudocode is located (for the psuedocode panel.)
I have made every single algorithm have a string which details where the relevant text file information for each algorithm is.
I have a method which then takes the string when the algorithm is passed in and stores it into a string variable.
This string variable is then passed to the panel.
Unfortunately this is throwing a null pointer and I have been trying to debug this and can't get far.
public class SortAnimator extends JFrame
{
private static final int VALUES_LENGTH = 30;
private static final int FRAME_WIDTH = 1200;
private static final int FRAME_HEIGHT = 700;
private PsuedocodePanel pseudoPanel;
private Menu menu;
private InformationPanel infoPanel;
private String algoName;
public String algoLocation;
public SortAnimator(Sorter s) throws IOException
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu=new Menu();
pseudoPanel=new PsuedocodePanel();
ArrayComponent panel = new ArrayComponent();
infoPanel= new InformationPanel();
add(menu,BorderLayout.NORTH);
add(panel, BorderLayout.CENTER);
add(pseudoPanel,BorderLayout.WEST);
add(infoPanel,BorderLayout.SOUTH);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setVisible(true);
int[] values = new int[VALUES_LENGTH];
for (int i = 0; i < values.length; i++)
values[i] = (int) (Math.random() * panel.getHeight());
s.setValues(values);
s.setPanel(panel);
Thread t = new Thread(s);
t.start();
algoName=s.getAlgorithmName();
algoLocation =s.getAlgorithmLocation();
System.out.println(algoLocation);
pseudoPanel.passFileLocation(algoLocation);
}
}
public class PsuedocodePanel extends JPanel{
private JTextArea txtArea;
private String textFile;
private String fileLocation;
public PsuedocodePanel() throws FileNotFoundException, IOException{
setLayout(new BorderLayout());
txtArea=new JTextArea();
txtArea.setEditable(false);
add(txtArea,BorderLayout.CENTER);
FileReader fr = new FileReader(this.fileLocation);
BufferedReader reader=new BufferedReader(fr);
txtArea.read(reader,null);
Dimension dim=getPreferredSize();//returns object
System.out.println(getPreferredSize());
dim.width=300;
dim.height=75;
setPreferredSize(dim);
Border innerBorder=BorderFactory.createTitledBorder("Algorithm Psuedocode");
Border outerBorder=BorderFactory.createEmptyBorder(5,5,5,5);
setBorder(BorderFactory.createCompoundBorder(outerBorder,innerBorder));
}
public void passFileLocation(String algoLocation) {
this.fileLocation= algoLocation;
}

Your PsuedocodePanel class creates a FileReader in its constructor, using this.fileLocation, but fileLocation will be null at that point in the code - see simplified code fragment below:
public class PsuedocodePanel extends JPanel{
private String fileLocation; // not initialised
// constructor does not accept a fileLocation...
public PsuedocodePanel() throws FileNotFoundException, IOException{
// ... so this.fileLocation is null here:
FileReader fr = new FileReader(this.fileLocation);

Related

Intellij: What causes a dark green inspection highlight?

After searching forums and stackoverflow I can't see to figure out what this inspection highlight is trying to alert me to:
Selecting/hovering over the highlighted text returns nothing besides the standard context actions.
Originally these variables were declared and instantiated before the constructor. (ACTIONS TAKEN TO REPRODUCE) When I used the context action "Move initialization to constructor", the initializations in the constructor are highlighted dark green. See attached img.
Anyone know what's going on here?
example:
public class HoaQueueEditorDialog extends ListDialogBase implements Mutable {
private static final String SAVE = "Save";
private static final String CANCEL = "Cancel";
private static final String CHAR_DELIMITER = ",";
private static final String[] COL_NAMES = {"Workflow Step Name"};
private static final Color NORM_BACKGROUND = TRexUIManager.getColor(TRexUIManager.CONTENT_BACKGROUND);
private static final Color NORM_FOREGROUND = Color.black;
private static final int[] COL_WIDTHS = {325};
private static final ArrayList<AppOptionsUtil.WorkflowStepInfo> SUPPORTED_STEPS_LIST = AppOptionsUtil.getDisplayHoaInfoWfStepsSupportedList();
// UI Elements
private TButton saveButton;
private TButton cancelButton;
private JPanel parentPanel;
private JPanel buttonPanelRight;
private JPanel buttonPanelLeft;
// Stores the data necessary to build a table row and it's corresponding checkbox object.
protected HashMap<AppOptionsUtil.WorkflowStepInfo, TCheckBox> checkBoxMap;
private TTable wfQueuesTable;
private DefaultTableModel tableModel;
private TChangeListener changeListener = null;
private boolean escKeyPressedInsideYesNoCancel = false;
private String originalAppOptionValues = null;
private String returnAppOptionValues = null;
public HoaQueueEditorDialog() {
try {
this.tableModel = new DefaultTableModel(new Object[][]{{}}, COL_NAMES);
this.wfQueuesTable = new TTable();
wfQueuesTable.setModel(tableModel);
wfQueuesTable.setBackground(NORM_BACKGROUND);
wfQueuesTable.setRowHeight(42);
wfQueuesTable.getSelectionModel().addListSelectionListener(new DocumentTableSelectionListener());
init();
initMVC();
this.setResizable(true);
} catch (Exception ex) {
TRexToolkit.showErrorMessage("Error initializing Document Print Screen.", "Error", ex);
}
buttonPanelLeft = new JPanel(new FlowLayout(LEFT));
buttonPanelRight = new JPanel(new FlowLayout(RIGHT));
parentPanel = new JPanel();
}
IntelliJ IDEA is highlighting the changes it made when you invoked the Move initialization to constructor intention. Because the changes are quite far away from the cursor, you might not see them otherwise. Pressing Escape will remove the highlighting.

Why will my program not play the next song in the array?

I have been working on this code for a really long time and i just can't seem to figure out my problem. i want to be able to play a list of songs one right after another and i thought i would be able to do that with a simple recursive method that delays the average length of a song, and have it call the next song and play it... However it only plays the very first song and then stops after that and nothing else happens... I have asked countless people to look at this and nobody can help me out.. And no this is not a school project, it is a music player that my mother would like me to use at a party in the next upcoming weekend, so this is like my last ditch effort... Any help with this would be greatly appreciated!!!
private JLabel messageLabel;
private JButton playlist;
private JPanel panel;
BufferedImage image;
AudioStream audioStream1, audioStream2, audioStream3;
//Object[] music = new Object[3];
private final int WINDOW_WIDTH = 800;
private final int WINDOW_HEIGHT = 525;
// File destinationss
private String s1 = "C:\\Users\\Tony\\Desktop\\Java\\NetBeansProjects\\Gui Stuff\\src\\No_Pressure.wav";
private String s2 = "C:\\Users\\Tony\\Desktop\\Java\\NetBeansProjects\\Gui Stuff\\src\\Grateful_Dead_-_Touch_of_Grey.wav";
private String s3 = "C:\\Users\\Tony\\Desktop\\Java\\NetBeansProjects\\Gui Stuff\\src\\Stairway_to_Heaven_Led_Zeppelin_Lyrics.wav";
InputStream in1 = new FileInputStream(s1);
InputStream in2 = new FileInputStream(s2);
InputStream in3 = new FileInputStream(s3);
private ArrayList music;
public JukeBoxWithArrays() throws IOException {
music = new ArrayList();
audioStream1 = new AudioStream(in1);
audioStream2 = new AudioStream(in2);
audioStream3 = new AudioStream(in3);
music.add(audioStream1);
music.add(audioStream2);
music.add(audioStream3);
setTitle("Juke Box Playlist");
setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
messageLabel = new JLabel("Click the Button to play the playlist");
// Create the Playlist button
playlist = new JButton("Playlist number 1");
// Register the event Listener
playlist.addActionListener(new PlaylistListener());
// Create the panel
panel = new JPanel();
image = ImageIO.read(new File("C:\\Users\\Tony\\Desktop\\Java\\NetBeansProjects\\Gui Stuff\\src\\jukebox2.jpg"));
panel.add(messageLabel);
panel.add(playlist);
panel.add((new JLabel(new ImageIcon(image))));
// Add the panel to the Content Pane
add(panel);
// Display the Window
setVisible(true);
}
private class PlaylistListener implements ActionListener {
int x = 0;
public void actionPerformed(ActionEvent e) {
try {
playMusic(x);
} catch (InterruptedException ex) {
Logger.getLogger(JukeBoxWithArrays.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void playMusic(int x) throws InterruptedException {
if (x > music.size()) {
AudioPlayer.player.stop((InputStream) music.get(x));
} else {
AudioPlayer.player.start((InputStream) music.get(x));
}
Thread.sleep(5 * 60 * 1000); // I believe this is where I am running into my problem
playMusic(x++);
}
}
#SuppressWarnings("restriction")
public static void main(String[] args) throws Exception {
JukeBoxWithArrays jbwa = new JukeBoxWithArrays();
jbwa.pack();
}
}
It seems your code is failing for the same reason this:
private static int x = 0;
public static void main(String[] args) throws ParseException {
int x = 0;
doSomething(x);
doSomething(x);
doSomething(x);
doSomething(x);
doSomething(x);
}
private static void doSomething(int x) {
System.out.println(x++);
}
Outputs this:
0
0
0
0
0
Your Listener has an x field, that your are passing by value between the methods. You should remove the x argument on playMusic(), so everytime it increments x, it would use the object field instead.

Java JTextField information access from another class

I am using a gui with JTextFields to collect some information and then a JButton that takes that infomration and writes it to a file, sets the gui visibility to false, and then uses Runnable to create an instance of another JFrame from a different class to display a slideshow.
I would like to access some of the information for the JTextFields from the new JFrame slideshow. I have tried creating an object of the previous class with accessor methods, but the values keep coming back null (I know that I have done this correctly).
I'm worried that when the accessor methods go to check what the variables equal the JTextFields appear null to the new JFrame.
Below is the sscce that shows this problem.
package accessmain;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class AccessMain extends JFrame implements ActionListener
{
private static final int FRAMEWIDTH = 800;
private static final int FRAMEHEIGHT = 300;
private JPanel mainPanel;
private PrintWriter outputStream = null;
private JTextField subjectNumberText;
private String subjectNumberString;
public static void main(String[] args)
{
AccessMain gui = new AccessMain();
gui.setVisible(true);
}
public AccessMain()
{
super("Self Paced Slideshow");
setSize(FRAMEWIDTH, FRAMEHEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
//Begin Main Content Panel
mainPanel = new JPanel();
mainPanel.setBorder(new EmptyBorder(0,10,0,10));
mainPanel.setLayout(new GridLayout(7, 2));
mainPanel.setBackground(Color.WHITE);
add(mainPanel, BorderLayout.CENTER);
mainPanel.add(new JLabel("Subject Number: "));
subjectNumberText = new JTextField(30);
mainPanel.add(subjectNumberText);
mainPanel.add(new JLabel(""));
JButton launch = new JButton("Begin Slideshow");
launch.addActionListener(this);
mainPanel.add(launch);
//End Main Content Panel
}
#Override
public void actionPerformed(ActionEvent e)
{
String actionCommand = e.getActionCommand();
if(actionCommand.equals("Begin Slideshow"))
{
subjectNumberString = subjectNumberText.getText();
if(!(subjectNumberString.equals("")))
{
System.out.println(getSubjectNumber());
this.setVisible(false);
writeFile();
outputStream.println("Subject Number:\t" + subjectNumberString);
outputStream.close();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
AccessClass testClass = new AccessClass();
testClass.setVisible(true);
}
});
}
else
{
//Add warning dialogue here later
}
}
}
private void writeFile()
{
try
{
outputStream = new PrintWriter(new FileOutputStream(subjectNumberString + ".txt", false));
}
catch(FileNotFoundException e)
{
System.out.println("Cannot find file " + subjectNumberString + ".txt or it could not be opened.");
System.exit(0);
}
}
public String getSubjectNumber()
{
return subjectNumberString;
}
}
And then creating a barebones class to show the loss of data:
package accessmain;
import javax.swing.*;
import java.awt.*;
public class AccessClass extends JFrame
{
AccessMain experiment = new AccessMain();
String subjectNumber = experiment.getSubjectNumber();
public AccessClass()
{
System.out.println(subjectNumber);
}
}
Hardcoding the accessor method with "test" like this:
public String getSubjectNumber()
{
return "test";
}
Running this method as below in the new JFrame:
SelfPaceMain experiment = new SelfPaceMain();
private String subjectNumber = experiment.getSubjectNumber();
System.out.println(subjectNumber);
Does cause the system to print "test". So the accessor methods seem to be working. However, trying to access the values from the JTextFields doesn't seem to work.
I would read the information from the file I create, but without being able to pass the subjectNumber (which is used as the name of the file), I can't tell the new class what file to open.
Is there a good way to pass data from JTextFields to other classes?
pass the argument 'AccessMain' or 'JTextField' to the second class:
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
AccessClass testClass = new AccessClass(AccessMain.this); //fixed this
testClass.setVisible(true);
}
});
Then reading the value of 'subjectNumber'(JTextField value) from the 'AccessMain' or 'JTextField' in the second class:
public class AccessClass extends JFrame
{
final AccessMain experiment;
public AccessClass(AccessMain experiment)
{
this.experiment = experiment;
}
public String getSubjectNumber(){
return experiment.getSubjectNumber();
}
}
Also, you should try Observer pattern.
A simple demo of Observalbe and Observer
Observable and Observer Objects

return an ArrayList to swing with logger interface

I'm using the code in this answer to provide logging functionality, and it works well! Thanks gustafc.
Sending messages to a swing JTextArea from different places
I want to use this approach and add the function: writeEntry(String, String) to write to an ArrayList that I can hopefully access from swing; i.e, click 'show' and have it write this list of word pairs to a JText element.
so adding a bit to gustafc's code.
the interface:
package com.example.logging;
public interface SimpleActivityLogger {
void logAction(String message);
void writeEntry(String s1); //*** I added this ***
}
passing it to another class as per gustafc's example:
public class SimpleComponentLogger implements SimpleActivityLogger{
private JTextComponent target;
private ArrayList data;
public SimpleComponentLogger(JTextComponent target, ArrayList data){
this.target = target;
this.data = data;
}
public void logAction(final String message){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
target.setText(String.format("%s%s%n", new Object[]{target.getText(), message}));
}
});
}
public void writeEntry(String s1){
data.add(s1);
System.out.println("data array length: " + data.size());
}
}
and then making an implementation:
// this originally extended NotesThread,
// but I assume you won't have that on your system
public class LookupIterator3 extends Thread {
private SimpleActivityLogger logger;
// Constructor that passes logger instance
public LookupIterator3(SimpleActivityLogger logger){
this.logger = logger;
}
public void doLookup(){
this.start();
}
public void run() {
String[] words = {"the", "quick", "smart", "fox", "jumps", "over", "the", "lazy", "dog"};
for(int i=0; i<words.length; i++){
synchronized(words){
try{
logger.logAction(words[i]);
words.wait(500);
}
catch(InterruptedException ie){ie.printStackTrace();}
}
logger.writeEntry(words[i]);
}
}
}
however, when I try to access the ArrayList from swing, it comes back size()=0.
Here's a big chunk of swing, but you should be able to just copy and paste it:
public class MySwingTest extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField filename = new JTextField();
private JTextField dir = new JTextField();
private JTextPane output, answersPane;
private JScrollPane scroller;
private SimpleComponentLogger logger;
private ArrayList answer;
public MySwingTest() {
JMenu fileMenu;
JMenuBar menuBar;
JMenuItem menuOpen, menuExit;
JButton answerButton = new JButton("show answers");
answerButton.addActionListener(new MyListener());
menuBar = new JMenuBar();
fileMenu = new JMenu("File");
menuBar.add(fileMenu);
menuOpen = new JMenuItem("open file");
menuExit = new JMenuItem("exit");
answer = new ArrayList();
output = new JTextPane();
logger = new SimpleComponentLogger(output, answer);
scroller = new JScrollPane(output, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
output.setEditable(false);
answer = new ArrayList();
answersPane = new JTextPane();
answersPane.setSize(100, 200);
answersPane.setEditable(false);
fileMenu.add(menuOpen);
fileMenu.add(menuExit);
menuOpen.addActionListener(new MyListener());
menuExit.addActionListener(new MyListener());
JPanel p = new JPanel();
p.setLayout(new GridLayout(2, 1));
p.add(filename);
p.add(dir);
Container cp = getContentPane();
cp.add(menuBar,BorderLayout.NORTH);
cp.add(p);
cp.add(scroller, BorderLayout.CENTER);
cp.add(answersPane, BorderLayout.WEST);
cp.add(answerButton, BorderLayout.SOUTH);
dir.setEditable(false);
filename.setEditable(false);
}
// Inner class listener
class MyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String eventCommand = e.getActionCommand();
if(eventCommand.equals("exit")){
System.exit(0);
}
if(eventCommand.equals("show answers")){
String entry = (String)answer.get(0);
answersPane.setText(entry);
}
else {
LookupIterator3 lu3 = new LookupIterator3(logger);
lu3.doLookup();
}
}
}
public static void main(String[] args) {
run(new MySwingTest(), 450, 600);
}
public static void run(JFrame frame, int width, int height) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width, height);
frame.setVisible(true);
}
}
Sorry about the long question, but this is doing my head in!
Any suggestions?
(I know I'm going to get ragged for writing a long qn, but I don't know what I could have left out)
OK. long edit complete.
Open that baby up and select "open file" from the menu. It will run without a filechooser.
The problem is actually quite simple: in your MySwingTest constructor you have twice the line :
answer = new ArrayList();
once before you create your logger and once after. Simply drop the second call and it should work fine.
Note: it is really a bad practice to share ArrayList between your instances (responsability is spread over several classes). It would be a lot simpler if you only had your logger creating directly its own ArrayList and providing access to it with a getter. Even better, it could directly offer an access to the objects it contains (preventing the possibility for other instances to modify the content of the ArrayList).
Note 2: consider using interface-declaration over class-declaration: use List instead of ArrayList in order to reduce coupling.
Note 3: I would strongly encourage you tu type your collections: List<String> answer = new ArrayList<String>();

Autocompletion stops after entering one word using JSuggestField - SSCCE attached

I added to my project the element of autocompletion; but after the user has entered one
word, the autocompletion algorithm stops. I can add more characters, however without
the autocompltion's suggestions.
I'm using JSuggestField (added the jar to my project) , here is SSCCE that illustrates the problem :
import javax.swing.*;
import ch.rakudave.suggest.JSuggestField;
import java.awt.*;
import java.util.Vector;
public class Classic extends JFrame {
public static final String CHILD = "/child::";
public static final String DESCENDANT = "/descendant::";
public static final String FOLLOWING_SIBLING = "/following-sibling::";
public static final String DESCENDANT_OR_SELF = "/descendant-or-self::";
public static final String SELF = "/self::";
public static final String PRECEDING_SIBLING = "/preceding-sibling::";
public static final String ANCESTOR_OR_SELF = "/ancestor-or-self::";
public static final String ANCESTOR = "/ancestor::";
public static final String FOLLOWING = "/following::";
public static final String PRECEDING = "/preceding::";
public Classic() {
initComponents();
}
private void initComponents() {
Vector<String> vector = new Vector<String>();
vector.add(DESCENDANT);
vector.add(FOLLOWING_SIBLING);
vector.add(DESCENDANT_OR_SELF);
vector.add(SELF);
vector.add(PRECEDING_SIBLING);
vector.add(ANCESTOR_OR_SELF);
vector.add(ANCESTOR);
vector.add(FOLLOWING);
vector.add(PRECEDING);
JSuggestField jsuggest= new JSuggestField(this,vector );
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(200, 200);
Container container = getContentPane();
container.setLayout(new FlowLayout(FlowLayout.LEFT));
JTextField textField = new JTextField(15);
jsuggest.setPreferredSize(new Dimension(100, 20));
//
// Right justify the JTextField contents
//
jsuggest.setHorizontalAlignment(JTextField.RIGHT);
container.add(jsuggest);
textField = jsuggest;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Classic().setVisible(true);
}
});
}
}
Here is a snapshot : .
This is nice , but I want that the autocompletion would work after each time the user has entered the character /, hence one autocompletion is not enough.
Any idea how can I solve this using JSuggestField or something else?
Thanks.

Categories