Stacked Bar Chart: Changing appearance of entire bar? - java

I am using achartengine in my Android app to display a stacked bar chart (something similar to this). I use the ChartFactory.getBarChartView to get a GraphicalView object that I then place in my layout.
My objective is to provide touch feedback to the user when one of the stacked bars is touched by the user. I intend to do this by changing some of the UI properties (probably color) of the bar that the user touched. However, I want to designate the entire stacked bar as touched. This is as opposed to designating just the selected section of the bar.
Taking the SalesStackedBarChart example from the demo, I want to designate the entire bar for, say, March as selected (not just the section for March 2008).
I already know how to set up onClickListener on the GraphicalView object and to use the getCurrentSeriesAndPoint() method. However, using this approach, I have been able to only designate the same section on all bars as selected. For example, the 2008 sections on all 12 bars are highlighted.
Question:
How do I change the appearance of all sections in a single stacked bar?
Here's my code. It works as designed (i.e, sets the selected section on all 12 bars to gray), but this is not what I want.
mGraph.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
SeriesSelection seriesSelection = mGraph.getCurrentSeriesAndPoint();
if (seriesSelection == null) {
Toast.makeText(mContext, "No chart element was long pressed",
Toast.LENGTH_SHORT).show();
return false; // no chart element was long pressed, so let
// something
// else handle the event
} else {
SimpleSeriesRenderer renderer = mMultiRenderer.getSeriesRendererAt(seriesSelection.getSeriesIndex());
Toast.makeText(mContext, "Chart element in series index "
+ seriesSelection.getSeriesIndex() + " data point index "
+ seriesSelection.getPointIndex() + " was long pressed",
Toast.LENGTH_SHORT).show();
renderer.setColor(Color.LTGRAY);
return true;
}
}
});

Setting the color of a series will change the colors of all bars in that series.
One potential solution would be to create an extra series containing only the bars you want to highlight as selected. Quite tricky.

Related

JavaFX - ListView Selection and Making Text Appear

This is my first post and I'm still a beginner in Java. The purpose of this program is to create a menu with food items in it and be able to select the items using ListView (which is the variable menu in this case). When I select the food items in the ListView, they are supposed to appear on the right side of the screen showing the text of what is selected (i.e. if Hamburger and Hotdog are selected from ListView, Hamburger and Hotdog appear as text on the right side of the screen). I got some pictures to include too, using ImageView and those images appear just fine without a problem. The problem is when I select from ListView, nothing appears because I'm not sure how to make it appear... I've tried get the index and then setting the text like that, getting the items, etc... I'm just really lost at the moment. I'm just not sure why it's not working because in my head the plan works fine, I get the index and then set that index to the ListView, getting the strings, but it's just not working. What am I doing wrong, or how should I be thinking about solving this?
Edit:
When I try to add the text from this line:
vBox.getChildren().add(foodItemsList[i]);
foodItemsList[i] has the error of
ArrayType expected, instead found
javafx.collections.ObservableList
This is my code:
menu.getSelectionModel().selectedItemProperty().addListener( e -> {
flowPane.getChildren().clear();
for (Integer i : menu.getSelectionModel().getSelectedIndices()) {
flowPane.getChildren().add(foodPics[i]);
}
});
// ### This just displays the current value and the value I last selected, if I selected 3+ values,
// the last 2 are the only ones that show.
menu.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
item1.setText(newValue);
item2.setText(oldValue);
}
});
menu.getSelectionModel().selectedItemProperty().addListener( e -> {
flowPane.getChildren().clear();
for (String i : menu.getSelectionModel().getSelectedItems()) {
vBox.getChildren().add(foodItemsList[i]);
}
});

MouseEvents inside JList objects

