Android MP Chart highlightValue not working, throws ArrayIndexOutOfBoundsException - java

I'm playing around with Android MP Chart lib to draw awesome charts.
I'm trying to highlight values on my chart, but it does not puts the highlight to the right place, or throws ArrayIndexOutOfBoundsException.
I've made a little dummy project for it. When user clicks on the next button, the highlight should move to positive direction.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
final int DATA_MAX_COUNT = 30;
List<MyData> list = new ArrayList<>(); ///<Dummy data stored in here
List<Entry> entries = new ArrayList<>(); ///<Entries for MP Chart
int highlightIndex = 0; ///<Chart's data index to be highlighted
CombinedChart combinedChart; ///<I use combined chart because there will be more data sets added later on
Button prevBtn; ///<Button for highlight control
Button nextBtn; ///<Button for highlight control
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
combinedChart = (CombinedChart) findViewById(R.id.chart);
prevBtn = (Button) findViewById(R.id.prev_btn);
prevBtn.setOnClickListener(this);
nextBtn = (Button) findViewById(R.id.next_btn);
nextBtn.setOnClickListener(this);
generateData();
drawChart();
}
#Override
public void onClick(View v) {
//Clicking buttons should move the highlighted value
if (v.equals(prevBtn)) {
if (highlightIndex > 0) {
highlightIndex--;
}
} else if (v.equals(nextBtn)) {
if (highlightIndex + 1 < DATA_MAX_COUNT) {
highlightIndex++;
}
}
//Does not work, throws exception
//combinedChart.highlightValue(new Highlight(highlightIndex, 0, 0));
//Does not work, throws exception
//combinedChart.highlightValue(highlightIndex, 0, false);
//Exception
// java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
// at com.github.mikephil.charting.data.CombinedData.getDataByIndex(CombinedData.java:152)
// at com.github.mikephil.charting.data.CombinedData.getEntryForHighlight(CombinedData.java:183)
// at com.github.mikephil.charting.charts.Chart.highlightValue(Chart.java:635)
// at com.github.mikephil.charting.charts.Chart.highlightValue(Chart.java:613)
//Works, but highlights value on chart with like x=0 and y= 190, wtf?
combinedChart.highlightValue(combinedChart.getHighlighter().getHighlight(highlightIndex, 0));
}
//Generating random data to a list
public void generateData() {
for (int i = 0; i < DATA_MAX_COUNT; i++) {
MyData myData = new MyData(new Random().nextInt(100) + 100);
list.add(myData);
}
}
//Simple func for adding data to entries and drawing chart
private void drawChart() {
CombinedData combinedData = new CombinedData();
for (int i = 0; i < list.size(); i++) {
MyData myData = list.get(i);
entries.add(new Entry(i, myData.getValue(), myData));
}
LineDataSet lineDataSet = new LineDataSet(entries, "My data list");
lineDataSet.setHighLightColor(Color.RED);
lineDataSet.setHighlightLineWidth(3);
LineData lineData = new LineData();
lineData.addDataSet(lineDataSet);
combinedData.setData(lineData);
combinedChart.setData(combinedData);
combinedChart.invalidate();
}
//Dummy data class
public static class MyData {
private int value;
public MyData(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
}
I don't get it why I'm getting
java.lang.ArrayIndexOutOfBoundsException: length=10; index=-1
Because what the hell is -1? and what is 10? There are not a single thing in my code which is 10, and why does any of the chart's functions getting -1?
I'm using
com.github.PhilJay:MPAndroidChart:v3.0.3
Please help if you can.
E D I T:
I've added combinedChart.setOnChartValueSelectedListener(this); to the chart.
With this callback onValueSelected(Entry, Highlight) I can test this thing in another way. It gives a Highlight object. If I does nothing in this callback, the chart draws the highlights well. If I call it programatically with the same X value, it throws the usual exception or draws the highlight to wrong position. (to zero)
See the callback:
#Override
public void onValueSelected(Entry e, Highlight h) {
float x = h.getX();
Log.i("Highlighted", "Actual highlight: " + x);
//Getting the same exception as above
//combinedChart.highlightValue(x, 0, false);
//Does not works, draws to x=0 position with any given x
combinedChart.highlightValue(combinedChart.getHighlighter().getHighlight(x, 0));
}

Here is solution:
Highlight high = new Highlight(highlightIndex, 0, 0);
high.setDataIndex(0);
combinedChart.highlightValue(high, false);
You need to add high.setDataIndex(0); line.
Explaination:
In Highlight constructor first parameter is X value, the value you increase or decrease. Second is index of graph you want to select. Since you have only one, you specify 0 there. Also you should specify it second time high.setDataIndex(0); (otherwise it is treated as -1, bug ! ) and your code will work:

Related

How can be draw marker on linechart using MPAndroidChart:v3.1.0 in android?

I am using MPAndroidChart:v3.1.0 dependency . But I am not able to show marker every point of line chart.
Dependencies this: implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
I am using below listener
enter code here
'''
lineChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
#Override
public void onValueSelected(Entry e, Highlight h) {
IDataSet iDataSet = lineChart.getData().getDataSets().get(h.getDataSetIndex());
Highlight highlight[] = new Highlight[((LineDataSet) iDataSet).getValues().size()];
for (int i = 0; i < ((LineDataSet) iDataSet).getValues().size(); i++) {
Highlight highlight1 = new Highlight(e.getX(), e.getY(), h.getXPx(), h.getYPx(), h.getDataSetIndex(), h.getStackIndex(), h.getAxis());
highlight1.setDataIndex(i);
highlight[i] = highlight1;
}
MarkerView markerView = new CustomMarkerView(TestPerformanceActivity.this, R.layout.custom_markerview, R.color.red);
markerView.setChartView(lineChart);
lineChart.setMarker(markerView);
lineChart.setDrawMarkers(true);
lineChart.highlightValues(highlight);
lineChart.notifyDataSetChanged();
Log.e("LineChartSelection", "onValueSelected");
}
#Override
public void onNothingSelected() {
Log.e("LineChartSelection", "onNothingSelected");
}
});
'''
I am also call these method on LineDataSet
method is: lineDataSet.setHighlightEnabled(true);
lineDataSet.setDrawHighlightIndicators(true);
But I am not able show marker on line chart . For better reference check screenshot which I want to show.
enter image description here

JGraphX new initialization of graph/graphComponent does not work as expected and causes artefacts

Hi I am using JGraphX to build some kind of Java swing based graph editor application. The application in general works fine and as intended under normal
circumstances. In general I have an class called Editor which contains all essential declarations for the graph, as seen in the code example below.
initializing the graph and overriding some of its methods
public class Editor extends JFrame implements Serializable {
Handler handler;
JTabbedPane tabPane;
mxGraphComponent graphComponent;
EntityDataTable dataTable;
protected static mxGraph graph = new mxGraph() {
// Overrides method to disallow edge label editing
public boolean isCellEditable(Object cell) {
if (cell instanceof mxCell) {
mxCell c = (mxCell) cell;
if (c.isEdge()) {
return false;
} else {
return false;
}
}
return false;
}
// Overrides method to disallow edge selection
public boolean isCellSelectable(Object cell)
{
if (model.isEdge(cell))
{
return false;
}
return super.isCellSelectable(cell);
}
// Overrides method to provide a cell label in the display
public String convertValueToString(Object cell) {
if (cell instanceof mxCell) {
Object value = ((mxCell) cell).getValue();
if (value instanceof Element) {
Element elt = (Element) value;
// String tag = elt.getTagName();
String tag = elt.getAttribute("name");
return tag;
}
}
return super.convertValueToString(cell);
}
public String getToolTipForCell(Object cell){
return "Double Click to Edit";
}
};
...
restricts certain undoEvents
protected mxEventSource.mxIEventListener undoHandler = new mxEventSource.mxIEventListener(){
public void invoke(Object source, mxEventObject evt)
{
mxUndoableEdit evt1 = (mxUndoableEdit) evt.getProperty("edit");
List<mxUndoableEdit.mxUndoableChange> changes = evt1.getChanges();
Object[] temp = graph.getSelectionCellsForChanges(changes);
boolean islegal = true;
for (int i = 0; i < temp.length; i++)
{
mxCell cell = (mxCell)temp[i];
String value = cell.getValue().toString();
if (value.equals("subprocess")||value.equals("optional")||value.equals("parallel")||value.equals("synchronous")||value.equals("activating")||value.equals("deactivating")){
//System.out.println("is not legal");
islegal = false;
}
}
for (int i = 0; i < changes.size(); i++){
if (changes.get(i).toString().contains("mxValueChange")){
islegal = false;
}
}
graph.setSelectionCells(graph.getSelectionCellsForChanges(changes));
if (islegal == true){
undoManager.undoableEditHappened((mxUndoableEdit) evt
.getProperty("edit"));
}else{
// System.out.println("illegal undo");
}
}};
...
protected boolean modified = false;
protected mxGraphOutline graphOutline;
protected JPanel actionPane;
mxUndoManager undoManager;
public Editor() {
handler = new Handler(this);
dataTable = new EntityDataTable(handler);
initGUI();
initGraphSettings();
}
public Editor(SaveData saveData) {
handler = new Handler(this);
dataTable = new EntityDataTable(handler);
initGUI();
initGraphSettings();
//erst alle entities erstellen und submitten, dann alle verbindungselemente zu den entities hinzufügen und nochmal submit
//Load entities
ArrayList<DataSaveElement> saveDataList = saveData.getSaveData(); for (int i = 0; i < saveDataList.size(); i++){
System.out.println("Loaded "+saveDataList.get(i).getType()+" "+saveDataList.get(i).getName());
if (saveDataList.get(i).getType().equals("Process")){
ProcessPopUp temp = new ProcessPopUp(handler, this);
temp.setGlobalID(saveDataList.get(i).getGlobalID());
temp.setName(saveDataList.get(i).getName());
temp.setDesc(saveDataList.get(i).getDescription());
temp.setType(saveDataList.get(i).getType());
... a lot of code for rebuilding, some graph settings, the gui etc.
Inside of the initGui() my mxGraphComponent is initialized
graphComponent = new mxGraphComponent(graph);
Since the graph visualization is only one part of the application and other data exists in the background, while saving all data values are stored including the postions for vertices etc. So when loading a save file a fresh application is build from the ground up simply adding all saved data values step by step. When I close the entire java application, start it again and load my saved file there is no problem at all. The problem occures when loading a saved file while the application is still running like e. g.
menuItem = new JMenuItem("Open...",
new ImageIcon("images/middle.gif"));
menuItem.addActionListener(new ActionListener() {
#java.lang.Override
public void actionPerformed(ActionEvent e) {
LoadAndSaveManager manager = new LoadAndSaveManager();
try {
Object o = manager.load(new FileChooser(0).getSelectedFile().getAbsolutePath());
SaveData saveData =(SaveData) o;
Editor editorNew = new Editor(saveData);
new MenuBar(editorNew);
editorNew.setVisible(true);
editor.dispose();
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
menu.add(menuItem);
My menubar is quite basic an gets the editor als parameter. Since a new Editor is created which creates a new mxGraph, as well as a new mxGraphComponent and finally disposes the old editor there should be no interference...at least as far as I know. However, despite having a new Editor instance which has its own new Graph and GraphComponent the old one is still used somehow. As shown in the example images below.
This will be saved and the application is closed completely.
Two nodes and a link for saving:
When starting the application and loading the saved data nothing is wrong.
Next I start a new one and add for example three nodes and two links.
Three nodes and two links:
Now I load the previously saved data. I would expect that the the window closes and a new one with the prevois data pops up. This is not the case. The data is loaded, but the old graph seems still active somehow and all nodes and links are on the graph.
Mixed up data:
If this would be the only problem I could simply clear the graph and add all "loading data" afterwards, however somehow the graphComponent seems to be broken as well. When dragging nodes the links sometimes are disrupted.
Disrupted links:
From my observations so far this seems to fix itself when selecting an area (I think this forces the graphComponent to refresh())
Selecting:
Unfortunately posting the entire code is not that much of an option, so I posted some code I think might be of importance for the problem. If further code is required I will specifically post it afterwards.
I am not sure why this happens and after hours of research I somehow hit a wall and and I am not sure what I am doing wrong. I would really appreciate some advice.
Here is an minimal full code example of the problem regarding the graphComponents interference problem when declaring a new one.
public class Main {
Editor editor;
public Main() {
editor = new Editor();
new MenuBar(editor);
editor.setVisible(true);
}
public static void main(String args[]) {
new Main();
}}
public class Editor extends JFrame {
mxGraphComponent graphComponent;
protected static mxGraph graph = new mxGraph() {
// Overrides method to disallow edge label editing
public boolean isCellEditable(Object cell) {
if (cell instanceof mxCell) {
mxCell c = (mxCell) cell;
if (c.isEdge()) {
return false;
} else {
return false;
}
}
return false;
}
// Overrides method to disallow edge selection
public boolean isCellSelectable(Object cell)
{
if (model.isEdge(cell))
{
return false;
}
return super.isCellSelectable(cell);
}
// Overrides method to provide a cell label in the display
public String convertValueToString(Object cell) {
if (cell instanceof mxCell) {
Object value = ((mxCell) cell).getValue();
if (value instanceof Element) {
Element elt = (Element) value;
// String tag = elt.getTagName();
String tag = elt.getAttribute("name");
return tag;
}
}
return super.convertValueToString(cell);
}
public String getToolTipForCell(Object cell){
return "Double Click to Edit";
}
};
public Editor() {
initGUI();
initGraphSettings();
}
public Editor(ArrayList<SaveDataElement> saveData) {
initGUI();
initGraphSettings();
//Load data
addToGraph(saveData);
}
public void initGUI(){
setExtendedState(JFrame.MAXIMIZED_BOTH);
setSize(new Dimension(1200, 900));
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
graphComponent = new mxGraphComponent(graph);
JPanel graphPanel = new JPanel(new BorderLayout());
graphPanel.add(graphComponent);
add(graphPanel);
}
public void initGraphSettings(){
Map<String, Object> style = graph.getStylesheet().getDefaultEdgeStyle();
style.put(mxConstants.STYLE_ALIGN, true);
style.put(mxConstants.STYLE_EDGE, mxConstants.EDGESTYLE_TOPTOBOTTOM);
graph.setCellsCloneable(false);
graphComponent.setConnectable(false);
graphComponent.getViewport().setBackground(Color.WHITE);
new mxRubberband(graphComponent);
}
public mxGraph getGraph(){
return graph;
}
public void addToGraph(ArrayList<SaveDataElement> saveData){
for (int i = 0; i < saveData.size(); i++) {
String name = saveData.get(i).getName();
int vertPosX = saveData.get(i).getPosX();
int vertPosY = saveData.get(i).getPosY();
new AddGraphNode("node", name, "rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;", vertPosX, vertPosY);
}
Object[] cells = graph.getChildVertices(graph.getDefaultParent());
Object startCell = null;
Object endCell = null;
for (int i = 0; i < saveData.size(); i++){
for (int j = 0; j < cells.length; j++){
if (((mxCell)cells[j]).getAttribute("name").equals(saveData.get(i).getName()))
startCell = cells[j];
for (int k = 0; k < saveData.get(i).getTargets().size(); k++){
if (((mxCell)cells[j]).getAttribute("name").equals(saveData.get(i).getTargets().get(k))){
endCell = cells[j];
new AddGraphLink(startCell, endCell,"Link", "endArrow=classic;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;verticalAlign=top;verticalLabelPosition=bottom'");
}
}
}
}
}}
public class MenuBar extends JMenuBar {
MenuBar(Editor editor){
JMenuBar menuBar = new JMenuBar();
JMenuItem menuItem;
JMenu menu = new JMenu("File");
menuBar.add(menu);
menuItem = new JMenuItem("Add");
menuItem.addActionListener(new ActionListener() {
#java.lang.Override
public void actionPerformed(ActionEvent e) {
//Setting up some data to create nodes and links
ArrayList<SaveDataElement> saveData = new ArrayList<SaveDataElement>();
ArrayList<String> targetsForTestX = new ArrayList<String>();
targetsForTestX.add("Test Y");
targetsForTestX.add("Test Z");
saveData.add(new SaveDataElement("Test X", 200, 300, targetsForTestX));
ArrayList<String> targetsForTestY = new ArrayList<String>();
saveData.add(new SaveDataElement("Test Y", 300, 420, targetsForTestY));
ArrayList<String> targetsForTestZ = new ArrayList<String>();
saveData.add(new SaveDataElement("Test Z", 100, 420, targetsForTestZ));
editor.addToGraph(saveData);
}
});
menu.add(menuItem);
menuItem = new JMenuItem("Load 1");
menuItem.addActionListener(new ActionListener() {
#java.lang.Override
public void actionPerformed(ActionEvent e) {
//Setting up some data to create nodes and links
ArrayList<SaveDataElement> saveData = new ArrayList<SaveDataElement>();
ArrayList<String> targetsForTest1 = new ArrayList<String>();
targetsForTest1.add("Test 2");
saveData.add(new SaveDataElement("Test 1", 40, 40, targetsForTest1));
ArrayList<String> targetsForTest2 = new ArrayList<String>();
saveData.add(new SaveDataElement("Test 2", 200, 40, targetsForTest2));
Editor editorNew = new Editor(saveData);
new MenuBar(editorNew);
editorNew.setVisible(true);
editor.dispose();
}
});
menu.add(menuItem);
editor.setJMenuBar(menuBar);
}}
public class SaveDataElement {
String name;
int posX, posY;
ArrayList<String> targets;
public SaveDataElement(String name, int posX, int posY, ArrayList<String> targets){
this.name = name;
this.posX = posX;
this.posY = posY;
this.targets = targets;
}
public String getName() {
return name;
}
public int getPosX() {
return posX;
}
public int getPosY() {
return posY;
}
public ArrayList<String> getTargets() {
return targets;
}}
public class AddGraphNode extends Editor {
public AddGraphNode(String tag, String name, String style, int vertPosX, int vertPoxY){
this.getGraph().getModel().beginUpdate();
Object parent = this.getGraph().getDefaultParent();
Document doc = mxDomUtils.createDocument();
Element entity = doc.createElement(tag);
entity.setAttribute("name", name);
try
{
Object v1 = this.getGraph().insertVertex(parent, "1",entity, vertPosX, vertPoxY, (int)(name.length()*8) ,
40, style);
}
finally
{
this.getGraph().getModel().endUpdate();
}
}}
public class AddGraphLink extends Editor{
public AddGraphLink(Object v1, Object v2, String relation, String style){
this.getGraph().getModel().beginUpdate();
Object parent = this.getGraph().getDefaultParent();
try
{
this.getGraph().insertEdge(parent, null, relation, v1, v2,style);
}
finally
{
this.getGraph().getModel().endUpdate();
}
}}
When using the the add menu item some nodes and links are added to the graph and with the load 1 menu item a new Editor will be created (creating a new graph and graphComponent). However, the added nodes and links are still present on the new component.
Regarding the visually broken links I mentioned above, this does not occur...I will investigate this further. Despite that this might also be connected with the graphComponent problem.
I see 3 major problems in your code:
Inappropriate use of a static field: protected static mxGraph graph = new mxGraph() {
Inappropriate inheritance: public class AddGraphLink extends Editor {
And again, inappropriate inheritance: class AddGraphNode extends Editor {
By making the graph field static, changes made to one variable will be felt in all variables, and this is the likely cause for your so-called "artifacts". And the reason that you feel that you must make the field static is because since the two classes above are inheriting from Editor (again inappropriately). The solution is obvious:
Make the graph field an instance field, not a static one, and
Don't use inheritance where it doesn't belong. Instead your AddGraphXxxx classes should not extend Editor but rather should have Editor fields within them, one that you can set via the constructor, and one whose methods you can call, something like this, for example:
// protected static mxGraph graph = new mxGraph() { //!! **** NO ****
private mxGraph graph = new mxGraph() { //!! **** YES ****
.....
.....
public class AddGraphNode {
public AddGraphNode(Editor editor, String tag, String name, String style, int vertPosX, int vertPoxY) {
// **** note use of the editor parameter below ****
editor.getGraph().getModel().beginUpdate();
Object parent = editor.getGraph().getDefaultParent();
Document doc = mxDomUtils.createDocument();
Element entity = doc.createElement(tag);
entity.setAttribute("name", name);
try {
// **** same here ****
Object v1 = editor.getGraph().insertVertex(parent, "1", entity, vertPosX, vertPoxY,
(int) (name.length() * 8), 40, style);
} finally {
// **** and the same here ****
editor.getGraph().getModel().endUpdate();
}
}
}
and you would create this instance within Editor by passing in the this parameter:
new AddGraphNode2(this, "node", name,
"rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;",
vertPosX, vertPosY);
You would make simiar changes to the AddGraphLink class.
Side note, please check out the The Use of Multiple JFrames, Good/Bad Practice? to see why swapping JFrames is not the best program design, and how you can change the code to improve its structure and user experience.

How to make a method in a jbutton?

So, i made a button like this
parameter nomor in LoadPlanet and LoadRR is parameter to show some data to textbox.
my code is like this
the button appear correctly, but if i clicked the buttons, all of them show data from the last data which supposed to be data in last button.
-> a result from tblplanet.JmlPlanet() is 8, so the parameter was like LoadPlanet(8), so that every button show 8th data.
my question is how to make the parameter in sequence, so the button can show data correctly? Any ideas?
public void createButton() {
for (i = 0; i < tblplanet.JmlPlanet(); i++) {
tblplanet.draw(i + 1);
planet_name = tblplanet.getNama_planet();
JButton PlanetJButton = new JButton();
PlanetJButton.setBounds(10, 5 + (i * 35), 95, 26);
PlanetJButton.setText(planet_name);
PanelButton.add(PlanetJButton);
PlanetJButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent event) {
for (int i = 0; i < tblplanet.JmlPlanet(); i++) {
nomor = i;
LoadPlanet(nomor);
LoadRR(nomor);
}
}
});
}
}
Create a class which implements ActionListener and takes a parameter (int) of the planet that it represents
public class PlanetActionListener implements ActionListener {
private final int planet;
public PlanetActionListener(int planet) {
this.planet = planet;
}
#Override
public void actionPerformed(ActionEvent e) {
LoadPlanet(planet);
LoadRR(planet);
}
}
Then simply add the ActionListener to your button
PlanetJButton.addActionListener(new PlanetActionListener(i));
Depending on how you code is structured, you may need to make the PlanetActionListener an inner class so it can access the appropriate methods. See Nested Classes for more details

Android GraphView, to add X and Y coordinates, to a graph, using EditTextView

So, I am making a graphing app(Line Graph), using android GraphView.
What I did:
Create a graph view
Create 2 text views(Edit text views that only take numbers), for x
and y coordinates
A button that adds the point(x and y coordinates) to the graph and
updates the new graph.
I'm calling the button via the following function: writecor(View view)--(Write Coordinates to the graph...)
public void writecor(View view)
{
GraphView linegraph = (GraphView)findViewById(R.id.graph);
EditText xc,yc;
int xv,yv;
xc=(EditText)findViewById(R.id.xcor);
yc=(EditText)findViewById(R.id.ycor);
xv=Integer.parseInt(xc.getText().toString());
yv=Integer.parseInt(yc.getText().toString());
line_series = new LineGraphSeries<DataPoint>(generatedata());
line_series.appendData(new DataPoint(xv,yv),true,50);
line_series.resetData(generatedata());
linegraph.addSeries(line_series);
}
where generatedata() --(contains preexisting coordinates) is as follows:
private DataPoint[] generatedata()
{
DataPoint[] values =
{
new DataPoint(1,5),
new DataPoint(2,8),
new DataPoint(4,7),
new DataPoint(7,11)
};
The code is obviously wrong, so can you help me?
Try something like this :
DataPoint[] values;
int size=0;
private void generateData(int x,int y) {
values = new DataPoint[size+1];
DataPoint v = new DataPoint(x, y);
values[size] = v;
}
}
public void writecor(View view)
{
GraphView linegraph = (GraphView)findViewById(R.id.graph);
EditText xc,yc;
int xv,yv;
xc=(EditText)findViewById(R.id.xcor);
yc=(EditText)findViewById(R.id.ycor);
xv=Integer.parseInt(xc.getText().toString());
yv=Integer.parseInt(yc.getText().toString());
generateData(int xv,int yv);
line_series = new LineGraphSeries<DataPoint>(values);
}

getting corresponding filename of image once button pressed

A Set of imagefiles are added to an arraylist(filelist2) of type File.Then an imageview and a button are addded to a vbox,such vboxes are added to a grids of a gripane using a for loop.( number of iterations is equal to size of the filelist2)Once a button is pressed I need to get the corresponding filename of the image within that vbox.
Say I pressed the button contained at (1,1) {i.e row no01 ,col no1} I need to get filename of image at (1,1)
here's a screenshot:
here's my code: FXMLController
File file = new File("D:\\SERVER\\Server Content\\Apps\\icons");
File[] filelist1 = file.listFiles();
ArrayList<File> filelist2 = new ArrayList<>();
for (File file1 : filelist1) {
filelist2.add(file1);
}
btnar = new ArrayList<>();
for (int i = 0; i < filelist2.size(); i++) {
downloadbtn = new Button("Download");
btnar.add(downloadbtn);
final int index=i;
downloadbtn.setId(String.valueOf(index));
downloadbtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
try {
System.out.println("sssss");
downloadbtn.getId();
//System.out.println(filelist2.get(Integer.valueOf(downloadbtn.getId())).getName());
} catch (Exception ex) {
Logger.getLogger(HomeUI_2Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
System.out.println(filelist2.size());
gridpane.setAlignment(Pos.CENTER);
gridpane.setPadding(new Insets(20, 20, 20, 20));
gridpane.setHgap(20);
gridpane.setVgap(20);
ColumnConstraints columnConstraints = new ColumnConstraints();
columnConstraints.setFillWidth(true);
columnConstraints.setHgrow(Priority.ALWAYS);
gridpane.getColumnConstraints().add(columnConstraints);
int imageCol = 0;
int imageRow = 0;
for (int i = 0; i < filelist2.size(); i++) {
System.out.println(filelist2.get(i).getName());
image = new Image(filelist2.get(i).toURI().toString());
pic = new ImageView();
pic.setFitWidth(130);
pic.setFitHeight(130);
pic.setImage(image);
vb = new VBox();
vb.getChildren().addAll(pic, (Button) btnar.get(i));
gridpane.add(vb, imageCol, imageRow);
GridPane.setMargin(pic, new Insets(2, 2, 2, 2));
imageCol++;
// To check if all the 3 images of a row are completed
if (imageCol > 2) {
// Reset Column
imageCol = 0;
// Next Row
imageRow++;
}
}
Why not simply
System.out.println(filelist2.get(index).getName());
?
(Actually, it's not really clear to me why you create filelist2 at all. Why not do
btnar = new ArrayList<>();
for (int i=0; i < filelist1.length; i++) {
downloadbtn = new Button("Download");
btnar.add(downloadbtn);
final int index=i;
downloadbtn.setId(String.valueOf(index));
downloadbtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
try {
System.out.println("sssss");
System.out.println(filelist1[index].getName());
} catch (Exception ex) {
Logger.getLogger(HomeUI_2Controller.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
Use setUserData and getUserData to store and retrieve custom values in Nodes ! Set the fileName as the userdata and on click, retrieve it.
downloadbtn.setUserData(filelist2.get(index).getName());
downloadbtn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
System.out.println(downloadbtn.getUserData());
}
Consider using a java.util.HashMap<Button, File> and calling hashMap.get(actionEvent.getSource()).getName() to get the file name.
I've created a DataButton which can hold some typed data (unlike userData which has the type Object).
You can specify a Renderer to render the data on the button or to render an alternative text, eg. in your case: "Download".
Eg. you could use something like this:
List<Path> pathlist2 = new ArrayList<>();
...
// provide language specific text for "Download"
ResourceBundle myResourceBundle = ...;
...
DownloadRenderer downloadRenderer = new DownloadRenderer(myResourceBundle);
...
// the dafault renderer would set the text property to path.toString()
DataButton<Path> downloadbtn = new DataButton<>(downloadRenderer);
downloadbtn.setData(pathlist2.get(index));
downloadbtn.setOnAction((actionEvent) -> {
Path path = downloadbtn.getData();
...
});
...
private static class DownloadRenderer extends AbstractDataRenderer<Object> {
private final ResourceBundle myResourceBundle;
public DownloadRenderer(final ResourceBundle myResourceBundle) {
this.myResourceBundle = myResourceBundle;
}
#Override
public String getText(Object item) {
return myResourceBundle.getString("downloadbtn.text");
}
}
As you can see, you can work directly with Path objects (which should be preferred to the legacy File objects). You don't have to cast or convert the data.
Note: you could also omit the DownloadRenderer and set the text property directly:
downloadbtn.setData(pathlist2.get(index));
downloadbtn.setText(myResourceBundle.getString("downloadbtn.text"));
But then you have to make sure to call setText always after setData.
The library is Open Source and is available from Maven Central:
<dependency>
<groupId>org.drombler.commons</groupId>
<artifactId>drombler-commons-fx-core</artifactId>
<version>0.4</version>
</dependency>

Categories

Resources