I'm writing a small program that creates a gui to display the contents of a csv file. I've tried following the outline from the Oracle website (http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#data), but my problem is that the 'getColumnCount' method that is used to build the table can't access the 'headers' variable. Or more likely, it can, but the changes I thought I made to it in the main method did not connect to it. If anyone can shed some light on what's wrong and how to fix it, it'd be much appreciated.
public class MyTableModel implements TableModel {
private String[] headers; //This line.
private Object[][] tableData;
public static void main(String[] args) {
String fileName = "products.csv";
String[] csvList = readCSV(fileName);
String[] headers = Arrays.copyOfRange(csvList, 0, 10); //Or maybe this line isn't changing the one above.
}
private static String[] readCSV(String file) {
//Some code to fill the list.
return fileString;
}
#Override
public int getColumnCount() {
return headers.length; //<<This line of code
}
}
#Hovercraft Full Of Eels
Oh, I should have mentioned. I'm implementing this class like this, which is to say, I'm calling it from elsewhere.
private static void createGUI() {
csvTabler table = new csvTabler();
table.setTitle("CSV Table");
table.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table.createJTable();
table.pack();
table.setVisible(true);
}
private void createJTable() {
jTable = new JTable(new MyTableModel());
}
I'm sure this affects your solution but I'm not sure how to adjust..
String[] headers = Arrays.copyOfRange(csvList, 0, 10); //Or maybe this line isn't changing the one above.
Yep, that's it in a nutshell .... you're trying to change an instance field from a static method and are also shadowing the variable to boot, and that just won't work. Understand that the headers variable declared within the main method is local to this method -- visible only within the method -- and so changes to it will have absolutely no effect on the headers instance field in the class. Instead create a constructor and pass the header data in when you need to pass it into the class.
A bad idea is to make headers static -- just don't do this as this throws out the OOPs baby with the bathwater, essentially fixing your problem with a kludge rather than making a much cleaner more fundamental improvement to your program.
For example:
public class MyTableModel implements TableModel {
private String[] headers; //This line.
private Object[][] tableData;
public MyTableModel(String[] headers, Object[][] tableData) {
this.headers = headers;
this.tableData = tableData;
}
#Override
public int getColumnCount() {
return headers.length; //<<This line of code
}
public static void main(String[] args) {
String fileName = "products.csv";
String[] csvList = readCSV(fileName);
String[] headers = Arrays.copyOfRange(csvList, 0, 10);
Object[][] tableData = ..MyTableModel.. // code to create this
// now create a table model with your data and use it.
MyTableModel myTableModel = new MyTableModel(headers, tableData);
}
private static String[] readCSV(String file) {
String fileString = "";
//Some code to fill the list.
return fileString;
}
}
Other issues: You should almost never implement TableModel but rather extend either DefaultTableModel or AbstractTableModel. Otherwise your model will miss most of the necessary machinery to make it work.
Regarding:
What if I made the instance field static as well? But assuming that no such easy option exists. Do I do away with my main() method? I suspected that a constructor would be better, but the main method was helpful for testing at first, and I was getting a lot of errors with the constructor I tried to build.
Again, avoid statics as this increases connectedness of your code, its "coupling" without benefit which greatly increases your risk of hard to find bugs as your program grows.
Regarding, "do I do away with my main method" -- but of course your program will need a main method somewhere, so you already know the answer to this. The main method should be small and should serve only to set the pieces of the application in motion, and nothing more.
regarding "I suspected that a constructor would be better, but the main method was helpful for testing at first, and I was getting a lot of errors with the constructor I tried to build." -- a constructor is necessary, the main method and the constructor are no mutually exclusive, and as for errors -- fix them, one at a time.
Related
I decided to split the last part of that question here into a new question here: https://softwareengineering.stackexchange.com/questions/411738/extension-of-classes-where-to-put-behaviour-how-much-direct-access-is-allowe
If i have a lib and i want to use it, i wrote mostly a own class. This class has one method. In that there is the code how to instantiate the lib/framework. Sometimes there are a few more methods, with them i not only instantiate the class but use it. For example if i want to start a http-server i have there a start-method.
class Container
{
TheLib theLib;
public void init() //or a constructor
{
//some init of the theLib
}
public void start() //
{
theLib.doSomething(...)
theLib.doSomethingmore(...);
theLib.start(...);
}
//important!
public TheLib getTheLib()
{
return this.theLib; //after i started configured it and so on, i want of course use all methods,
which the lib have in some other parts in my application
}
}
But it seems not to be the best solution.
Are there any better solutions, that OO is?
Often i also use only one method, a own class for this seems to be here a big overhead?
Exposing the lib breaks encapsulation? Tell-Dont-Ask is also violated?
Everything depend on what you actually need or how you have access to your 'the lib' instance.
public class Container {
private TheLib theLib;
/* #1: Do you already created the instance before? */
public Container(TheLib theLib) {
this.theLib = theLib;
}
/* #2: Do you need to created the instance each time? */
public Container() {
this.theLib = new TheLib();
}
public void start() {
theLib.doSomething(...)
theLib.doSomethingmore(...);
theLib.start(...);
}
public TheLib getTheLib() {
return this.theLib;
}
public static void main(String[] args) {
/* #1 */
TheLib theLib = ...;
Container container = new Container(theLib);
/* #2 */
Container container = new Container();
/* Continue the flow of your program */
container.start();
container.getTheLib().doSomethingEvenMore();
}
}
Or maybe you actually need only one instance of your 'Container' class. In this case, you should look on how to make a singleton: Java Singleton and Synchronization
Anwser: Often i also use only one method, a own class for this seems to be here a big overhead?
Well, in Java, you cannot do formal programming like in C, so everything line of code that you write, or will be using, has to be in a class of some sort.
If your piece of code is small and don't really need an object, static function might do the work.
Hello i am trying to familiarize myself with Java by doing a very simple "bankaccount" application and it doesn't even save to db or something so it resets all data on rerun.
The problem i am trying to find a good way of doing is that i have an ArrayList of accounts that i want to be able to access from any class so that during runtime for example after an deposit if i access that account later when i want to get balance i get an that account from the ArrayList and it is updated to the deposit value.
When googling i found this solution but i dont like it since it uses static ArrayList. is there any more elegant way than this for an applicaiton that only saves the state/data during runtime.
Simple class that adds the test accounts and so on where first value is acountId and second is balance
public class AccountsModel {
private ArrayList<AccountModel> listOfAccounts;
public AccountsModel() {
listOfAccounts = new ArrayList<AccountModel>();
listOfAccounts.add(new AccountModel(1,0));
listOfAccounts.add(new AccountModel(2,0));
listOfAccounts.add(new AccountModel(3,0));
listOfAccounts.add(new AccountModel(4,0));
}
public ArrayList<AccountModel> getListOfAccounts(){
return listOfAccounts;
}
}
Then in my main class i just do this
static AccountsModel accounts = new AccountsModel();
public static ArrayList<AccountModel> listOfAccounts = accounts.getListOfAccounts();
this "works" as i can get the same list from anywhere within the application. But is there any simple and elegant way of doing this some other way?
You said you dislike the static solution but to me "It needs to be accessed by many classes" screams static variables.
Basically, you create a wrapper for your ArrayList which carries out operations:
class AccountsModel {
private static ArrayList<AccountModel> singleton;
// a static constructor also wouldn't be a bad idea here
public static void init() {
/* add a bunch of AccountModels here*/
}
public static ArrayList<AccountModel> getAccounts() {
return singleton;
}
}
An example of a main method:
public static void main(String[] args) {
ArrayList<AccountModel> accounts = AccountModels.getAccounts();
}
I'm learning to code and currently I'm trying to clean up my massive code by finally learning classes. I'm telling you this just to give a heads-up my terminology might still be off :) :)
The situation
My code works with "layers" that will be drawn on top of each other
There are two types of layers: video layers and image layers.
Both types of layers are child from parent class "Layer"
They need to be run by creation order
The goal
I want to run a code for each item/object of the class.
current code
import java.util.*;
public class main {
public static void main(String[] args){
// defining the objects
LayerVideo item01 = new LayerVideo();
item01.path = "import/01/";
LayerVideo item02 = new LayerVideo();
item02.path = "import/02/";
LayerImage item03 = new LayerImage();
item03.path = "import/03/";
// here is the main goal:
// to run/call each object from class "Layer"
// "allLayers" does not exist, but that's what I don't know how to do.
allLayers.forEach( item ->{
System.out.println( item.path );
// expected result in console:
// import/01/
// import/02/
// import/03/
});
}
public static class Layer {
}
public static class LayerVideo extends Layer {
public String path;
}
public static class LayerImage extends Layer {
public String path;
}
}
Thoughts
How to get all excising objects from a class
If I have them, how to ID them?, by var name?
Could I sort/filter the objects in a loop?
Two things:
consider to make your classes top level ones. So don't go public static class LayerVideo inside your Main class. If they are that important, the classes should each go into their own java file.
then learn about Java collections to organized object instances. You could define use an ArrayList for example.
Beyond that, the point is probably: if you want common things for two different classes, then your base class needs to have that, like:
public abstract class Layer {
private String path;
public String getPath() { return path; }
public void setPath(String newPath) { path = newPath; }
and then your subclasses simply inherit that behavior.
Then, you simply can add objects with that extend that base type to a collection:
List<Layer> layers = new ArrayList<>();
Layer layer = new VideoLayer();
layers.add(layer);
So, with the help and pointers of #GhostCat I've came to the following working code:
main.java
public class main {
public static void main(String[] args){
// debug to see amount of elements in list
System.out.println( settings.layers.size() );
// Aggregate with .forEach(), but will switch to .stream() to also be able to filter
settings.layers.forEach( layer -> {
System.out.println( layer.path );
// do stuff
});
}
}
settings.java
import java.util.ArrayList;
import java.util.List;
public class settings extends main{
public static List<Layer> layers = new ArrayList<>();
static {
layers.add( new LayerImage(true, "input/01/", new int[] {255,255,255} ) );
layers.add( new LayerImage(false, "input/02/", new int[] {255,0,0} ) );
layers.add( new LayerVideo(true, "input/03/", new int[] {0,0,255} ) );
}
}
Layer.java
public abstract class Layer {
boolean run;
String path;
int[] color;
public Layer(boolean startRun, String startPath, int[] startColor) {
run = startRun;
path = startPath;
color = startColor;
}
}
LayerImage.java
public class LayerImage extends Layer {
public LayerImage( boolean startRun, String startPath, int[] startColor) {
super( startRun, startPath, startColor) ;
}
}
LayerVideo.java
public class LayerVideo extends Layer {
public LayerVideo( boolean startRun, String startPath, int[] startColor) {
super( startRun, startPath, startColor) ;
}
}
In the main.java I'll swap the aggregator .forEach() with .stream() later on. Sounds more flexible and to be able to filter the results in advance seems like a big advantage. (then I can also use the item.run to see if I want to run this layer).
Why is there a settings class? I want to be able to have ALL the settings and variables to set for the outcome in one file. This way I can (I think) quickly use different setting files. Maybe also change it to XML input later. Use a GUI or whatever. (You might think "ah, sweet summer child", I'll cross that bridge when I get there).
The Layer SuperClass will have around the 10 parameters/arguments in the constructor when finished. Feels a lot to change and maintaining for the SubClasses by passing it with super(); And later on make changes. What is I will have around, say, 20 SubClasses. Is there a more efficient way?
Any other pointers on what I can do better in this code above?
All in all a LOT learned today! Thanks everyone and special thanks to #GhostCat
I personally create an static ArrayList from the object for every class and add the objects to it in the constructor (with list.add(this)).
Like:
public class Layer{
static ArrayList<Layer> layerList = new ArrayList<>();
public Layer() {
layerList.add(this);
}
}
I have a very simple Java JTable question.
I am creating this class to make things easier in the rest of my application. I receive an error when running it. I know what the errors mean, but have no idea what else to try.
You'll see in the code what I am trying to accomplish:
My Class:
import javax.swing.*;
public class CPTable extends JScrollPane
{
private JTable table;
CPTable(Object [] headers, Object [][] data)
{
table = new JTable(data, headers);
this = new JScrollPane(table);//The line I can't figure out.
}
}
My errors: (an obvious one)
cannot assign a value to final variable this
this = new JScrollPane(table);
and
incompatible types
found : javax.swing.JScrollPane
required: CPTable
Try this:
private CPTable(JTable table) {
super(table);
this.table = table;
}
public CPTable(Object[] headers, Object[][] data) {
this(new JTable(data, headers));
}
You cannot reassign this, but you can cause the correct superclass constructor to be called by using super (which must be the first statement in your constructor).
The this statement is called "constructor delegation"---it chains through to the other constructor so that you can pass the table to the superclass as well as assign it to your table field.
I'm using netbeans to program something with a user interface...
I hava a main class that named "NewJFrame.java"(A) and one more class
that named "NewClass.java"(B). Class A is extended to class B like this:
public class NewClass extends NewJFrame{
...
}
Contents of ClassA are public static like this:
public static javax.swing.JTextField TextBox1;
I also has a button in classA .So when I click the button, it will call a function
from the classB and that function needs to edit TextBox1's text...
Here is whats going on when I click the button:
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String Str1;
NewClass nc = new NewClass();
Str1=nc.call();
}
Here is the funcion in ClassB:
public String call()
{
String Str;
Str = TextBox1.getText();
TextBox1.setText(Str + "1"); //This part isn't work.
JOptionPane.showConfirmDialog(null,Str,"22222222",JOptionPane.PLAIN_MESSAGE);
return Str;
}
So I can read the text of TextBox1 and show it in a messagebox but cannot edit his text.
If I put this code in main class it works perfectly but in another class it doesn't work.
Can someone help me to reslove this problem?
(I'm using netbeans 6.9.1)
I Just Trying to use some another class to add my code because I dont want all the codes stay in same file this is not usefull... Come on someone needs to know how to do that you can't be writing all the codes in a *.java file right?
The problem you are facing has nothing to do with NetBeans IDE,
you will face the same problem with any IDE for this code.
One way of achieving this is by aggregating the NewJFrame class in the NewClass
instead of extending it:
Let me exlplain with some code:
public class NewClass {
private NewJFrame frame = null;
public NewClass(NewJFrame frame) {
this.frame = frame;
}
public String call()
{
String text;
text = frame.TextBox1.getText();
frame.TextBox1.setText(text + "1"); //This will work now.
JOptionPane.showConfirmDialog(null,text,"22222222",JOptionPane.PLAIN_MESSAGE);
return text;
}
}
Here we will receive a reference to the calling JFrame class and will use fields
defined in that class.
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String Str1;
NewClass nc = new NewClass(this); // see the parameter we are passing here
Str1=nc.call();
}
When we create an object of class NewClass we will pass the reference of the
currently calling NewJFrame object
This will work check it.
Now coming to why your code is not working. When NewClass is extending NewJFrame
and when you create a new object of NewClass class it contains a separate
copy of the NewJFrame which is different from the calling NewJFrame reference hence
the field is getting set in another JFrame and not what you wanted.
with regards
Tushar Joshi, Nagpur
AFAIK Netbeans prevents you from editing by hand GUI's and behaves diferrently depending on strange issues like the one you have... but it was months ago, I dont know if current version sucks that much yet.
I really don't understand why you are forcing yourself to use a new class for this? Even if you NEED to, I don't understand why NewClass extends NewJFrame since you are only creating an instance to call a method that has nothing to do with GUI.
I think creating NewClass isn't necessary. Writing all the code in one class isn't bad by itself. This really depends on MANY factors: how much is "all the code"? Does it make sense to separate responsibilities? Etc, etc...
So make the JTextField and JButton NOT static and NOT public, and simply do everything in there:
private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String str = TextBox1.getText();
TextBox1.setText(str + "1"); //This part isn't work.
JOptionPane.showConfirmDialog(null,Str,"22222222",JOptionPane.PLAIN_MESSAGE);
}
P.S.: variable names are start in lowercase: String str, not String Str.
I Found a solution. I'm throwing the contents whereever I'll use. Here is an Example:
Main class:
private void formWindowOpened(WindowEvent evt) {
Tab1Codes tc1 = new Tab1Codes();
if(!tc1.LockAll(TabMenu1))
System.exit(1);
tc1.dispose();
}
Another class where I added some of my codes:
public boolean LockAll(javax.swing.JTabbedPane TabMenu){
try
{
TabMenu.setEnabledAt(1, false);
TabMenu.setEnabledAt(2, false);
TabMenu.setEnabledAt(3, false);
TabMenu.setEnabledAt(4, false);
}catch(Exception e)
{
JOptionPane.showConfirmDialog(null, "I can't Lock the tabs!",
"Locking tabs...",
JOptionPane.PLAIN_MESSAGE,
JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
So, I can edit the contents in another class but it's little useless to send every content I want to read and edit.
If someone knows any short way please write here.