I am a bit confused regarding a situation I have. I created a ListModel extending DefaultListModel and ListRenderer implementing ListCellRenderer for displaying a custom cell in a JList. The cells are some objects created from a class extending JPanel, that contain a JLabel and a JButton.
My issue is related to the mouse events: I want to trigger a certain event when clicking on the JButton inside a cell of the JList, yet I can not figure out how to match the mouse source point to that of the JButton from the respective index. More exactly, I added a mouse listener to the list, but I want it to trigger something if the mouse point is located inside the bounds of the JButton, and another action if it's on the data item. I added some prints to find out the cause of this, but before that some code to highlight the structure:
public WifiGuiHandler(JButton reference) {
btnReference = reference;
wifiListener = new WifiListener();
wifiPopupContainer = new JScrollPopupMenu("Connections.");
wifiPopupContainer.setMaximumVisibleRows(7);
connectionsHolder = new ArrayList<>();
listOfConnections = new JList();
listOfConnectionsModel = new ListModel(connectionsHolder);
listOfConnectionsRenderer = new ListRenderer();
listOfConnections.setModel(listOfConnectionsModel);
listOfConnections.setCellRenderer(listOfConnectionsRenderer);
wifiPopupContainer.add(listOfConnections);
wifiPopupContainer.pack();
initializeTestVariables();
initializeListeners();
}
Here, the constructor for the class that takes a JButton and adds a mouse listener to it, that triggers the appearance of a JPopupMenu, which has only one component, the JList that hold the entire data. Also, links the ArrayList with the data items to the ListModel.
public void initializeTestVariables() {
for (int i = 0; i <= 10; i++) {
WifiItem item = new WifiItem("Connection number " + i + ".", i);
connectionsHolder.add(item);
}
}
Setting up the data items.
public void initializeListeners() {
listOfConnections.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int index = listOfConnections.locationToIndex(e.getPoint());
if (index >= 0) {
WifiItem item = (WifiItem) ((ListModel) listOfConnections.getModel()).getElementAt(index);
System.out.println("Button of " + item.getConnectionName() + " is at location :" + item.getButton().getLocation());
System.out.println("Button has the bounds : " + item.getButton().getBounds());
System.out.println("MouseEvent detected on : " + e.getPoint().getLocation());
if (item.getButton().getBounds().contains(e.getPoint())) {
item.connectHere();
}
if (item.getButton().isVisible()) {
System.out.println("Set expanded on : " + item.getConnectionName());
item.setExpandedState(false);
listOfConnectionsModel.fireContentsChanged(item, index, index);
updateGui(false);
} else {
System.out.println("Set expanded on : " + item.getConnectionName());
listOfConnectionsModel.fireContentsChanged(item, index, index);
item.setExpandedState(true);
updateGui(false);
}
}
}
});
btnReference.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
updateGui(true);
}
});
}
And this is where the confusion arises. I correctly get the data item( WifiItem) from the mouse event location/point, but when I click on the JButton of the WifiItem, it doesn't trigger that method, like it doesn't seem to detect that the JButton actually is there. I also set up the prints, and what is strange, the Point for the JButton is always the same, even though it actually is different, and this seems to be the problem. More exactly, from the output of the program:
Button of Connection number 2. is at location :java.awt.Point[x=137,y=33]
Button has the bounds : java.awt.Rectangle[x=137,y=33,width=90,height=26]
MouseEvent detected on : java.awt.Point[x=172,y=125]
Button of Connection number 3. is at location :java.awt.Point[x=137,y=33]
Button has the bounds : java.awt.Rectangle[x=137,y=33,width=90,height=26]
MouseEvent detected on : java.awt.Point[x=172,y=125]
The above mouse events points were actually located on the JButton itself, only it didn't get that. As another strange fact, only if I click the JButton of the FIRST element of the list does it trigger the required mouse action.
Another print revealed that all the JButtons have the same Point and Rectangle, and I don't get it. There are 10 items in the JList, each displayed properly, how can all their JButtons have the same location? I must be missing some key element here. I looked at other posts and tried other recommendations: converting the point with SwingUtilities, removing all the mouse listeners from the JList and adding them to the data items.
To sum it up,the issue is that the list triggers the events for the correct data item in it(meaning, I do get the correct index for the item located there), but if the mouse event happens on the JButton of any data item inside the list, it doesn't trigger the required effect (the point is not withing the bounds of the button, even though it should be).
More exactly, I added a mouse listener for the list, but I want it to trigger something if the mouse point is located inside the bounds of the JButton, and another action if it's on the data item.
An easier solution would be to use a JTable. The data is separated into columns and the JTable has an API to let you know which row/column was selected.
You can use the Table Button Column as your renderer/editor for the button.
Edit:
only if I click the JButton of the FIRST element of the list does it trigger the required mouse action
Sounds like your conversion of the mouse point is off.
, how can all their JButtons have the same location?
Again, the button location is releative to the renderer panel. The panel itself is relative to the row in the JList. So I would guess you need to need the row index and add the height of each of the previous rows to your calculation.

