I am learning java (just finished reading of Head First Java book) and I've started to write app (for mine and learning purposes), which would read log file and changed fond of the line according to defined rules/filters.
I have some prototype, but now I am stuck with design ... coding is not a big deal but I still have problem to think in OOP and to create good design.
What I currently have are 3 classes.
public class App {
//... contains main method, frame, button for file load, etc...
}
public class FileTail {
//... open/read file, and create thread where file is checked for
//changes and in case that file is changed, reads new lines
}
public class logText extends JTextPane {
//... where the text -> file output appears
}
What I would like to do next, is to have other components on the frame, where I would say e.g.:
filter out all lines which contains "INFO"
lines which contains string "ERROR" will be red
etc...
I cannot come up with design, like should I add this functionality to logText class? I know, that this is small app and probably everything could be in one class, but as one of the reasons is learning purpose, I would like to do it right.
I was thinking about create new class patern, which would contain searched string, Font and Color. Then in main class I would create ArrayList<Patern> and each before each new line is to be added to JTextPane, I would somehow search through ArrayList<Patern> for match.
I suggest you create a method that takes an argument of what ever you want to search for, and compares against a set of records, listing the records that records in some sort of list and returns the list.
good luck
Related
I am working on a school coding project, which involves using the JFugue library in Java. However, I am having significant difficulty saving loaded and edited patterns to a file. So far, I have tried both the player.saveMidi (which is not recognized) and MidiFileManager.savePatternToMidi functions, but the edits do not save.
Here is a snippet of the aforementioned code:
Pattern pattern = new Pattern(MidiFileManager.loadPatternFromMidi(new File(filePath.getText())));
TextField midiData = new TextField(pattern.toString());
midiData.setFont(Font.font(14));
pattern = new Pattern(midiData.getText());
Button save = new Button("Save Edits");
Pattern finalPattern = pattern;
save.setOnAction(e -> {
try {
MidiFileManager.savePatternToMidi(finalPattern, new File(filePath.getText()));
Load.playAndEdit(filePath);
} catch (Exception ex) {
ex.printStackTrace();
}
});
Any help would certainly be appreciated!
Although your suspicion is that this is an issue with JFugue, the underlying issue is in the JavaFX pieces of the code.
The main issue is that the way the code is written, it looks like the expectation is that the TextField will be displayed, the user will make a change, and the code will remember that change in "pattern = new Pattern(midiData.getText())". That's not how the JavaFX TextField works. UI elements are not sequential like this; instead, they work with actions (or in JavaFX, you can "bind" the value of a UI component with a data element). If you get the text from the TextField in the action that triggers when the user presses the Save button, you will have the most recent data from the text field. As the code is written, the user's change is never placed into a variable.
Two other notes:
In your first line, MidiFileManager.loadPatternFromMidi returns a Pattern, so you don't need to put it into a "new Pattern()".
There is no need to say "Pattern finalPattern = pattern". That just creates a new variable that points to the same data as the existing variable. You can just save "pattern", if it has the information you expect from the text field (but again, this isn't the right place to say it, so it won't have the information that you're expecting).
One way to test that this is not a JFugue issue is to create a simple program that does, for example:
Pattern pattern = MidiFileManager.loadPatternFromMidi(new File(filePath.getText()));
pattern.add(" C D E");
MidiFileManager.savePatternToMidi(pattern, new File(filePath.getText()));
Then you would see that the resulting pattern has three new notes added to the end.
I've read through a dozen or so actionlistener/loop related questions here, but I'm not sure I've found my answer. I started on my first large Java project, a text RPG that's spiraled into around 5K lines of logic and game features which was functioning as intended using just the console - when I decided I'd try to build a Java swing GUI for it instead. Here's my problem:
I use a Room object which handles the description of where the player is at and also has an array of options for the player to choose next which it creates dynamically based on what cell the room's id is in on a csv file and what is beside it. I stopped outputting this to the console and instead started creating JButtons based on the options array like so:
public void showNarrate(){
add(dd,gridConstraints);
optionCopy.clear();
int i = 0;
for(JButton j : optionButtons){
//adding and formatting buttons to gridBagConstraint I also set actionCommand for each button to the triggerValue (ID of the next room which the button should take the player to)
}
//I tried using a copy of my JButton array here so I could have something to iterate over in actionListener after clearing out the original
//(Since it needs to be cleared so the next Room's buttons can be built after the player chooses an option)
for(JButton j : optionButtons){
optionCopy.add(j);
}
optionButtons.clear();
//dd is a seperate drawingComponent I used for outputting room descriptions which may be totally unnecessary at this point :/
dd.repaint();
setVisible(true);
}
Over in actionlistener (Same class) this is how I tried to swing it:
for(JButton j : optionCopy){
if(e.getActionCommand().equals(j.getActionCommand())){
Main.saveRoom = Main.currentRoom;
Main.currentRoom = j.getActionCommand();
System.out.println(Main.currentRoom);
}
}}
Then in my main class I call:
narrator.narrate(currentRoom, saveRoom); which takes care of some other logic concerning locked doors, encounters, etc.
Also in Main loop are some other methods related to autosave and tracking which rooms the player has visited. I know from other q/a i'v read on here that this is all pretty bad design, and I'm sttarting to understand that now, but my issue is this:
The first room of the game loads up fine, when I click a button it outputs to console(Just for testing) the correct trigger value of the room the button should be calling, so I'm getting that far, but how can I call the same method over again now?
-If I call narrate from actionListener it will wind up calling itself again and complain about ConcurrentModification.
-If I try to keep a loop going in my Main class it will keep looping and won't allow for the player to actually choose a button.
I've never used threads before, which I wonder might be the answer,and the closest thing to a related answer I've found is this:
Java: Method wait for ActionListener in another class
but I don't think moving actionListener to Main class would resolve my problem which is actionListener winding up calling itself recursively. And as for the observer-observable pattern... I just can't understand it :(
I appreciate any and all help, I've learned a LOT trying to make this thing work without seeking help as much as possible but this has stumped me.
Your loop in actionPerformed only checks whether a JButton exists in your optionList with the given actionCommand. However this can be done before actually doing something:
boolean contained = false;
for (JButton j : optionButtons)
if (j.getActionCommand().equals(e.getActionCommand()))
contained = true;
if (contained) {
// change room
}
now you can call narrate because you have finished iterating over the collection beforehand and will not get a ConcurrentModificationException
I'm working on my custom ColorChooserPanel class, but I don't know how to create a ColorSwatch.
I found a class named ColorSwatch or something like that but its package private and I can't access it.
How can I ensure that I have a proper color chooser?
First, you need to think about the way this should work, to formulate your goals into action points that you can always check and see whether and how they are fulfilled:
it should be displayed
it should handle click events
it should be able to return a color (the last chosen color, or a default in lack of that)
Now, a very common way of supporting color choosers is to have something like in this image:
However, this is way too complex for a first implementation. You should first have something which "works", that is, you are able to choose colors to taste success and then work out the subsequent details. Unless you say otherwise, I'm assuming that the Basic colors section is good for now. In that case, you can create a class, which contains a JPanel, containing clickable elements. Your class needs to have a Color member, which one can get calling a getter and which is set when a clickable item inside your JPanel is clicked. The clickable items can be JPanels on their own, for example.
If you prefer something ready-made, then kindly read these:
https://docs.oracle.com/javase/tutorial/uiswing/components/colorchooser.html
https://coderanch.com/t/332515/java/Color-Palette
I will do my best to explain-- I am trying to make a choose-your-own-adventure type game while using a TextField and a TextArea, where what is written in the TextField is appended into the TextArea (this I know how to do via ActionListener).
However, I need to have the TextArea start with a pre-written 'intro', which asks the user at the end if they want to continue or not. Therefore, I need it to be able to scan the user's response ('yes' or 'no') and choose the appropriate selection of pre-written text to follow.
I don't want to overwrite what is already in the TextArea, I want to add to it. I suppose what I'm confused about it how I'm supposed to lay out the entire file so that it functions properly, because the different choices for the adventure span different methods. Having
"String text = textField.getText();" only within the actionPerformed method means I can't use 'text' elsewhere, but moving that line up with my other variables tells me it can't reference the field before it's defined.
I am fairly new to Java and am working on this as a project for a non-programming school course. I've been through many iterations thus far and this is what seems to be my final attempt, as I've remade it repeatedly and don't have much time left. :(
Your questions/comments and my attempts to answer:
I am trying to make a choose-your-own-adventure type game while using a TextField and a TextArea, where what is written in the TextField is appended into the TextArea (this I know how to do via ActionListener).
As per my comment, be sure to create a Swing GUI which would use a JTextField and a JTextArea. You would then add your java.awt.event.ActionListener to the JTextArea, and the ActionListener would respond whenever the user pressed <ENTER> within the JTextField.
However, I need to have the TextArea start with a pre-written 'intro', which asks the user at the end if they want to continue or not. Therefore, I need it to be able to scan the user's response ('yes' or 'no') and choose the appropriate selection of pre-written text to follow.
This can be done easily, but sounds as if you may be trying to shoe-horn a linear console type program into a GUI. If so, consider reconsidering your program design since what works best for one often doesn't work well for another. If you do re-write, then you should consider redoing most including your program flow, but excepting perhaps the "model" portion of your previous program, the "business logic" that underlies everything.
I don't want to overwrite what is already in the TextArea, I want to add to it. I suppose what I'm confused about it how I'm supposed to lay out the entire file so that it functions properly, because the different choices for the adventure span different methods. Having "String text = textField.getText();" only within the actionPerformed method means I can't use 'text' elsewhere, but moving that line up with my other variables tells me it can't reference the field before it's defined.
Again as per comments a JTextArea has an append(String text) method that will add new text to existing text that is already displayed in your JText Area. So on that note, your ActionListener's actionPerformed method could be very simple and look something like:
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
textArea.append(text):
}
Although you may need to add line feeds, "\n" either before and/or after the text you are going to append.
I am making a knight's tour implementation in java, and currently I have everything jumbled into one giant mess of code.
I have a class called MainFrame which includes the code to solve the knights tour as well as methods for the menu, etc.
I want to create a new class called KT (for knights tour) which will contain the code for the algorithm, but I'm having lots of issues doing that.
I don't want to post code here because i dont want someone from my class copying or something, so I will just briefly explain.
In class KT, I have declared the variables, arrays, etc. I have methods such as printSolution, move, redo (the backtracking), etc.
However I am unsure how to tie in the code for the buttons (which is declared in MainFrame). For example, I have a loop in the print method that prints the correct solution on the 8x8 board. Right now I'm being asked to create a new method for the button even though I have the button in class MainFrame.
I have a KT k = new KT(); and then I'm launching MainFrame. Is that where I am doing it wrong or is it something really simple that I'm being too dumb to figure out?
tl;dr program works well when i have everything in one class, but i want to make two classes and make everything "look" nice
First of all, give your KnightTour class an actual name. Like, you know, KnightTour. If you were coding this for cash money, the next guy who had to read your code would want to punch the guy who called a class something like KT.
Think about creating this class so that you can use it from a GUI controller like your button and menu laden applet. But so that it can ALSO be used from, say, a character based application where you type commands at a prompt and have your new class evaluate those commands.
The reason I suggest this is because it will force you to create your KnightTour class so that it is PURELY the "business logic" for your app. By that I mean that your KnightTour class should not know anything about buttons, menus, GUIs, text interfaces, or anything like that. You need to think about your KnightTour class in terms of what it must accomplish.
I don't really know what KnightTour does. So I'll just throw out some ideas of what kind of functionality it might need to support. I'm assuming everything takes place on a chess board?
Get the state (occupied, unoccupied) for a given board location (x,y)
Put a chess piece (piece enumerator) on a given location (x,y)
Validate placement of a piece (piece enumerator, location x,y)
Suggest a move, returning a Suggestion object with a piece enumerator and location
Reset the board to start all over.
Now, when you push a button that says "place a piece on 5,5" then you'll handle that event in your GUI controller, and then call the "set piece" method (#2 above) to do that work. If you have a character based application, when you type "put knight at 5,5" then you'll parse that text, and then invoke #2 above. The key point is that both of those user interfaces access the same KnightTour methods to do the same work.
In the actionPerformed method of your MainFrame class just call the appropriate methods to get the solution from KT (which, by the way, I would rename to KnightsTour...readability counts).
Ideally you want all your logic (the model) broken up into sensible methods in KnightsTour, and all your display and button-handling code (the view and controller) in MainFrame. If that's difficult, it's a good sign that you need to rethink how you divided things into methods (and what you're doing with global state...which is frowned upon).
I'm sorry I can't be more specific--I'm kind of hand-tied since you didn't post code.