How to Hide and show Items using a toggle button in android studio

I'm trying to display 4 charts on a single activity. I want to give the user the option of choosing what kind of graph to show by providing the toggle button.
E.g.:
These are the following graphs which show energy consumption:
Elec Bar Graph
Elec Line Chart
Gas Bar Graph
Gas Line Chart
There are two toggle buttons, one for electricity and one for Gas. When clicking on the electricity toggle button, you should be able to switch between bar graph and line chart only for electricity. Same thing is applied for the gas button.
Problem: After clicking on the Electricity Toggle Button to see line chart for electricity and then clicking on the Gas Toggle Button to see line chart for gas consumption the output is: two line charts for both electricity and gas, whereas it should just show the line chart for gas consumption upon clicking the gas toggle button.
This is a brief snippet of the code:
switch (v.getId()) {
case R.id.electricityButton:
boolean check = ((ToggleButton) v).isChecked();
if (check) {
CreateElectricityLineGraph();
GasLineGraph.setVisibility(View.INVISIBLE);
ElecbarChart.setVisibility(View.INVISIBLE);
ElecLineChart.setVisibility(View.VISIBLE);
else {
CreateElectricityBarGraph();
GasbarChart.setVisibility(View.INVISIBLE);
ElectricityLineChart.setVisibility(View.INVISIBLE);
GasLineChart.setVisibility(View.INVISIBLE);
ElectricitybarChart.setVisibility(View.VISIBLE);
System.out.println("Elec Bar Chart Now Visible");
}
break;
case R.id.GasButton:
boolean c = ((ToggleButton) v).isChecked();
if (c) {
ElectricityLineChart.setVisibility(View.INVISIBLE);
CreateGasLineGraph();
ElectricitybarChart.setVisibility(View.INVISIBLE);
GasLineChart2.setVisibility(View.VISIBLE);
System.out.println("Reached the end of if statement 2");
}
else{
CreateGasBarGraph();
ElectricitybarChart.setVisibility(View.INVISIBLE);
ElectricityLineChart.setVisibility(View.INVISIBLE);
GasLineChart2.setVisibility(View.INVISIBLE);
GasbarChart.setVisibility(View.VISIBLE);
System.out.println("The Gas Bar graph has been made visible");
}
break;
Please help me.
This is due to GasLineChart and GasLineChart2 both are visible in checked condition. you have not make GasLineChart invisible in any condition and also make GasLineChart2 visible on 2nd Condition

edit text Typeface android

I want to change the Text style on a button click. When the user clicks the button it makes the selected area italic. When the user clicks it again I want the selected area to become non italic. How is this possible. This is my code:
if (id == R.id.italic) {
int startSelection = noteContent.getSelectionStart();
int endSelection = noteContent.getSelectionEnd();
Spannable spannable = noteContent.getText();
StyleSpan[] spans = spannable.getSpans(startSelection, endSelection, StyleSpan.class);
if (spans.length == 0 ) {
spannable.setSpan(new StyleSpan(Typeface.ITALIC), startSelection, endSelection , 0);
} else {
StyleSpanRemover spanRemover = new StyleSpanRemover();
spanRemover.RemoveStyle(spannable, startSelection, endSelection, Typeface.ITALIC);
}
}
When I run this code the selected area becomes Italic on the button click. Then if I were to click the button again the same selected area would become un italic. Sounds like it works fine. But it does not. For some reason if I were to take the same selected area and re italicize it it will not become italic. This is because spans.length is still set to 1. It did not go back to zero when I made the Italicized text normal. Any idea on how to set spans.length back to 0?

GWT - Google visualization problems using layout panels?

I'm having troubles in my GWT app with a Google Visualization chart not showing up until after the user has some sort of interaction with the window (e.g. moves the mouse across the screen or presses a button). This would be fine except that the chart is suppose to show up as the first thing the user sees and since it's meant to be seen on a mobile device, it's likely they will not see the chart because their first interaction will be clicking a button that hides the chart to show other information.
Using the "Getting started tutorial" over at the Visualization code's page, the chart loads immediately fine (once some slight changes are made the fix the problems from the slightly out of date tutorial). After some trial and error to find where the difference between my code and the example code that was causing the problem, I found that it's happening because my code is using the newer layout panels instead of just regular panels in GWT.
The below code is the working tutorial code changed so that it uses a RootLayoutPanel.get() instead of a RootPanel.get(). With this, the chart doesn't load until you click to reload the page, then you can see the chart for an instant before the page reloads. This should be easily tested with the below code. To get the chart to show up for the entire time, simply change RootLayoutPanel.get() to RootPanel.get().
Something in my app is allowing the chart to load after user interaction (I'm not sure what). However, the layout panel is certainly the problem as if I change it to a regular panel it works fine. Unfortunately, my entire app is built using layout panels.
What's going on and how might I be able to make the chart show up from the start using layout panels? Thank you much!
package com.test.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.Selection;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.events.SelectHandler;
import com.google.gwt.visualization.client.visualizations.corechart.PieChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;
public class SimpleViz implements EntryPoint {
public void onModuleLoad() {
// Create a callback to be called when the visualization API
// has been loaded.
Runnable onLoadCallback = new Runnable() {
public void run() {
LayoutPanel panel = RootLayoutPanel.get();
// Create a pie chart visualization.
PieChart pie = new PieChart(createTable(), createOptions());
pie.addSelectHandler(createSelectHandler(pie));
panel.add(pie);
}
};
// Load the visualization api, passing the onLoadCallback to be called
// when loading is done.
VisualizationUtils.loadVisualizationApi(onLoadCallback, PieChart.PACKAGE);
}
private Options createOptions() {
Options options = Options.create();
options.setWidth(400);
options.setHeight(240);
options.setTitle("My Daily Activities");
return options;
}
private SelectHandler createSelectHandler(final PieChart chart) {
return new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
String message = "";
// May be multiple selections.
JsArray<Selection> selections = chart.getSelections();
for (int i = 0; i < selections.length(); i++) {
// add a new line for each selection
message += i == 0 ? "" : "\n";
Selection selection = selections.get(i);
if (selection.isCell()) {
// isCell() returns true if a cell has been selected.
// getRow() returns the row number of the selected cell.
int row = selection.getRow();
// getColumn() returns the column number of the selected cell.
int column = selection.getColumn();
message += "cell " + row + ":" + column + " selected";
} else if (selection.isRow()) {
// isRow() returns true if an entire row has been selected.
// getRow() returns the row number of the selected row.
int row = selection.getRow();
message += "row " + row + " selected";
} else {
// unreachable
message += "Pie chart selections should be either row selections or cell selections.";
message += " Other visualizations support column selections as well.";
}
}
Window.alert(message);
}
};
}
private AbstractDataTable createTable() {
DataTable data = DataTable.create();
data.addColumn(ColumnType.STRING, "Task");
data.addColumn(ColumnType.NUMBER, "Hours per Day");
data.addRows(2);
data.setValue(0, 0, "Work");
data.setValue(0, 1, 14);
data.setValue(1, 0, "Sleep");
data.setValue(1, 1, 10);
return data;
}
}
With the Layout panels the sizing of the widgets is done in JavaScript. When the initial page is loaded the initial sizing is done after everything else is finished. However in your case the pie is added when the library is loaded and that runs after the initial sizing. Therefor your widget isn't sized and won't show up. You need to call panel.forceLayout(); explicitly as the last method in you run method.
The google chart tools definately work with LayoutPanels. I am using it myself.
It's really difficult to say what's wrong but here are a couple of suggestions:
Check with Chrome Dev Tools (Console) if an exception is thrown.
Do you have standard mode enabled. That's important with LayoutPanels (make sure you have <!DOCTYPE html> in your HTML host page
You could try a 3rd party wrapper (supports automatic resizes)

Categories